github-issue-tower-defence-management 1.113.0 → 1.114.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 (78) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +2 -2
  3. package/bin/adapter/entry-points/console/consoleReadApi.js +11 -1
  4. package/bin/adapter/entry-points/console/consoleReadApi.js.map +1 -1
  5. package/bin/adapter/entry-points/console/ui-dist/assets/{index-CEJmPNRK.css → index-Blb_xqIx.css} +1 -1
  6. package/bin/adapter/entry-points/console/ui-dist/assets/index-DQyZ8KpG.js +101 -0
  7. package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
  8. package/bin/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.js +36 -27
  9. package/bin/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.js.map +1 -1
  10. package/bin/adapter/repositories/FileSystemSessionRecordReader.js +69 -0
  11. package/bin/adapter/repositories/FileSystemSessionRecordReader.js.map +1 -0
  12. package/bin/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.js +9 -2
  13. package/bin/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.js.map +1 -1
  14. package/bin/domain/usecases/ResolveInteractiveLiveSessionsUseCase.js +15 -0
  15. package/bin/domain/usecases/ResolveInteractiveLiveSessionsUseCase.js.map +1 -1
  16. package/bin/domain/usecases/adapter-interfaces/SessionRecordReader.js +3 -0
  17. package/bin/domain/usecases/adapter-interfaces/SessionRecordReader.js.map +1 -0
  18. package/package.json +1 -1
  19. package/src/adapter/entry-points/console/consoleReadApi.test.ts +82 -0
  20. package/src/adapter/entry-points/console/consoleReadApi.ts +21 -1
  21. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.stories.tsx +16 -0
  22. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.test.tsx +61 -0
  23. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.tsx +59 -5
  24. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.stories.tsx +76 -0
  25. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.test.tsx +56 -0
  26. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.tsx +39 -0
  27. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentList.tsx +4 -0
  28. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.stories.tsx +24 -4
  29. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.test.tsx +13 -3
  30. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.tsx +6 -0
  31. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestDetail.tsx +4 -0
  32. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.test.ts +1 -0
  33. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.ts +1 -0
  34. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleReferenceLink.test.ts +48 -0
  35. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleReferenceLink.ts +39 -0
  36. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +25 -2
  37. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +2 -1
  38. package/src/adapter/entry-points/console/ui/src/features/console/logic/references.test.ts +80 -0
  39. package/src/adapter/entry-points/console/ui/src/features/console/logic/references.ts +44 -0
  40. package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +1 -0
  41. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +1 -0
  42. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +12 -0
  43. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleReferenceLinkContainer.tsx +25 -0
  44. package/src/adapter/entry-points/console/ui/src/features/console/testing/fixtures.ts +40 -0
  45. package/src/adapter/entry-points/console/ui/src/index.css +23 -0
  46. package/src/adapter/entry-points/console/ui-dist/assets/{index-CEJmPNRK.css → index-Blb_xqIx.css} +1 -1
  47. package/src/adapter/entry-points/console/ui-dist/assets/index-DQyZ8KpG.js +101 -0
  48. package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
  49. package/src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.test.ts +107 -26
  50. package/src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts +49 -29
  51. package/src/adapter/repositories/FileSystemSessionRecordReader.test.ts +59 -0
  52. package/src/adapter/repositories/FileSystemSessionRecordReader.ts +31 -0
  53. package/src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.test.ts +51 -0
  54. package/src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts +10 -1
  55. package/src/domain/entities/InteractiveLiveSession.ts +1 -0
  56. package/src/domain/entities/LiveSessionProcessSnapshot.ts +1 -0
  57. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +4 -0
  58. package/src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.test.ts +66 -59
  59. package/src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts +19 -0
  60. package/src/domain/usecases/adapter-interfaces/SessionRecordReader.ts +3 -0
  61. package/types/adapter/entry-points/console/consoleReadApi.d.ts +1 -0
  62. package/types/adapter/entry-points/console/consoleReadApi.d.ts.map +1 -1
  63. package/types/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.d.ts +4 -11
  64. package/types/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.d.ts.map +1 -1
  65. package/types/adapter/repositories/FileSystemSessionRecordReader.d.ts +5 -0
  66. package/types/adapter/repositories/FileSystemSessionRecordReader.d.ts.map +1 -0
  67. package/types/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.d.ts +3 -1
  68. package/types/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.d.ts.map +1 -1
  69. package/types/domain/entities/InteractiveLiveSession.d.ts +1 -0
  70. package/types/domain/entities/InteractiveLiveSession.d.ts.map +1 -1
  71. package/types/domain/entities/LiveSessionProcessSnapshot.d.ts +1 -0
  72. package/types/domain/entities/LiveSessionProcessSnapshot.d.ts.map +1 -1
  73. package/types/domain/usecases/ResolveInteractiveLiveSessionsUseCase.d.ts +1 -0
  74. package/types/domain/usecases/ResolveInteractiveLiveSessionsUseCase.d.ts.map +1 -1
  75. package/types/domain/usecases/adapter-interfaces/SessionRecordReader.d.ts +4 -0
  76. package/types/domain/usecases/adapter-interfaces/SessionRecordReader.d.ts.map +1 -0
  77. package/bin/adapter/entry-points/console/ui-dist/assets/index-DfNrA5uV.js +0 -101
  78. package/src/adapter/entry-points/console/ui-dist/assets/index-DfNrA5uV.js +0 -101
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>TDPM Console</title>
7
- <script type="module" crossorigin src="/assets/index-DfNrA5uV.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-CEJmPNRK.css">
7
+ <script type="module" crossorigin src="/assets/index-DQyZ8KpG.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-Blb_xqIx.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.FileSystemInteractiveLiveSessionTranscriptResolver = void 0;
37
37
  const fs = __importStar(require("fs"));
