github-issue-tower-defence-management 1.134.0 → 1.135.0

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 (45) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +5 -4
  3. package/bin/adapter/entry-points/cli/index.js +11 -1
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/cli/projectConfig.js +21 -0
  6. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  7. package/bin/adapter/entry-points/console/dashboardComposeService.js +18 -0
  8. package/bin/adapter/entry-points/console/dashboardComposeService.js.map +1 -1
  9. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +81 -54
  10. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  11. package/bin/adapter/entry-points/handlers/machineStatusWriter.js +6 -0
  12. package/bin/adapter/entry-points/handlers/machineStatusWriter.js.map +1 -1
  13. package/bin/adapter/repositories/ProcHostMetricsRepository.js +4 -0
  14. package/bin/adapter/repositories/ProcHostMetricsRepository.js.map +1 -1
  15. package/bin/domain/usecases/dashboard/ComposeDashboardUseCase.js +26 -4
  16. package/bin/domain/usecases/dashboard/ComposeDashboardUseCase.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/adapter/entry-points/cli/index.test.ts +42 -1
  19. package/src/adapter/entry-points/cli/index.ts +20 -1
  20. package/src/adapter/entry-points/cli/projectConfig.test.ts +75 -0
  21. package/src/adapter/entry-points/cli/projectConfig.ts +31 -0
  22. package/src/adapter/entry-points/console/dashboardComposeService.test.ts +32 -0
  23. package/src/adapter/entry-points/console/dashboardComposeService.ts +20 -0
  24. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +66 -0
  25. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +7 -1
  26. package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +61 -0
  27. package/src/adapter/entry-points/handlers/machineStatusWriter.ts +17 -0
  28. package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +25 -0
  29. package/src/adapter/repositories/ProcHostMetricsRepository.ts +5 -0
  30. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +26 -3
  31. package/src/domain/usecases/dashboard/ComposeDashboardUseCase.test.ts +55 -0
  32. package/src/domain/usecases/dashboard/ComposeDashboardUseCase.ts +34 -5
  33. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  34. package/types/adapter/entry-points/cli/projectConfig.d.ts +5 -0
  35. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  36. package/types/adapter/entry-points/console/dashboardComposeService.d.ts.map +1 -1
  37. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts +1 -1
  38. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  39. package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts +7 -0
  40. package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts.map +1 -1
  41. package/types/adapter/repositories/ProcHostMetricsRepository.d.ts +1 -0
  42. package/types/adapter/repositories/ProcHostMetricsRepository.d.ts.map +1 -1
  43. package/types/domain/usecases/dashboard/ComposeDashboardUseCase.d.ts +6 -1
  44. package/types/domain/usecases/dashboard/ComposeDashboardUseCase.d.ts.map +1 -1
  45. package/types/index.d.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ComposeDashboardUseCase.js","sourceRoot":"","sources":["../../../../src/domain/usecases/dashboard/ComposeDashboardUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ComposeDashboardUseCase.js","sourceRoot":"","sources":["../../../../src/domain/usecases/dashboard/ComposeDashboardUseCase.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.134.0",
3
+ "version": "1.135.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -70,9 +70,10 @@ jest.mock('../../repositories/FetchWebhookRepository', () => ({
70
70
  sendGetRequest: jest.fn(),
71
71
  })),
72
72
  }));
73
+ const mockScheduleHandle = jest.fn().mockResolvedValue(null);
73
74
  jest.mock('../handlers/HandleScheduledEventUseCaseHandler', () => ({
74
75
  HandleScheduledEventUseCaseHandler: jest.fn().mockImplementation(() => ({
75
- handle: jest.fn().mockResolvedValue(null),
76
+ handle: mockScheduleHandle,
76
77
  })),
77
78
  }));
