github-issue-tower-defence-management 1.151.7 → 1.152.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.
Files changed (46) hide show
  1. package/.github/workflows/api-created_issue_pr.yml +1 -1
  2. package/.github/workflows/ci-failure-issue-creator.yml +1 -1
  3. package/.github/workflows/close-manual-prs.yml +1 -1
  4. package/.github/workflows/commit-lint.yml +1 -1
  5. package/.github/workflows/console-ui.yml +1 -1
  6. package/.github/workflows/create-pr.yml +2 -2
  7. package/.github/workflows/secret-scan.yml +1 -1
  8. package/.github/workflows/test.yml +1 -1
  9. package/.github/workflows/umino-project.yml +2 -2
  10. package/CHANGELOG.md +14 -0
  11. package/bin/adapter/entry-points/console/ui-dist/assets/{index-CGqYXHZV.css → index-lemrqYKZ.css} +1 -1
  12. package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
  13. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +0 -19
  14. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  15. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js +1 -13
  16. package/bin/adapter/entry-points/handlers/inTmuxByHumanDataWriter.js.map +1 -1
  17. package/bin/adapter/repositories/TranscriptOwnerCallStatusProvider.js +0 -41
  18. package/bin/adapter/repositories/TranscriptOwnerCallStatusProvider.js.map +1 -1
  19. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js +2 -21
  20. package/bin/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/adapter/ci/workflowRunCancellation.test.ts +42 -10
  23. package/src/adapter/entry-points/console/ui/src/index.css +0 -7
  24. package/src/adapter/entry-points/console/ui-dist/assets/{index-CGqYXHZV.css → index-lemrqYKZ.css} +1 -1
  25. package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
  26. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +0 -33
  27. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +3 -104
  28. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.ts +0 -19
  29. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.singleScan.test.ts +10 -12
  30. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.test.ts +0 -178
  31. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.ts +0 -61
  32. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +0 -99
  33. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.ts +1 -47
  34. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  35. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts +0 -2
  36. package/types/adapter/entry-points/handlers/inTmuxByHumanDataWriter.d.ts.map +1 -1
  37. package/types/adapter/repositories/TranscriptOwnerCallStatusProvider.d.ts +0 -3
  38. package/types/adapter/repositories/TranscriptOwnerCallStatusProvider.d.ts.map +1 -1
  39. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts +0 -19
  40. package/types/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.d.ts.map +1 -1
  41. package/src/adapter/entry-points/handlers/resolveUnansweredOwnerCalls.test.ts +0 -111
  42. package/src/adapter/entry-points/handlers/resolveUnansweredOwnerCalls.ts +0 -33
  43. package/src/domain/entities/UnansweredOwnerCall.ts +0 -4
  44. package/src/domain/usecases/intmux/UnansweredOwnerCallSessionKeyContract.test.ts +0 -141
  45. /package/bin/adapter/entry-points/console/ui-dist/assets/{index-BjFRJoM1.js → index-DR_LIP9n.js} +0 -0
  46. /package/src/adapter/entry-points/console/ui-dist/assets/{index-BjFRJoM1.js → index-DR_LIP9n.js} +0 -0