38
+ const os = __importStar(require("os"));
38
39
  const path = __importStar(require("path"));
39
40
  const modifiedEpochMs = (filePath) => {
40
41
  try {
@@ -45,19 +46,10 @@ const modifiedEpochMs = (filePath) => {
45
46
  return null;
46
47
  }
47
48
  };
48
- /**
49
- * Resolves the real transcript path of an interactive Claude Code session from
50
- * the session id and config directory taken from the session's process
51
- * environment. The transcript lives at
52
- * `<configDir>/projects/<cwd-slug>/<sessionId>.jsonl`; this resolver scans the
53
- * `projects` subdirectories for a file named `<sessionId>.jsonl` and returns the
54
- * most recently modified match. Because resolution is keyed on the process
55
- * session id rather than on a session name or issue URL, a plain-named session
56
- * (for example one named `workbench`) resolves just as well as an issue-url
57
- * named one.
58
- */
49
+ const defaultSharedProjectsDirectory = () => path.join(os.homedir(), '.claude', 'projects');
59
50
  class FileSystemInteractiveLiveSessionTranscriptResolver {
60
- constructor() {
51
+ constructor(sharedProjectsDirectory = defaultSharedProjectsDirectory()) {
52
+ this.sharedProjectsDirectory = sharedProjectsDirectory;
61
53
  this.resolveTranscriptPaths = (sessions) => {
62
54
  const resolved = new Map();
63
55
  for (const session of sessions) {
@@ -69,7 +61,34 @@ class FileSystemInteractiveLiveSessionTranscriptResolver {
69
61
  return resolved;
70
62
  };
71
63
  this.resolveTranscriptPath = (session) => {
72
- const projectsDirectory = path.join(session.configDir, 'projects');
64
+ const projectsDirectories = this.listProjectsDirectories(session.configDir);
65
+ let latestPath = null;
66
+ let latestEpochMs = -Infinity;
67
+ for (const candidateSessionId of session.candidateSessionIds) {
68
+ const fileName = `${candidateSessionId}.jsonl`;
69
+ for (const projectsDirectory of projectsDirectories) {
70
+ for (const candidate of this.listCandidatePaths(projectsDirectory, fileName)) {
71
+ const epochMs = modifiedEpochMs(candidate);
72
+ if (epochMs === null) {
73
+ continue;
74
+ }
75
+ if (epochMs > latestEpochMs) {
76
+ latestEpochMs = epochMs;
77
+ latestPath = candidate;
78
+ }
79
+ }
80
+ }
81
+ }
82
+ return latestPath;
83
+ };
84
+ this.listProjectsDirectories = (configDir) => {
85
+ const perSessionProjectsDirectory = path.join(configDir, 'projects');
86
+ if (perSessionProjectsDirectory === this.sharedProjectsDirectory) {
87
+ return [perSessionProjectsDirectory];
88
+ }
89
+ return [perSessionProjectsDirectory, this.sharedProjectsDirectory];
90
+ };
91
+ this.listCandidatePaths = (projectsDirectory, fileName) => {
73
92
  let projectEntries;
74
93
  try {
75
94
  projectEntries = fs.readdirSync(projectsDirectory, {
@@ -77,26 +96,16 @@ class FileSystemInteractiveLiveSessionTranscriptResolver {
77
96
  });
78
97
  }
79
98
  catch {
80
- return null;
99
+ return [];
81
100
  }
82
- const fileName = `${session.sessionId}.jsonl`;
83
- let latestPath = null;
84
- let latestEpochMs = -Infinity;
101
+ const candidatePaths = [];
85
102
  for (const projectEntry of projectEntries) {
86
103
  if (!projectEntry.isDirectory()) {
87
104
  continue;
88
105
  }
89
- const candidate = path.join(projectsDirectory, projectEntry.name, fileName);
90
- const epochMs = modifiedEpochMs(candidate);
91
- if (epochMs === null) {
92
- continue;
93
- }
94
- if (epochMs > latestEpochMs) {
95
- latestEpochMs = epochMs;
96
- latestPath = candidate;
97
- }
106
+ candidatePaths.push(path.join(projectsDirectory, projectEntry.name, fileName));
98
107
  }
99
- return latestPath;
108
+ return candidatePaths;
100
109
  };
101
110
  }
102
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAI7B,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAiB,EAAE;IAC1D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAa,kDAAkD;IAA/D;QACE,2BAAsB,GAAG,CACvB,QAAkC,EACb,EAAE;YACvB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;gBAC3D,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;oBAC5B,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;QAEM,0BAAqB,GAAG,CAC9B,OAA+B,EAChB,EAAE;YACjB,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACnE,IAAI,cAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,cAAc,GAAG,EAAE,CAAC,WAAW,CAAC,iBAAiB,EAAE;oBACjD,aAAa,EAAE,IAAI;iBACpB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,SAAS,QAAQ,CAAC;YAC9C,IAAI,UAAU,GAAkB,IAAI,CAAC;YACrC,IAAI,aAAa,GAAG,CAAC,QAAQ,CAAC;YAC9B,KAAK,MAAM,YAAY,IAAI,cAAc,EAAE,CAAC;gBAC1C,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC;oBAChC,SAAS;gBACX,CAAC;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,iBAAiB,EACjB,YAAY,CAAC,IAAI,EACjB,QAAQ,CACT,CAAC;gBACF,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;gBAC3C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;oBACrB,SAAS;gBACX,CAAC;gBACD,IAAI,OAAO,GAAG,aAAa,EAAE,CAAC;oBAC5B,aAAa,GAAG,OAAO,CAAC;oBACxB,UAAU,GAAG,SAAS,CAAC;gBACzB,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC;CAAA;AAjDD,gHAiDC"}
1
+ {"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAI7B,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAiB,EAAE;IAC1D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,8BAA8B,GAAG,GAAW,EAAE,CAClD,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAEjD,MAAa,kDAAkD;IAC7D,YACmB,0BAAkC,8BAA8B,EAAE;QAAlE,4BAAuB,GAAvB,uBAAuB,CAA2C;QAGrF,2BAAsB,GAAG,CACvB,QAAkC,EACb,EAAE;YACvB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;gBAC3D,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;oBAC5B,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;QAEM,0BAAqB,GAAG,CAC9B,OAA+B,EAChB,EAAE;YACjB,MAAM,mBAAmB,GAAG,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC5E,IAAI,UAAU,GAAkB,IAAI,CAAC;YACrC,IAAI,aAAa,GAAG,CAAC,QAAQ,CAAC;YAC9B,KAAK,MAAM,kBAAkB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;gBAC7D,MAAM,QAAQ,GAAG,GAAG,kBAAkB,QAAQ,CAAC;gBAC/C,KAAK,MAAM,iBAAiB,IAAI,mBAAmB,EAAE,CAAC;oBACpD,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,kBAAkB,CAC7C,iBAAiB,EACjB,QAAQ,CACT,EAAE,CAAC;wBACF,MAAM,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;wBAC3C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;4BACrB,SAAS;wBACX,CAAC;wBACD,IAAI,OAAO,GAAG,aAAa,EAAE,CAAC;4BAC5B,aAAa,GAAG,OAAO,CAAC;4BACxB,UAAU,GAAG,SAAS,CAAC;wBACzB,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAC;QACpB,CAAC,CAAC;QAEM,4BAAuB,GAAG,CAAC,SAAiB,EAAY,EAAE;YAChE,MAAM,2BAA2B,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACrE,IAAI,2BAA2B,KAAK,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBACjE,OAAO,CAAC,2BAA2B,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,CAAC,2BAA2B,EAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACrE,CAAC,CAAC;QAEM,uBAAkB,GAAG,CAC3B,iBAAyB,EACzB,QAAgB,EACN,EAAE;YACZ,IAAI,cAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,cAAc,GAAG,EAAE,CAAC,WAAW,CAAC,iBAAiB,EAAE;oBACjD,aAAa,EAAE,IAAI;iBACpB,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,KAAK,MAAM,YAAY,IAAI,cAAc,EAAE,CAAC;gBAC1C,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC;oBAChC,SAAS;gBACX,CAAC;gBACD,cAAc,CAAC,IAAI,CACjB,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAC1D,CAAC;YACJ,CAAC;YACD,OAAO,cAAc,CAAC;QACxB,CAAC,CAAC;IAxEC,CAAC;CAyEL;AA5ED,gHA4EC"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FileSystemSessionRecordReader = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const isRecord = (value) => typeof value === 'object' && value !== null;
40
+ class FileSystemSessionRecordReader {
41
+ constructor() {
42
+ this.readCurrentSessionId = (configDir, pid) => {
43
+ const recordPath = path.join(configDir, 'sessions', `${pid}.json`);
44
+ let content;
45
+ try {
46
+ content = fs.readFileSync(recordPath, 'utf8');
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ let parsed;
52
+ try {
53
+ parsed = JSON.parse(content);
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ if (!isRecord(parsed)) {
59
+ return null;
60
+ }
61
+ const sessionId = parsed.sessionId;
62
+ return typeof sessionId === 'string' && sessionId.length > 0
63
+ ? sessionId
64
+ : null;
65
+ };
66
+ }
67
+ }
68
+ exports.FileSystemSessionRecordReader = FileSystemSessionRecordReader;
69
+ //# sourceMappingURL=FileSystemSessionRecordReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileSystemSessionRecordReader.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemSessionRecordReader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAG7B,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE9C,MAAa,6BAA6B;IAA1C;QACE,yBAAoB,GAAG,CAAC,SAAiB,EAAE,GAAW,EAAiB,EAAE;YACvE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;YACnE,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,MAAe,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YACnC,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAC1D,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,IAAI,CAAC;QACX,CAAC,CAAC;IACJ,CAAC;CAAA;AAvBD,sEAuBC"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LocalProcessLiveSessionProcessSnapshotProvider = void 0;
4
+ const FileSystemSessionRecordReader_1 = require("./FileSystemSessionRecordReader");
4
5
  const SESSION_ID_ENV_KEY = 'CLAUDE_CODE_SESSION_ID';
5
6
  const CONFIG_DIR_ENV_KEY = 'CLAUDE_CONFIG_DIR';
6
7
  /**
@@ -11,9 +12,10 @@ const CONFIG_DIR_ENV_KEY = 'CLAUDE_CONFIG_DIR';
11
12
  * pure resolver, so all host access is contained in this adapter.
12
13
  */
13
14
  class LocalProcessLiveSessionProcessSnapshotProvider {
14
- constructor(localCommandRunner, environReader) {
15
+ constructor(localCommandRunner, environReader, sessionRecordReader = new FileSystemSessionRecordReader_1.FileSystemSessionRecordReader()) {
15
16
  this.localCommandRunner = localCommandRunner;
16
17
  this.environReader = environReader;
18
+ this.sessionRecordReader = sessionRecordReader;
17
19
  this.getSnapshot = async () => {
18
20
  const sessionNames = await this.listSessionNames();
19
21
  const sessions = [];
@@ -59,12 +61,17 @@ class LocalProcessLiveSessionProcessSnapshotProvider {
59
61
  const ppid = Number(match[2]);
60
62
  const commandLine = match[3].trim();
61
63
  const environ = this.environReader.readEnviron(pid);
64
+ const configDir = environ?.[CONFIG_DIR_ENV_KEY] ?? null;
65
+ const currentSessionId = configDir === null
66
+ ? null
67
+ : this.sessionRecordReader.readCurrentSessionId(configDir, pid);
62
68
  processes.push({
63
69
  pid,
64
70
  ppid,
65
71
  commandLine,
66
72
  sessionId: environ?.[SESSION_ID_ENV_KEY] ?? null,
67
- configDir: environ?.[CONFIG_DIR_ENV_KEY] ?? null,
73
+ currentSessionId,
74
+ configDir,
68
75
  });
69
76
  }
70
77
  return processes;
@@ -1 +1 @@
1
- {"version":3,"file":"LocalProcessLiveSessionProcessSnapshotProvider.js","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LocalProcessLiveSessionProcessSnapshotProvider.js","sourceRoot":"","sources":["../../../src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts"],"names":[],"mappings":"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"}
@@ -55,11 +55,26 @@ class ResolveInteractiveLiveSessionsUseCase {
55
55
  sessions.push({
56
56
  sessionName: session.sessionName,
57
57
  sessionId: interactiveProcess.sessionId,
58
+ candidateSessionIds: this.collectCandidateSessionIds(interactiveProcess),
58
59
  configDir: interactiveProcess.configDir,
59
60
  });
60
61
  }
61
62
  return sessions;
62
63
  };
64
+ this.collectCandidateSessionIds = (interactiveProcess) => {
65
+ const candidateSessionIds = [];
66
+ const seenSessionIds = new Set();
67
+ for (const sessionId of [
68
+ interactiveProcess.currentSessionId,
69
+ interactiveProcess.sessionId,
70
+ ]) {
71
+ if (sessionId !== null && !seenSessionIds.has(sessionId)) {
72
+ seenSessionIds.add(sessionId);
73
+ candidateSessionIds.push(sessionId);
74
+ }
75
+ }
76
+ return candidateSessionIds;
77
+ };
63
78
  this.findInteractiveProcess = (panePids, processByPid, childrenByPpid) => {
64
79
  const visited = new Set();
65
80
  const queue = [...panePids];
@@ -1 +1 @@
1
- {"version":3,"file":"ResolveInteractiveLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ResolveInteractiveLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=SessionRecordReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionRecordReader.js","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SessionRecordReader.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.113.0",
3
+ "version": "1.114.1",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -1,5 +1,33 @@
1
1
  import { mock } from 'jest-mock-extended';
2
+ import { Issue } from '../../../domain/entities/Issue';
2
3
  import { IssueRepository } from '../../../domain/usecases/adapter-interfaces/IssueRepository';
4
+
5
+ const buildIssueFixture = (title: string): Issue => ({
6
+ nameWithOwner: 'o/r',
7
+ number: 1,
8
+ title,
9
+ state: 'OPEN',
10
+ status: null,
11
+ story: null,
12
+ nextActionDate: null,
13
+ nextActionHour: null,
14
+ estimationMinutes: null,
15
+ dependedIssueUrls: [],
16
+ completionDate50PercentConfidence: null,
17
+ url: 'https://github.com/o/r/issues/1',
18
+ assignees: [],
19
+ labels: [],
20
+ org: 'o',
21
+ repo: 'r',
22
+ body: '',
23
+ itemId: 'itemId',
24
+ isPr: false,
25
+ isInProgress: false,
26
+ isClosed: false,
27
+ createdAt: new Date('2026-01-01T00:00:00Z'),
28
+ author: 'octocat',
29
+ closingIssueReferenceUrls: [],
30
+ });
3
31
  import {
4
32
  ISSUE_TITLE_CACHE_TTL_MS,
5
33
  IssueTitleStateCache,
@@ -241,6 +269,9 @@ describe('consoleReadApi', () => {
241
269
  merged: false,
242
270
  isPullRequest: false,
243
271
  });
272
+ issueRepository.getIssueByUrl.mockResolvedValue(
273
+ buildIssueFixture('Issue title from repository'),
274
+ );
244
275
  const cache = new IssueTitleStateCache(() => 0);
245
276
  const url = 'https://github.com/o/r/issues/1';
246
277
  const first = await handleIssueTitle(issueRepository, cache, url);
@@ -248,12 +279,63 @@ describe('consoleReadApi', () => {
248
279
  state: 'OPEN',
249
280
  merged: false,
250
281
  isPullRequest: false,
282
+ title: 'Issue title from repository',
251
283
  });
252
284
  const second = await handleIssueTitle(issueRepository, cache, url);
253
285
  expect(second.body).toEqual(first.body);
254
286
  expect(issueRepository.getIssueOrPullRequestState).toHaveBeenCalledTimes(
255
287
  1,
256
288
  );
289
+ expect(issueRepository.getIssueByUrl).toHaveBeenCalledTimes(1);
290
+ });
291
+
292
+ it('returns the pull request title from the summary for pull request urls', async () => {
293
+ const issueRepository = mock<IssueRepository>();
294
+ issueRepository.getIssueOrPullRequestState.mockResolvedValue({
295
+ state: 'CLOSED',
296
+ merged: true,
297
+ isPullRequest: true,
298
+ });
299
+ issueRepository.getPullRequestSummary.mockResolvedValue({
300
+ title: 'Pull request title from summary',
301
+ body: 'body',
302
+ additions: 1,
303
+ deletions: 0,
304
+ changedFiles: 1,
305
+ });
306
+ const cache = new IssueTitleStateCache(() => 0);
307
+ const url = 'https://github.com/o/r/pull/2';
308
+ const response = await handleIssueTitle(issueRepository, cache, url);
309
+ expect(response.body).toEqual({
310
+ state: 'CLOSED',
311
+ merged: true,
312
+ isPullRequest: true,
313
+ title: 'Pull request title from summary',
314
+ });
315
+ expect(issueRepository.getPullRequestSummary).toHaveBeenCalledWith(url);
316
+ expect(issueRepository.getIssueByUrl).not.toHaveBeenCalled();
317
+ });
318
+
319
+ it('falls back to an empty title when the title source returns nothing', async () => {
320
+ const issueRepository = mock<IssueRepository>();
321
+ issueRepository.getIssueOrPullRequestState.mockResolvedValue({
322
+ state: 'OPEN',
323
+ merged: false,
324
+ isPullRequest: false,
325
+ });
326
+ issueRepository.getIssueByUrl.mockResolvedValue(null);
327
+ const cache = new IssueTitleStateCache(() => 0);
328
+ const response = await handleIssueTitle(
329
+ issueRepository,
330
+ cache,
331
+ 'https://github.com/o/r/issues/3',
332
+ );
333
+ expect(response.body).toEqual({
334
+ state: 'OPEN',
335
+ merged: false,
336
+ isPullRequest: false,
337
+ title: '',
338
+ });
257
339
  });
258
340
 
259
341
  it('re-fetches a non-merged result after the TTL elapses', async () => {
@@ -12,6 +12,7 @@ export type IssueOrPullRequestState = {
12
12
  state: string;
13
13
  merged: boolean;
14
14
  isPullRequest: boolean;
15
+ title: string;
15
16
  };
16
17
 
17
18
  export type PullRequestStatus = {
@@ -215,6 +216,19 @@ export const handleRelatedPrs = async (
215
216
  return ok({ relatedPullRequests: withSummaries });
216
217
  };
217
218
 
219
+ const resolveIssueOrPullRequestTitle = async (
220
+ issueRepository: IssueRepository,
221
+ url: string,
222
+ isPullRequest: boolean,
223
+ ): Promise<string> => {
224
+ if (isPullRequest) {
225
+ const summary = await issueRepository.getPullRequestSummary(url);
226
+ return summary?.title ?? '';
227
+ }
228
+ const issue = await issueRepository.getIssueByUrl(url);
229
+ return issue?.title ?? '';
230
+ };
231
+
218
232
  export const handleIssueTitle = async (
219
233
  issueRepository: IssueRepository,
220
234
  cache: IssueTitleStateCache,
@@ -227,7 +241,13 @@ export const handleIssueTitle = async (
227
241
  if (cached !== null) {
228
242
  return ok(cached);
229
243
  }
230
- const state = await issueRepository.getIssueOrPullRequestState(url);
244
+ const baseState = await issueRepository.getIssueOrPullRequestState(url);
245
+ const title = await resolveIssueOrPullRequestTitle(
246
+ issueRepository,
247
+ url,
248
+ baseState.isPullRequest,
249
+ );
250
+ const state: IssueOrPullRequestState = { ...baseState, title };
231
251
  cache.set(url, state);
232
252
  return ok(state);
233
253
  };
@@ -4,9 +4,12 @@ import {
4
4
  consoleCodeFenceBodyFixture,
5
5
  consoleMarkdownBodyFixture,
6
6
  consoleMarkdownImageBodyFixture,
7
+ consoleMarkdownReferenceBodyFixture,
7
8
  consoleMermaidBodyFixture,
9
+ consoleReferenceStatesFixture,
8
10
  } from '../../testing/fixtures';
9
11
  import { ConsoleMarkdownContent } from './ConsoleMarkdownContent';
12
+ import { ConsoleReferenceLink } from './ConsoleReferenceLink';
10
13
 
11
14
  const meta: Meta<typeof ConsoleMarkdownContent> = {
12
15
  title: 'Console/ConsoleMarkdownContent',
@@ -37,6 +40,19 @@ export const WithProxiedGitHubImages: Story = {
37
40
  },
38
41
  };
39
42
 
43
+ export const WithDecoratedReferenceLinks: Story = {
44
+ args: {
45
+ body: consoleMarkdownReferenceBodyFixture,
46
+ renderReferenceLink: (href, fallbackText) => (
47
+ <ConsoleReferenceLink
48
+ href={href}
49
+ fallbackText={fallbackText}
50
+ state={consoleReferenceStatesFixture[href] ?? null}
51
+ />
52
+ ),
53
+ },
54
+ };
55
+
40
56
  export const Empty: Story = {
41
57
  args: { body: '' },
42
58
  };
@@ -33,4 +33,65 @@ describe('ConsoleMarkdownContent', () => {
33
33
  ).not.toBeNull();
34
34
  });
35
35
  });
36
+
37
+ it('decorates pull request and issue links via the reference renderer', async () => {
38
+ const body =
39
+ 'See https://github.com/octo/repo/pull/7 and https://github.com/octo/repo/issues/9 for details.';
40
+ const renderReferenceLink = jest.fn((href: string) => (
41
+ <span className="decorated-reference" data-href={href}>
42
+ decorated:{href}
43
+ </span>
44
+ ));
45
+ const { container } = render(
46
+ <ConsoleMarkdownContent
47
+ body={body}
48
+ renderReferenceLink={renderReferenceLink}
49
+ />,
50
+ );
51
+ await waitFor(() => {
52
+ expect(container.querySelectorAll('.decorated-reference').length).toBe(2);
53
+ });
54
+ const decoratedHrefs = Array.from(
55
+ container.querySelectorAll('.decorated-reference'),
56
+ ).map((node) => node.getAttribute('data-href'));
57
+ expect(decoratedHrefs).toEqual([
58
+ 'https://github.com/octo/repo/pull/7',
59
+ 'https://github.com/octo/repo/issues/9',
60
+ ]);
61
+ });
62
+
63
+ it('leaves non-issue links untouched', async () => {
64
+ const body =
65
+ 'Docs at https://example.com/page and source https://github.com/octo/repo/blob/main/file.ts';
66
+ const renderReferenceLink = jest.fn(() => (
67
+ <span className="decorated-reference">decorated</span>
68
+ ));
69
+ const { container } = render(
70
+ <ConsoleMarkdownContent
71
+ body={body}
72
+ renderReferenceLink={renderReferenceLink}
73
+ />,
74
+ );
75
+ await waitFor(() => {
76
+ const anchors = container.querySelectorAll('a[href]');
77
+ expect(anchors.length).toBe(2);
78
+ });
79
+ expect(renderReferenceLink).not.toHaveBeenCalled();
80
+ expect(container.querySelector('.decorated-reference')).toBeNull();
81
+ });
82
+
83
+ it('keeps reference links as plain anchors when no renderer is provided', () => {
84
+ const { container } = render(
85
+ <ConsoleMarkdownContent
86
+ body={'See https://github.com/octo/repo/pull/7 now.'}
87
+ />,
88
+ );
89
+ const anchor = container.querySelector('a[href]');
90
+ expect(anchor?.getAttribute('href')).toBe(
91
+ 'https://github.com/octo/repo/pull/7',
92
+ );
93
+ expect(
94
+ container.querySelector('.console-markdown-reference-host'),
95
+ ).toBeNull();
96
+ });
36
97
  });