78
79
  jest.mock('../console/ensureConsoleRunning', () => ({
@@ -162,6 +163,46 @@ describe('CLI', () => {
162
163
  expect(program).toBeDefined();
163
164
  });
164
165
 
166
+ describe('schedule --inTmuxProjectOrder', () => {
167
+ it('should pass the parsed, trimmed project order to the handler', async () => {
168
+ await program.parseAsync([
169
+ 'node',
170
+ 'test',
171
+ 'schedule',
172
+ '-t',
173
+ 'schedule',
174
+ '-c',
175
+ configFilePath,
176
+ '--inTmuxProjectOrder',
177
+ 'alpha, beta ,gamma',
178
+ ]);
179
+
180
+ expect(mockScheduleHandle).toHaveBeenCalledWith(
181
+ configFilePath,
182
+ undefined,
183
+ ['alpha', 'beta', 'gamma'],
184
+ );
185
+ });
186
+
187
+ it('should pass null when --inTmuxProjectOrder is omitted', async () => {
188
+ await program.parseAsync([
189
+ 'node',
190
+ 'test',
191
+ 'schedule',
192
+ '-t',
193
+ 'schedule',
194
+ '-c',
195
+ configFilePath,
196
+ ]);
197
+
198
+ expect(mockScheduleHandle).toHaveBeenCalledWith(
199
+ configFilePath,
200
+ undefined,
201
+ null,
202
+ );
203
+ });
204
+ });
205
+
165
206
  describe('loadConfigFile', () => {
166
207
  it('should load config from YAML file', () => {
167
208
  const config = {
@@ -132,11 +132,22 @@ const buildGithubRepositoryParams = (
132
132
  token,
133
133
  ];
134
134
 
135
+ const parseInTmuxProjectOrder = (raw: string | undefined): string[] | null => {
136
+ if (raw === undefined) {
137
+ return null;
138
+ }
139
+ return raw
140
+ .split(',')
141
+ .map((name) => name.trim())
142
+ .filter((name) => name.length > 0);
143
+ };
144
+
135
145
  interface ScheduleOptions {
136
146
  trigger: 'issue' | 'schedule';
137
147
  config: string;
138
148
  issue?: string;
139
149
  verbose: boolean;
150
+ inTmuxProjectOrder?: string;
140
151
  }
141
152
 
142
153
  export const program = new Command();
@@ -156,6 +167,10 @@ program
156
167
  .requiredOption('-c, --config <path>', 'Path to config YAML file')
157
168
  .option('-v, --verbose', 'Verbose output')
158
169
  .option('-i, --issue <url>', 'GitHub Issue URL')
170
+ .option(
171
+ '--inTmuxProjectOrder <names>',
172
+ 'Comma-separated project names, in display order, for the in-tmux-by-human session list. When omitted, falls back to the inTmuxProjectOrder value in the config file.',
173
+ )
159
174
  .action(async (options: ScheduleOptions) => {
160
175
  if (options.trigger === 'issue' && !options.issue) {
161
176
  console.error('Issue URL is required when trigger type is "issue"');
@@ -165,7 +180,11 @@ program
165
180
  const { HandleScheduledEventUseCaseHandler } =
166
181
  await import('../handlers/HandleScheduledEventUseCaseHandler');
167
182
  const handler = new HandleScheduledEventUseCaseHandler();
168
- await handler.handle(options.config, options.verbose);
183
+ await handler.handle(
184
+ options.config,
185
+ options.verbose,
186
+ parseInTmuxProjectOrder(options.inTmuxProjectOrder),
187
+ );
169
188
  }
170
189
  });
171
190
 
@@ -0,0 +1,75 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { loadConfigFile, mergeConfigs } from './projectConfig';
5
+
6
+ describe('loadConfigFile disks', () => {
7
+ let dir: string;
8
+
9
+ beforeEach(() => {
10
+ dir = fs.mkdtempSync(path.join(os.tmpdir(), 'project-config-disks-'));
11
+ });
12
+
13
+ afterEach(() => {
14
+ fs.rmSync(dir, { recursive: true, force: true });
15
+ });
16
+
17
+ const writeConfig = (content: string): string => {
18
+ const filePath = path.join(dir, 'config.yml');
19
+ fs.writeFileSync(filePath, content);
20
+ return filePath;
21
+ };
22
+
23
+ it('parses a disks list of title and mountpoint pairs', () => {
24
+ const filePath = writeConfig(
25
+ [
26
+ "projectName: 'demo'",
27
+ 'disks:',
28
+ " - title: 'D'",
29
+ " mountpoint: '/'",
30
+ " - title: 'S'",
31
+ " mountpoint: '/mountpoint-secondary'",
32
+ ].join('\n'),
33
+ );
34
+ expect(loadConfigFile(filePath).disks).toEqual([
35
+ { title: 'D', mountpoint: '/' },
36
+ { title: 'S', mountpoint: '/mountpoint-secondary' },
37
+ ]);
38
+ });
39
+
40
+ it('yields undefined disks when the key is absent', () => {
41
+ const filePath = writeConfig("projectName: 'demo'\n");
42
+ expect(loadConfigFile(filePath).disks).toBeUndefined();
43
+ });
44
+
45
+ it('yields undefined disks when an entry is missing required fields', () => {
46
+ const filePath = writeConfig(
47
+ ['disks:', " - title: 'D'"].join('\n') + '\n',
48
+ );
49
+ expect(loadConfigFile(filePath).disks).toBeUndefined();
50
+ });
51
+ });
52
+
53
+ describe('mergeConfigs disks', () => {
54
+ it('prefers cli override disks over the config file disks', () => {
55
+ const merged = mergeConfigs(
56
+ { disks: [{ title: 'D', mountpoint: '/' }] },
57
+ { disks: [{ title: 'C', mountpoint: '/cli' }] },
58
+ {},
59
+ );
60
+ expect(merged.disks).toEqual([{ title: 'C', mountpoint: '/cli' }]);
61
+ });
62
+
63
+ it('falls back to the config file disks when no cli override is present', () => {
64
+ const merged = mergeConfigs(
65
+ { disks: [{ title: 'D', mountpoint: '/' }] },
66
+ {},
67
+ {},
68
+ );
69
+ expect(merged.disks).toEqual([{ title: 'D', mountpoint: '/' }]);
70
+ });
71
+
72
+ it('yields undefined disks when neither source provides them', () => {
73
+ expect(mergeConfigs({}, {}, {}).disks).toBeUndefined();
74
+ });
75
+ });
@@ -25,6 +25,12 @@ export type ConfigFile = {
25
25
  changeTargetPathAliases?: Record<string, string>;
26
26
  consoleAccessToken?: string;
27
27
  consoleProjects?: Record<string, string>;
28
+ disks?: DiskConfig[];
29
+ };
30
+
31
+ export type DiskConfig = {
32
+ title: string;
33
+ mountpoint: string;
28
34
  };
29
35
 
30
36
  const getStringValue = (
@@ -82,6 +88,29 @@ const getStringArrayValue = (
82
88
  export const isRecord = (value: unknown): value is Record<string, unknown> =>
83
89
  typeof value === 'object' && value !== null && !Array.isArray(value);
84
90
 
91
+ const getDisksValue = (
92
+ obj: Record<string, unknown>,
93
+ key: string,
94
+ ): DiskConfig[] | undefined => {
95
+ const value = obj[key];
96
+ if (!Array.isArray(value)) {
97
+ return undefined;
98
+ }
99
+ const disks: DiskConfig[] = [];
100
+ for (const item of value) {
101
+ if (!isRecord(item)) {
102
+ return undefined;
103
+ }
104
+ const title = item['title'];
105
+ const mountpoint = item['mountpoint'];
106
+ if (typeof title !== 'string' || typeof mountpoint !== 'string') {
107
+ return undefined;
108
+ }
109
+ disks.push({ title, mountpoint });
110
+ }
111
+ return disks;
112
+ };
113
+
85
114
  const knownProjectReadmeConfigKeys = [
86
115
  'defaultAgentName',
87
116
  'defaultLlmModelName',
@@ -155,6 +184,7 @@ export const loadConfigFile = (configFilePath: string): ConfigFile => {
155
184
  ),
156
185
  consoleAccessToken: getStringValue(parsed, 'consoleAccessToken'),
157
186
  consoleProjects: getStringRecordValue(parsed, 'consoleProjects'),
187
+ disks: getDisksValue(parsed, 'disks'),
158
188
  };
159
189
  } catch (error) {
160
190
  const message = error instanceof Error ? error.message : String(error);
@@ -320,6 +350,7 @@ export const mergeConfigs = (
320
350
  consoleAccessToken:
321
351
  cliOverrides.consoleAccessToken ?? configFile.consoleAccessToken,
322
352
  consoleProjects: cliOverrides.consoleProjects ?? configFile.consoleProjects,
353
+ disks: cliOverrides.disks ?? configFile.disks,
323
354
  });
324
355
 
325
356
  type GraphqlProjectV2ReadmeResponse = {
@@ -113,6 +113,7 @@ describe('buildComposeDashboardInput', () => {
113
113
  memPct: 55,
114
114
  cpuPct: 62,
115
115
  diskPct: 89,
116
+ disks: null,
116
117
  load: [16, 23, 40],
117
118
  cycleMinutes: 14,
118
119
  });
@@ -121,6 +122,37 @@ describe('buildComposeDashboardInput', () => {
121
122
  }
122
123
  });
123
124
 
125
+ it('reads a disks array from machine-status.json', () => {
126
+ const dataDir = makeDataDir();
127
+ try {
128
+ fs.writeFileSync(
129
+ path.join(dataDir, 'machine-status.json'),
130
+ JSON.stringify({
131
+ memPct: 55,
132
+ cpuPct: 62,
133
+ diskPct: 89,
134
+ disks: [
135
+ { title: 'D', pct: 89 },
136
+ { title: 'S', pct: 41 },
137
+ ],
138
+ load: [16, 23, 40],
139
+ cycleMinutes: 14,
140
+ capturedAt: 'x',
141
+ }),
142
+ );
143
+ const input = buildComposeDashboardInput({
144
+ dashboardDataDir: dataDir,
145
+ projectNames: [],
146
+ });
147
+ expect(input.machineStatus?.disks).toEqual([
148
+ { title: 'D', pct: 89 },
149
+ { title: 'S', pct: 41 },
150
+ ]);
151
+ } finally {
152
+ fs.rmSync(dataDir, { recursive: true, force: true });
153
+ }
154
+ });
155
+
124
156
  it('preserves a null cycleMinutes from machine-status.json', () => {
125
157
  const dataDir = makeDataDir();
126
158
  try {
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import {
4
+ ComposeDashboardDisk,
4
5
  ComposeDashboardInput,
5
6
  ComposeDashboardMachineStatus,
6
7
  ComposeDashboardProject,
@@ -88,6 +89,24 @@ const parseLoad = (value: unknown): [number, number, number] | null => {
88
89
  return [oneMinute, fiveMinute, fifteenMinute];
89
90
  };
90
91
 
92
+ const parseDisks = (value: unknown): ComposeDashboardDisk[] | null => {
93
+ if (!Array.isArray(value)) {
94
+ return null;
95
+ }
96
+ const disks: ComposeDashboardDisk[] = [];
97
+ for (const entry of value) {
98
+ if (!isRecord(entry) || typeof entry.title !== 'string') {
99
+ return null;
100
+ }
101
+ const pct = asFiniteNumber(entry.pct);
102
+ if (pct === null) {
103
+ return null;
104
+ }
105
+ disks.push({ title: entry.title, pct });
106
+ }
107
+ return disks;
108
+ };
109
+
91
110
  const readMachineStatus = (
92
111
  dashboardDataDir: string,
93
112
  ): ComposeDashboardMachineStatus | null => {
@@ -104,6 +123,7 @@ const readMachineStatus = (
104
123
  memPct: asFiniteNumber(value.memPct),
105
124
  cpuPct: asFiniteNumber(value.cpuPct),
106
125
  diskPct: asFiniteNumber(value.diskPct),
126
+ disks: parseDisks(value.disks),
107
127
  load: parseLoad(value.load),
108
128
  cycleMinutes,
109
129
  };
@@ -126,9 +126,13 @@ jest.mock('./situationFileWriter', () => ({
126
126
  jest.mock('./rotationOrderFileWriter', () => ({
127
127
  writeRotationOrderFile: jest.fn(),
128
128
  }));
129
+ jest.mock('./inTmuxByHumanDataWriter', () => ({
130
+ writeInTmuxByHumanData: jest.fn(),
131
+ }));
129
132
 
130
133
  import { HandleScheduledEventUseCaseHandler } from './HandleScheduledEventUseCaseHandler';
131
134
  import { writeSituationFile } from './situationFileWriter';
135
+ import { writeInTmuxByHumanData } from './inTmuxByHumanDataWriter';
132
136
  import { GraphqlProjectRepository } from '../../repositories/GraphqlProjectRepository';
133
137
  import { ApiV3IssueRepository } from '../../repositories/issue/ApiV3IssueRepository';
134
138
  import { RestIssueRepository } from '../../repositories/issue/RestIssueRepository';
@@ -148,6 +152,7 @@ const MockedApiV3CheerioRestIssueRepository = jest.mocked(
148
152
  const MockedProxyClaudeTokenUsageRepository = jest.mocked(
149
153
  ProxyClaudeTokenUsageRepository,
150
154
  );
155
+ const MockedWriteInTmuxByHumanData = jest.mocked(writeInTmuxByHumanData);
151
156
 
152
157
  const validConfig = {
153
158
  projectName: 'test-project',
@@ -643,4 +648,65 @@ defaultAgentName: readme-agent
643
648
  );
644
649
  });
645
650
  });
651
+
652
+ describe('inTmuxProjectOrder override', () => {
653
+ const getInTmuxProjectOrderArg = (): string[] | null | undefined => {
654
+ const call = MockedWriteInTmuxByHumanData.mock.calls[0];
655
+ if (call === undefined) {
656
+ throw new Error('writeInTmuxByHumanData was not called');
657
+ }
658
+ return call[0].inTmuxProjectOrder;
659
+ };
660
+
661
+ it('should use the CLI override when provided, ignoring the config value', async () => {
662
+ jest.mocked(fs.readFileSync).mockReturnValue(
663
+ YAML.stringify({
664
+ ...validConfig,
665
+ inTmuxProjectOrder: ['alpha', 'beta'],
666
+ }),
667
+ );
668
+
669
+ const handler = new HandleScheduledEventUseCaseHandler();
670
+ await handler.handle('config.yml', false, ['gamma', 'delta']);
671
+
672
+ expect(getInTmuxProjectOrderArg()).toEqual(['gamma', 'delta']);
673
+ });
674
+
675
+ it('should fall back to the config value when the CLI override is null', async () => {
676
+ jest.mocked(fs.readFileSync).mockReturnValue(
677
+ YAML.stringify({
678
+ ...validConfig,
679
+ inTmuxProjectOrder: ['alpha', 'beta'],
680
+ }),
681
+ );
682
+
683
+ const handler = new HandleScheduledEventUseCaseHandler();
684
+ await handler.handle('config.yml', false, null);
685
+
686
+ expect(getInTmuxProjectOrderArg()).toEqual(['alpha', 'beta']);
687
+ });
688
+
689
+ it('should fall back to the config value when the override argument is omitted', async () => {
690
+ jest.mocked(fs.readFileSync).mockReturnValue(
691
+ YAML.stringify({
692
+ ...validConfig,
693
+ inTmuxProjectOrder: ['alpha', 'beta'],
694
+ }),
695
+ );
696
+
697
+ const handler = new HandleScheduledEventUseCaseHandler();
698
+ await handler.handle('config.yml', false);
699
+
700
+ expect(getInTmuxProjectOrderArg()).toEqual(['alpha', 'beta']);
701
+ });
702
+
703
+ it('should pass null when neither the override nor the config provides a value', async () => {
704
+ jest.mocked(fs.readFileSync).mockReturnValue(YAML.stringify(validConfig));
705
+
706
+ const handler = new HandleScheduledEventUseCaseHandler();
707
+ await handler.handle('config.yml', false, null);
708
+
709
+ expect(getInTmuxProjectOrderArg()).toBeNull();
710
+ });
711
+ });
646
712
  });
@@ -86,6 +86,7 @@ export class HandleScheduledEventUseCaseHandler {
86
86
  handle = async (
87
87
  configFilePath: string,
88
88
  _verbose: boolean,
89
+ inTmuxProjectOrderOverride: string[] | null = null,
89
90
  ): Promise<{
90
91
  project: Project;
91
92
  issues: Issue[];
@@ -103,6 +104,7 @@ export class HandleScheduledEventUseCaseHandler {
103
104
  claudeCodeOauthTokenListJsonPath?: string;
104
105
  consoleDataOutputDir?: string;
105
106
  dashboardDataDir?: string;
107
+ disks?: { title: string; mountpoint: string }[];
106
108
  workflowBlockerStoryName?: string;
107
109
  inTmuxDataOutputDir?: string;
108
110
  newIssueRepo?: string;
@@ -492,6 +494,7 @@ export class HandleScheduledEventUseCaseHandler {
492
494
  await writeMachineStatus({
493
495
  dashboardDataDir,
494
496
  allIssuesCacheDir: `${cachePath}/allIssues-${result.project.id}`,
497
+ disks: mergedInput.disks ?? null,
495
498
  });
496
499
  } catch (error) {
497
500
  console.error(
@@ -524,7 +527,10 @@ export class HandleScheduledEventUseCaseHandler {
524
527
  inTmuxDataOutputDir: mergedInput.inTmuxDataOutputDir ?? null,
525
528
  inTmuxConsoleBaseUrl: mergedInput.inTmuxConsoleBaseUrl ?? null,
526
529
  inTmuxConsoleToken: mergedInput.inTmuxConsoleToken ?? null,
527
- inTmuxProjectOrder: mergedInput.inTmuxProjectOrder ?? null,
530
+ inTmuxProjectOrder:
531
+ inTmuxProjectOrderOverride ??
532
+ mergedInput.inTmuxProjectOrder ??
533
+ null,
528
534
  pjcode: input.projectName,
529
535
  assigneeLogin: input.manager,
530
536
  org: input.org,
@@ -91,6 +91,67 @@ describe('writeMachineStatus', () => {
91
91
  expect(written).toEqual(expected);
92
92
  });
93
93
 
94
+ it('writes a per-mountpoint disks array when a disks list is configured', async () => {
95
+ fs.writeFileSync(
96
+ path.join(procDirectory, 'meminfo'),
97
+ 'MemTotal: 1000 kB\nMemAvailable: 450 kB\n',
98
+ );
99
+ fs.writeFileSync(
100
+ path.join(procDirectory, 'loadavg'),
101
+ '1.50 0.80 0.40 1/100 200\n',
102
+ );
103
+ const statPath = path.join(procDirectory, 'stat');
104
+ fs.writeFileSync(statPath, 'cpu 600 0 0 400 0 0 0 0 0 0\n');
105
+ const sleep = async (): Promise<void> => {
106
+ fs.writeFileSync(statPath, 'cpu 660 0 0 440 0 0 0 0 0 0\n');
107
+ };
108
+ const blocksByMountpoint: Record<
109
+ string,
110
+ { blocks: number; bfree: number; bavail: number }
111
+ > = {
112
+ '/': { blocks: 1100, bfree: 200, bavail: 100 },
113
+ '/mountpoint-secondary': { blocks: 1000, bfree: 700, bavail: 700 },
114
+ };
115
+ const repository = new ProcHostMetricsRepository(
116
+ procDirectory,
117
+ sleep,
118
+ (mountpoint) => blocksByMountpoint[mountpoint],
119
+ );
120
+
121
+ await writeMachineStatus({
122
+ dashboardDataDir: dir,
123
+ allIssuesCacheDir: null,
124
+ disks: [
125
+ { title: 'D', mountpoint: '/' },
126
+ { title: 'S', mountpoint: '/mountpoint-secondary' },
127
+ ],
128
+ hostMetricsRepository: repository,
129
+ now: new Date('2026-06-26T12:00:00.000Z'),
130
+ });
131
+
132
+ const written = readJson(path.join(dir, 'machine-status.json'));
133
+ expect(written).toMatchObject({
134
+ diskPct: 90,
135
+ disks: [
136
+ { title: 'D', pct: 90 },
137
+ { title: 'S', pct: 30 },
138
+ ],
139
+ });
140
+ });
141
+
142
+ it('omits the disks array when no disks list is configured', async () => {
143
+ const { repository } = buildHostMetricsRepository(procDirectory);
144
+ await writeMachineStatus({
145
+ dashboardDataDir: dir,
146
+ allIssuesCacheDir: null,
147
+ hostMetricsRepository: repository,
148
+ now: new Date('2026-06-26T12:00:00.000Z'),
149
+ });
150
+ const written = readJson(path.join(dir, 'machine-status.json'));
151
+ expect(written).toMatchObject({ diskPct: 90 });
152
+ expect(written).not.toHaveProperty('disks');
153
+ });
154
+
94
155
  it('writes cycleMinutes null when there is no previous machine-status', async () => {
95
156
  const { repository } = buildHostMetricsRepository(procDirectory);
96
157
  const cacheDir = path.join(dir, 'allIssues-PVT');
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
+ import { DiskConfig } from '../cli/projectConfig';
3
4
  import {
4
5
  ProcHostMetricsRepository,
5
6
  cycleMinutesFromFetchTimestamps,
@@ -8,14 +9,21 @@ import {
8
9
  export type MachineStatusWriterParams = {
9
10
  dashboardDataDir: string | null | undefined;
10
11
  allIssuesCacheDir: string | null | undefined;
12
+ disks?: DiskConfig[] | null;
11
13
  hostMetricsRepository?: ProcHostMetricsRepository;
12
14
  now?: Date;
13
15
  };
14
16
 
17
+ export type MachineStatusDisk = {
18
+ title: string;
19
+ pct: number;
20
+ };
21
+
15
22
  export type MachineStatusFile = {
16
23
  memPct: number;
17
24
  cpuPct: number;
18
25
  diskPct: number;
26
+ disks?: MachineStatusDisk[];
19
27
  load: [number, number, number];
20
28
  cycleMinutes: number | null;
21
29
  lastFetchedAt: string | null;
@@ -68,6 +76,14 @@ export const writeMachineStatus = async (
68
76
  const diskPct = hostMetricsRepository.readDiskUsedPercent();
69
77
  const load = hostMetricsRepository.readLoadAverages();
70
78
 
79
+ const configuredDisks = params.disks ?? [];
80
+ const disks: MachineStatusDisk[] = configuredDisks.map((disk) => ({
81
+ title: disk.title,
82
+ pct: hostMetricsRepository.readDiskUsedPercentForMountpoint(
83
+ disk.mountpoint,
84
+ ),
85
+ }));
86
+
71
87
  const machineStatusPath = path.join(dashboardDataDir, 'machine-status.json');
72
88
  const previousLastFetchedAt =
73
89
  readLastFetchedAtFromJsonFile(machineStatusPath);
@@ -83,6 +99,7 @@ export const writeMachineStatus = async (
83
99
  memPct,
84
100
  cpuPct,
85
101
  diskPct,
102
+ ...(disks.length > 0 ? { disks } : {}),
86
103
  load: [load.oneMinute, load.fiveMinute, load.fifteenMinute],
87
104
  cycleMinutes,
88
105
  lastFetchedAt: currentLastFetchedAt,
@@ -167,6 +167,31 @@ describe('ProcHostMetricsRepository', () => {
167
167
  expect(repository.readDiskUsedPercent()).toBe(90);
168
168
  });
169
169
 
170
+ it('reads the df-style disk used percent for a given mountpoint', () => {
171
+ const blocksByMountpoint: Record<string, DiskBlocks> = {
172
+ '/': { blocks: 1100, bfree: 200, bavail: 100 },
173
+ '/mountpoint-a': { blocks: 1000, bfree: 700, bavail: 700 },
174
+ };
175
+ const requestedMountpoints: string[] = [];
176
+ const repository = new ProcHostMetricsRepository(
177
+ procDirectory,
178
+ async () => {},
179
+ (mountpoint) => {
180
+ requestedMountpoints.push(mountpoint);
181
+ const blocks = blocksByMountpoint[mountpoint];
182
+ if (!blocks) {
183
+ throw new Error(`unexpected mountpoint ${mountpoint}`);
184
+ }
185
+ return blocks;
186
+ },
187
+ );
188
+ expect(repository.readDiskUsedPercentForMountpoint('/mountpoint-a')).toBe(
189
+ 30,
190
+ );
191
+ expect(repository.readDiskUsedPercentForMountpoint('/')).toBe(90);
192
+ expect(requestedMountpoints).toEqual(['/mountpoint-a', '/']);
193
+ });
194
+
170
195
  it('samples /proc/stat twice and computes the busy percent', async () => {
171
196
  const statPath = path.join(procDirectory, 'stat');
172
197
  let sampleIndex = 0;
@@ -173,4 +173,9 @@ export class ProcHostMetricsRepository {
173
173
  const { blocks, bfree, bavail } = this.readDiskBlocks(this.rootPath);
174
174
  return parseDiskUsedPercent(blocks, bfree, bavail);
175
175
  };
176
+
177
+ readDiskUsedPercentForMountpoint = (mountpoint: string): number => {
178
+ const { blocks, bfree, bavail } = this.readDiskBlocks(mountpoint);
179
+ return parseDiskUsedPercent(blocks, bfree, bavail);
180
+ };
176
181
  }