@@ -1,111 +0,0 @@
1
- import { resolveUnansweredOwnerCallsByTmuxSessionName } from './resolveUnansweredOwnerCalls';
2
- import { UnansweredOwnerCall } from '../../../domain/entities/UnansweredOwnerCall';
3
- import { InteractiveLiveSession } from '../../../domain/entities/InteractiveLiveSession';
4
- import { LiveSessionProcessSnapshot } from '../../../domain/entities/LiveSessionProcessSnapshot';
5
- import { toTmuxSessionName } from '../../../domain/usecases/intmux/InTmuxByHumanSessionReconcileUseCase';
6
-
7
- const ISSUE_URL = 'https://github.com/demo/repo/issues/1';
8
- const TMUX_SESSION_NAME = toTmuxSessionName(ISSUE_URL);
9
- const CONFIG_DIR = '/home/agent/.claude';
10
- const SESSION_ID = 'session-id-1';
11
-
12
- const snapshotWithSession = (): LiveSessionProcessSnapshot => ({
13
- sessions: [{ sessionName: TMUX_SESSION_NAME, panePids: [100] }],
14
- processes: [
15
- {
16
- pid: 100,
17
- ppid: 1,
18
- commandLine: `claude ${ISSUE_URL}`,
19
- sessionId: SESSION_ID,
20
- currentSessionId: SESSION_ID,
21
- configDir: CONFIG_DIR,
22
- },
23
- ],
24
- });
25
-
26
- describe('resolveUnansweredOwnerCallsByTmuxSessionName', () => {
27
- it('asks the call provider for the transcripts of the live interactive sessions and returns what it reports', async () => {
28
- const call: UnansweredOwnerCall = {
29
- calledAt: '2026-08-13T10:14:00.000Z',
30
- body: 'Please decide whether to merge the release branch',
31
- };
32
- const requestedTranscriptPaths: Map<string, string>[] = [];
33
- const resolvedSessions: InteractiveLiveSession[][] = [];
34
-
35
- const result = await resolveUnansweredOwnerCallsByTmuxSessionName({
36
- liveSessionProcessSnapshotProvider: {
37
- getSnapshot: async () => snapshotWithSession(),
38
- },
39
- interactiveLiveSessionTranscriptResolver: {
40
- resolveTranscriptPaths: (sessions) => {
41
- resolvedSessions.push(sessions);
42
- return new Map(
43
- sessions.map((session) => [
44
- session.sessionName,
45
- `/transcripts/${session.sessionId}.jsonl`,
46
- ]),
47
- );
48
- },
49
- },
50
- unansweredOwnerCallListProvider: {
51
- listUnansweredOwnerCallsBySessionName: async (
52
- transcriptPathBySessionName,
53
- ) => {
54
- requestedTranscriptPaths.push(transcriptPathBySessionName);
55
- return new Map([[TMUX_SESSION_NAME, [call]]]);
56
- },
57
- },
58
- });
59
-
60
- expect(resolvedSessions[0]?.map((session) => session.sessionName)).toEqual([
61
- TMUX_SESSION_NAME,
62
- ]);
63
- expect(requestedTranscriptPaths[0]?.get(TMUX_SESSION_NAME)).toBe(
64
- `/transcripts/${SESSION_ID}.jsonl`,
65
- );
66
- expect(result.get(TMUX_SESSION_NAME)).toEqual([call]);
67
- });
68
-
69
- it('keys the returned calls by the tmux session name the reconciler derives from the issue url', async () => {
70
- const result = await resolveUnansweredOwnerCallsByTmuxSessionName({
71
- liveSessionProcessSnapshotProvider: {
72
- getSnapshot: async () => snapshotWithSession(),
73
- },
74
- interactiveLiveSessionTranscriptResolver: {
75
- resolveTranscriptPaths: (sessions) =>
76
- new Map(
77
- sessions.map((session) => [session.sessionName, '/transcript']),
78
- ),
79
- },
80
- unansweredOwnerCallListProvider: {
81
- listUnansweredOwnerCallsBySessionName: async (
82
- transcriptPathBySessionName,
83
- ) =>
84
- new Map(
85
- [...transcriptPathBySessionName.keys()].map((sessionName) => [
86
- sessionName,
87
- [{ calledAt: '2026-08-13T10:14:00.000Z', body: 'body' }],
88
- ]),
89
- ),
90
- },
91
- });
92
-
93
- expect([...result.keys()]).toEqual([toTmuxSessionName(ISSUE_URL)]);
94
- });
95
-
96
- it('returns nothing when no live session exposes a transcript', async () => {
97
- const result = await resolveUnansweredOwnerCallsByTmuxSessionName({
98
- liveSessionProcessSnapshotProvider: {
99
- getSnapshot: async () => ({ sessions: [], processes: [] }),
100
- },
101
- interactiveLiveSessionTranscriptResolver: {
102
- resolveTranscriptPaths: () => new Map(),
103
- },
104
- unansweredOwnerCallListProvider: {
105
- listUnansweredOwnerCallsBySessionName: async () => new Map(),
106
- },
107
- });
108
-
109
- expect(result.size).toBe(0);
110
- });
111
- });
@@ -1,33 +0,0 @@
1
- import { UnansweredOwnerCall } from '../../../domain/entities/UnansweredOwnerCall';
2
- import { InteractiveLiveSession } from '../../../domain/entities/InteractiveLiveSession';
3
- import { ResolveInteractiveLiveSessionsUseCase } from '../../../domain/usecases/ResolveInteractiveLiveSessionsUseCase';
4
- import { LiveSessionProcessSnapshotProvider } from '../../../domain/usecases/adapter-interfaces/LiveSessionProcessSnapshotProvider';
5
- import { InteractiveLiveSessionTranscriptResolver } from '../../../domain/usecases/adapter-interfaces/InteractiveLiveSessionTranscriptResolver';
6
-
7
- export type UnansweredOwnerCallListProvider = {
8
- listUnansweredOwnerCallsBySessionName: (
9
- transcriptPathBySessionName: Map<string, string>,
10
- ) => Promise<Map<string, UnansweredOwnerCall[]>>;
11
- };
12
-
13
- export type ResolveUnansweredOwnerCallsParams = {
14
- liveSessionProcessSnapshotProvider: LiveSessionProcessSnapshotProvider;
15
- interactiveLiveSessionTranscriptResolver: InteractiveLiveSessionTranscriptResolver;
16
- unansweredOwnerCallListProvider: UnansweredOwnerCallListProvider;
17
- };
18
-
19
- export const resolveUnansweredOwnerCallsByTmuxSessionName = async (
20
- params: ResolveUnansweredOwnerCallsParams,
21
- ): Promise<Map<string, UnansweredOwnerCall[]>> => {
22
- const snapshot =
23
- await params.liveSessionProcessSnapshotProvider.getSnapshot();
24
- const interactiveSessions: InteractiveLiveSession[] =
25
- new ResolveInteractiveLiveSessionsUseCase().resolve(snapshot);
26
- const transcriptPathBySessionName =
27
- params.interactiveLiveSessionTranscriptResolver.resolveTranscriptPaths(
28
- interactiveSessions,
29
- );
30
- return params.unansweredOwnerCallListProvider.listUnansweredOwnerCallsBySessionName(
31
- transcriptPathBySessionName,
32
- );
33
- };
@@ -1,4 +0,0 @@
1
- export type UnansweredOwnerCall = {
2
- calledAt: string;
3
- body: string;
4
- };
@@ -1,141 +0,0 @@
1
- import { Issue } from '../../entities/Issue';
2
- import { IN_TMUX_STATUS_NAME } from '../../entities/WorkflowStatus';
3
- import { FieldOption, Project } from '../../entities/Project';
4
- import { UnansweredOwnerCall } from '../../entities/UnansweredOwnerCall';
5
- import { IssueRepository } from '../adapter-interfaces/IssueRepository';
6
- import { TmuxSessionRepository } from '../adapter-interfaces/TmuxSessionRepository';
7
- import { InTmuxByHumanSessionReconcileUseCase } from './InTmuxByHumanSessionReconcileUseCase';
8
- import { GenerateInTmuxByHumanDataUseCase } from './GenerateInTmuxByHumanDataUseCase';
9
-
10
- const ASSIGNEE = 'owner-login';
11
- const LAUNCHER = 'cl';
12
- const NOW = new Date('2026-06-25T12:00:00.000Z');
13
- const ISSUE_URL = 'https://github.com/demo/repo/issues/1';
14
- const STORY_NAME = 'Story Alpha';
15
-
16
- const fieldOption = (id: string, name: string): FieldOption => ({
17
- id,
18
- name,
19
- color: 'BLUE',
20
- description: '',
21
- });
22
-
23
- const projectWithStory: Project = {
24
- id: 'project-node-id',
25
- url: 'https://github.com/orgs/demo/projects/1',
26
- databaseId: 1,
27
- name: 'demo',
28
- status: {
29
- name: 'Status',
30
- fieldId: 'status-field',
31
- statuses: [fieldOption('st-tmux', IN_TMUX_STATUS_NAME)],
32
- },
33
- nextActionDate: null,
34
- nextActionHour: null,
35
- story: {
36
- name: 'story',
37
- fieldId: 'story-field',
38
- databaseId: 2,
39
- stories: [fieldOption('s1', STORY_NAME)],
40
- workflowManagementStory: { id: 'wm', name: 'workflow management' },
41
- },
42
- remainingEstimationMinutes: null,
43
- dependedIssueUrlSeparatedByComma: null,
44
- completionDate50PercentConfidence: null,
45
- };
46
-
47
- const inTmuxIssue: Issue = {
48
- nameWithOwner: 'demo/repo',
49
- number: 1,
50
- title: 'Issue 1',
51
- state: 'OPEN',
52
- status: IN_TMUX_STATUS_NAME,
53
- story: STORY_NAME,
54
- nextActionDate: null,
55
- nextActionHour: null,
56
- estimationMinutes: null,
57
- dependedIssueUrls: [],
58
- completionDate50PercentConfidence: null,
59
- url: ISSUE_URL,
60
- assignees: [ASSIGNEE],
61
- labels: [],
62
- org: 'demo',
63
- repo: 'repo',
64
- body: '',
65
- itemId: 'item-1',
66
- isPr: false,
67
- isInProgress: false,
68
- isClosed: false,
69
- createdAt: NOW,
70
- author: '',
71
- closingIssueReferenceUrls: [],
72
- };
73
-
74
- const tmuxSessionNameTheReconcilerCreatesFor = async (
75
- issue: Issue,
76
- ): Promise<string> => {
77
- const launchedSessionNames: string[] = [];
78
- const tmuxSessionRepository: TmuxSessionRepository = {
79
- listLiveSessionNames: async () => [],
80
- listLiveSessionsWithActivity: async () => [],
81
- listInteractiveProcessCommandLines: async () => [],
82
- launchDetachedSession: async (sessionName: string) => {
83
- launchedSessionNames.push(sessionName);
84
- },
85
- killSession: async () => undefined,
86
- killOwnSession: async () => undefined,
87
- sendKeys: async () => undefined,
88
- launchBareNameLeaderSession: async () => undefined,
89
- };
90
- const issueStateRepository: Pick<
91
- IssueRepository,
92
- 'getIssueOrPullRequestState'
93
- > = {
94
- getIssueOrPullRequestState: async () => ({
95
- state: 'OPEN',
96
- merged: false,
97
- isPullRequest: false,
98
- title: 'Issue 1',
99
- }),
100
- };
101
-
102
- await new InTmuxByHumanSessionReconcileUseCase(
103
- tmuxSessionRepository,
104
- issueStateRepository,
105
- ).run({
106
- issues: [issue],
107
- assigneeLogin: ASSIGNEE,
108
- launcherCommand: LAUNCHER,
109
- now: NOW,
110
- });
111
-
112
- return launchedSessionNames[0];
113
- };
114
-
115
- describe('unanswered owner call session key contract', () => {
116
- it('reads the calls under the very tmux session name the reconciler creates for that issue', async () => {
117
- const call: UnansweredOwnerCall = {
118
- calledAt: '2026-06-25T11:00:00.000Z',
119
- body: 'Please decide whether to merge the release branch',
120
- };
121
- const sessionNameTheReconcilerCreates =
122
- await tmuxSessionNameTheReconcilerCreatesFor(inTmuxIssue);
123
-
124
- const result = new GenerateInTmuxByHumanDataUseCase().run({
125
- project: projectWithStory,
126
- issues: [inTmuxIssue],
127
- pjcode: 'demo',
128
- assigneeLogin: ASSIGNEE,
129
- org: 'demo',
130
- repo: 'repo',
131
- consoleBaseUrl: 'https://console.example.test',
132
- consoleToken: 'test-token-value',
133
- unansweredCallsByTmuxSessionName: new Map([
134
- [sessionNameTheReconcilerCreates, [call]],
135
- ]),
136
- now: NOW,
137
- });
138
-
139
- expect(result.v5?.groups[0].sessions[0].unansweredCalls).toEqual([call]);
140
- });
141
- });