@oss-autopilot/core 1.13.0 → 1.14.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.
@@ -51,6 +51,21 @@ function readVettedIssues() {
51
51
  return null;
52
52
  }
53
53
  }
54
+ /**
55
+ * Get the mtime of the vetted issue list file in ms, or null if unknown.
56
+ * Used to detect external edits and invalidate the cached dashboard payload.
57
+ */
58
+ function getIssueListMtimeMs() {
59
+ try {
60
+ const info = detectIssueList();
61
+ if (!info)
62
+ return null;
63
+ return fs.statSync(info.path).mtimeMs;
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
54
69
  /**
55
70
  * Build the JSON payload that the SPA expects from GET /api/data.
56
71
  */
@@ -186,6 +201,7 @@ export async function startDashboardServer(options) {
186
201
  }
187
202
  // ── Build cached JSON response ───────────────────────────────────────────
188
203
  let cachedJsonData;
204
+ let cachedIssueListMtimeMs = getIssueListMtimeMs();
189
205
  try {
190
206
  cachedJsonData = buildDashboardJson(cachedDigest, stateManager.getState(), cachedCommentedIssues);
191
207
  }
@@ -217,9 +233,13 @@ export async function startDashboardServer(options) {
217
233
  else {
218
234
  stateChanged = stateManager.reloadIfChanged();
219
235
  }
220
- if (stateChanged) {
236
+ // Also rebuild when the vetted issue list file was edited outside this server (#924)
237
+ const currentIssueListMtimeMs = getIssueListMtimeMs();
238
+ const issueListChanged = currentIssueListMtimeMs !== cachedIssueListMtimeMs;
239
+ if (stateChanged || issueListChanged) {
221
240
  try {
222
241
  cachedJsonData = buildDashboardJson(cachedDigest, stateManager.getState(), cachedCommentedIssues);
242
+ cachedIssueListMtimeMs = currentIssueListMtimeMs;
223
243
  }
224
244
  catch (error) {
225
245
  warn(MODULE, `Failed to rebuild dashboard data after state reload: ${errorMessage(error)}`);
@@ -336,6 +356,7 @@ export async function startDashboardServer(options) {
336
356
  }
337
357
  // Rebuild dashboard data from cached digest + updated state
338
358
  cachedJsonData = buildDashboardJson(cachedDigest, stateManager.getState(), cachedCommentedIssues);
359
+ cachedIssueListMtimeMs = getIssueListMtimeMs();
339
360
  sendJson(res, 200, cachedJsonData);
340
361
  }
341
362
  // ── POST /api/refresh handler ────────────────────────────────────────────
@@ -357,6 +378,7 @@ export async function startDashboardServer(options) {
357
378
  cachedDigest = result.digest;
358
379
  cachedCommentedIssues = result.commentedIssues;
359
380
  cachedJsonData = buildDashboardJson(cachedDigest, stateManager.getState(), cachedCommentedIssues, result.allMergedPRs, result.allClosedPRs);
381
+ cachedIssueListMtimeMs = getIssueListMtimeMs();
360
382
  sendJson(res, 200, cachedJsonData);
361
383
  }
362
384
  catch (error) {
@@ -476,6 +498,7 @@ export async function startDashboardServer(options) {
476
498
  cachedDigest = result.digest;
477
499
  cachedCommentedIssues = result.commentedIssues;
478
500
  cachedJsonData = buildDashboardJson(cachedDigest, stateManager.getState(), cachedCommentedIssues, result.allMergedPRs, result.allClosedPRs);
501
+ cachedIssueListMtimeMs = getIssueListMtimeMs();
479
502
  warn(MODULE, 'Background data refresh complete');
480
503
  })
481
504
  .catch((error) => {
@@ -15,11 +15,10 @@ import { type StartupOutput, type IssueListInfo } from '../formatters/json.js';
15
15
  export declare function parseIssueListPathFromConfig(configContent: string): string | undefined;
16
16
  /**
17
17
  * Count available and completed items in an issue list file.
18
- * Available: list items (`- [`) NOT struck through or marked Done.
19
- * Completed: list items that ARE struck through or marked Done.
20
- *
21
- * @param content - Raw markdown content of the issue list
22
- * @returns Counts of available and completed items
18
+ * Available items exclude any vetting status that moves an item out of the
19
+ * actionable pool strikethrough, `**Done**`, and sub-bullet markers like
20
+ * `**Skip**`, `**Merged**`, `**Dropped**`, `**Closed**`, `**In Progress**`,
21
+ * `**Waiting**`. Matches the parse-issue-list command's classification (#907).
23
22
  */
24
23
  export declare function countIssueListItems(content: string): {
25
24
  availableCount: number;
@@ -14,6 +14,7 @@ import { errorMessage } from '../core/errors.js';
14
14
  import { warn } from '../core/logger.js';
15
15
  import { executeDailyCheck } from './daily.js';
16
16
  import { launchDashboardServer } from './dashboard-lifecycle.js';
17
+ import { parseIssueList } from './parse-list.js';
17
18
  /**
18
19
  * Parse issueListPath from a config file's YAML frontmatter.
19
20
  * @param configContent - Raw content of the config.md file
@@ -29,27 +30,13 @@ export function parseIssueListPathFromConfig(configContent) {
29
30
  }
30
31
  /**
31
32
  * Count available and completed items in an issue list file.
32
- * Available: list items (`- [`) NOT struck through or marked Done.
33
- * Completed: list items that ARE struck through or marked Done.
34
- *
35
- * @param content - Raw markdown content of the issue list
36
- * @returns Counts of available and completed items
33
+ * Available items exclude any vetting status that moves an item out of the
34
+ * actionable pool strikethrough, `**Done**`, and sub-bullet markers like
35
+ * `**Skip**`, `**Merged**`, `**Dropped**`, `**Closed**`, `**In Progress**`,
36
+ * `**Waiting**`. Matches the parse-issue-list command's classification (#907).
37
37
  */
38
38
  export function countIssueListItems(content) {
39
- let availableCount = 0;
40
- let completedCount = 0;
41
- const lines = content.split('\n');
42
- for (const line of lines) {
43
- // Match list items: "- [" or "- ~~[" (strikethrough completed items)
44
- if (/^\s*- (?:~~)?\[/.test(line)) {
45
- if (/~~|\*\*Done\*\*/.test(line)) {
46
- completedCount++;
47
- }
48
- else {
49
- availableCount++;
50
- }
51
- }
52
- }
39
+ const { availableCount, completedCount } = parseIssueList(content);
53
40
  return { availableCount, completedCount };
54
41
  }
55
42
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-autopilot/core",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "CLI and core library for managing open source contributions",
5
5
  "type": "module",
6
6
  "bin": {