project-logbook 1.2.0 → 1.4.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.
- package/README.md +2 -0
- package/dist/commands/answer.d.ts +1 -0
- package/dist/commands/answer.js +41 -0
- package/dist/commands/answer.js.map +1 -0
- package/dist/commands/answers.d.ts +6 -0
- package/dist/commands/answers.js +37 -0
- package/dist/commands/answers.js.map +1 -0
- package/dist/commands/ask.d.ts +1 -0
- package/dist/commands/ask.js +30 -0
- package/dist/commands/ask.js.map +1 -0
- package/dist/commands/build.js +25 -6
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/deprecate-qna.d.ts +1 -0
- package/dist/commands/deprecate-qna.js +33 -0
- package/dist/commands/deprecate-qna.js.map +1 -0
- package/dist/commands/log.js +2 -0
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/new-helpers.d.ts +0 -1
- package/dist/commands/new-helpers.js +6 -3
- package/dist/commands/new-helpers.js.map +1 -1
- package/dist/commands/release.js +2 -0
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/start.js +90 -21
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +6 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/unanswered.d.ts +1 -0
- package/dist/commands/unanswered.js +25 -0
- package/dist/commands/unanswered.js.map +1 -0
- package/dist/commands/watch.d.ts +15 -0
- package/dist/commands/watch.js +153 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/autolink.d.ts +5 -0
- package/dist/lib/autolink.js +36 -2
- package/dist/lib/autolink.js.map +1 -1
- package/dist/lib/build-helpers.d.ts +10 -1
- package/dist/lib/build-helpers.js +27 -4
- package/dist/lib/build-helpers.js.map +1 -1
- package/dist/lib/build-steps.js +2 -1
- package/dist/lib/build-steps.js.map +1 -1
- package/dist/lib/config.d.ts +16 -0
- package/dist/lib/config.js +17 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/custom-card-renderer.js +2 -1
- package/dist/lib/custom-card-renderer.js.map +1 -1
- package/dist/lib/entry-href.d.ts +7 -0
- package/dist/lib/entry-href.js +8 -0
- package/dist/lib/entry-href.js.map +1 -0
- package/dist/lib/markdown-processors.d.ts +2 -1
- package/dist/lib/post-template.js +3 -3
- package/dist/lib/post-template.js.map +1 -1
- package/dist/lib/template-helpers.d.ts +2 -1
- package/dist/lib/template-helpers.js +32 -2
- package/dist/lib/template-helpers.js.map +1 -1
- package/dist/lib/template-types.d.ts +14 -0
- package/dist/lib/templates.js +14 -4
- package/dist/lib/templates.js.map +1 -1
- package/dist/linters/index.js +2 -0
- package/dist/linters/index.js.map +1 -1
- package/dist/linters/jira-prefix.js +32 -16
- package/dist/linters/jira-prefix.js.map +1 -1
- package/dist/linters/qna.d.ts +3 -0
- package/dist/linters/qna.js +120 -0
- package/dist/linters/qna.js.map +1 -0
- package/dist/templates/about-watch.md +29 -0
- package/dist/templates/hub.css +677 -0
- package/dist/templates/hub.js +743 -0
- package/dist/templates/qna.md +11 -0
- package/dist/templates/steer.txt +2 -0
- package/dist/templates/styles.css +53 -0
- package/dist/utils/id.d.ts +1 -1
- package/dist/utils/id.js +4 -1
- package/dist/utils/id.js.map +1 -1
- package/dist/utils/qna.d.ts +46 -0
- package/dist/utils/qna.js +157 -0
- package/dist/utils/qna.js.map +1 -0
- package/dist/watch/__tests__/git-utils.test.d.ts +1 -0
- package/dist/watch/__tests__/git-utils.test.js +17 -0
- package/dist/watch/__tests__/git-utils.test.js.map +1 -0
- package/dist/watch/collector.d.ts +14 -0
- package/dist/watch/collector.js +33 -0
- package/dist/watch/collector.js.map +1 -0
- package/dist/watch/collectors/acli.d.ts +15 -0
- package/dist/watch/collectors/acli.js +197 -0
- package/dist/watch/collectors/acli.js.map +1 -0
- package/dist/watch/collectors/entries.d.ts +9 -0
- package/dist/watch/collectors/entries.js +90 -0
- package/dist/watch/collectors/entries.js.map +1 -0
- package/dist/watch/collectors/git.d.ts +12 -0
- package/dist/watch/collectors/git.js +58 -0
- package/dist/watch/collectors/git.js.map +1 -0
- package/dist/watch/collectors/glab.d.ts +10 -0
- package/dist/watch/collectors/glab.js +273 -0
- package/dist/watch/collectors/glab.js.map +1 -0
- package/dist/watch/collectors/index.d.ts +10 -0
- package/dist/watch/collectors/index.js +21 -0
- package/dist/watch/collectors/index.js.map +1 -0
- package/dist/watch/collectors/jira.d.ts +3 -0
- package/dist/watch/collectors/jira.js +111 -0
- package/dist/watch/collectors/jira.js.map +1 -0
- package/dist/watch/collectors/type-guards.d.ts +17 -0
- package/dist/watch/collectors/type-guards.js +35 -0
- package/dist/watch/collectors/type-guards.js.map +1 -0
- package/dist/watch/collectors/types.d.ts +37 -0
- package/dist/watch/collectors/types.js +9 -0
- package/dist/watch/collectors/types.js.map +1 -0
- package/dist/watch/dashboard-html.d.ts +11 -0
- package/dist/watch/dashboard-html.js +81 -0
- package/dist/watch/dashboard-html.js.map +1 -0
- package/dist/watch/dashboard-script.d.ts +12 -0
- package/dist/watch/dashboard-script.js +20 -0
- package/dist/watch/dashboard-script.js.map +1 -0
- package/dist/watch/dashboard-styles.d.ts +12 -0
- package/dist/watch/dashboard-styles.js +20 -0
- package/dist/watch/dashboard-styles.js.map +1 -0
- package/dist/watch/dashboard.d.ts +12 -0
- package/dist/watch/dashboard.js +50 -0
- package/dist/watch/dashboard.js.map +1 -0
- package/dist/watch/git-utils.d.ts +36 -0
- package/dist/watch/git-utils.js +117 -0
- package/dist/watch/git-utils.js.map +1 -0
- package/dist/watch/hub-state.d.ts +39 -0
- package/dist/watch/hub-state.js +57 -0
- package/dist/watch/hub-state.js.map +1 -0
- package/dist/watch/hub.d.ts +2 -0
- package/dist/watch/hub.js +252 -0
- package/dist/watch/hub.js.map +1 -0
- package/dist/watch/log-utils.d.ts +13 -0
- package/dist/watch/log-utils.js +24 -0
- package/dist/watch/log-utils.js.map +1 -0
- package/dist/watch/notify.d.ts +18 -0
- package/dist/watch/notify.js +45 -0
- package/dist/watch/notify.js.map +1 -0
- package/dist/watch/state.d.ts +38 -0
- package/dist/watch/state.js +36 -0
- package/dist/watch/state.js.map +1 -0
- package/dist/watch/strategies/behind-default.d.ts +5 -0
- package/dist/watch/strategies/behind-default.js +21 -0
- package/dist/watch/strategies/behind-default.js.map +1 -0
- package/dist/watch/strategies/idle.d.ts +5 -0
- package/dist/watch/strategies/idle.js +21 -0
- package/dist/watch/strategies/idle.js.map +1 -0
- package/dist/watch/strategies/in-progress.d.ts +5 -0
- package/dist/watch/strategies/in-progress.js +21 -0
- package/dist/watch/strategies/in-progress.js.map +1 -0
- package/dist/watch/strategies/index.d.ts +34 -0
- package/dist/watch/strategies/index.js +148 -0
- package/dist/watch/strategies/index.js.map +1 -0
- package/dist/watch/strategies/jira-not-in-review.d.ts +2 -0
- package/dist/watch/strategies/jira-not-in-review.js +29 -0
- package/dist/watch/strategies/jira-not-in-review.js.map +1 -0
- package/dist/watch/strategies/jira-still-open.d.ts +2 -0
- package/dist/watch/strategies/jira-still-open.js +31 -0
- package/dist/watch/strategies/jira-still-open.js.map +1 -0
- package/dist/watch/strategies/mr-approval-optional.d.ts +5 -0
- package/dist/watch/strategies/mr-approval-optional.js +21 -0
- package/dist/watch/strategies/mr-approval-optional.js.map +1 -0
- package/dist/watch/strategies/mr-approved.d.ts +5 -0
- package/dist/watch/strategies/mr-approved.js +21 -0
- package/dist/watch/strategies/mr-approved.js.map +1 -0
- package/dist/watch/strategies/mr-conflicts.d.ts +5 -0
- package/dist/watch/strategies/mr-conflicts.js +21 -0
- package/dist/watch/strategies/mr-conflicts.js.map +1 -0
- package/dist/watch/strategies/mr-draft.d.ts +5 -0
- package/dist/watch/strategies/mr-draft.js +21 -0
- package/dist/watch/strategies/mr-draft.js.map +1 -0
- package/dist/watch/strategies/mr-open-comments.d.ts +5 -0
- package/dist/watch/strategies/mr-open-comments.js +21 -0
- package/dist/watch/strategies/mr-open-comments.js.map +1 -0
- package/dist/watch/strategies/narrative-missing.d.ts +5 -0
- package/dist/watch/strategies/narrative-missing.js +21 -0
- package/dist/watch/strategies/narrative-missing.js.map +1 -0
- package/dist/watch/strategies/no-mr.d.ts +5 -0
- package/dist/watch/strategies/no-mr.js +21 -0
- package/dist/watch/strategies/no-mr.js.map +1 -0
- package/dist/watch/strategies/pipeline-failed.d.ts +5 -0
- package/dist/watch/strategies/pipeline-failed.js +21 -0
- package/dist/watch/strategies/pipeline-failed.js.map +1 -0
- package/dist/watch/strategies/pipeline-running.d.ts +5 -0
- package/dist/watch/strategies/pipeline-running.js +21 -0
- package/dist/watch/strategies/pipeline-running.js.map +1 -0
- package/dist/watch/strategies/ready-for-release.d.ts +7 -0
- package/dist/watch/strategies/ready-for-release.js +35 -0
- package/dist/watch/strategies/ready-for-release.js.map +1 -0
- package/dist/watch/strategies/ready-to-commit.d.ts +5 -0
- package/dist/watch/strategies/ready-to-commit.js +21 -0
- package/dist/watch/strategies/ready-to-commit.js.map +1 -0
- package/dist/watch/strategies/ready-to-push.d.ts +5 -0
- package/dist/watch/strategies/ready-to-push.js +21 -0
- package/dist/watch/strategies/ready-to-push.js.map +1 -0
- package/dist/watch/strategies/released.d.ts +6 -0
- package/dist/watch/strategies/released.js +21 -0
- package/dist/watch/strategies/released.js.map +1 -0
- package/dist/watch/strategies/squash-merged.d.ts +6 -0
- package/dist/watch/strategies/squash-merged.js +21 -0
- package/dist/watch/strategies/squash-merged.js.map +1 -0
- package/dist/watch/strategies/types.d.ts +31 -0
- package/dist/watch/strategies/types.js +12 -0
- package/dist/watch/strategies/types.js.map +1 -0
- package/dist/watch/strategies/unstaged-changes.d.ts +5 -0
- package/dist/watch/strategies/unstaged-changes.js +21 -0
- package/dist/watch/strategies/unstaged-changes.js.map +1 -0
- package/dist/watch/strategies/wrong-branch.d.ts +6 -0
- package/dist/watch/strategies/wrong-branch.js +26 -0
- package/dist/watch/strategies/wrong-branch.js.map +1 -0
- package/dist/watch/types.d.ts +211 -0
- package/dist/watch/types.js +25 -0
- package/dist/watch/types.js.map +1 -0
- package/dist/watch/watcher-fs.d.ts +39 -0
- package/dist/watch/watcher-fs.js +105 -0
- package/dist/watch/watcher-fs.js.map +1 -0
- package/dist/watch/watcher-http.d.ts +19 -0
- package/dist/watch/watcher-http.js +47 -0
- package/dist/watch/watcher-http.js.map +1 -0
- package/dist/watch/watcher.d.ts +4 -0
- package/dist/watch/watcher.js +185 -0
- package/dist/watch/watcher.js.map +1 -0
- package/package.json +8 -2
- package/src/templates/about-watch.md +29 -0
- package/src/templates/hub.css +677 -0
- package/src/templates/hub.js +743 -0
- package/src/templates/qna.md +11 -0
- package/src/templates/steer.txt +2 -0
- package/src/templates/styles.css +53 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
2
|
+
/** Hub server — serves the dashboard UI and bridges watchers ↔ SSE. */
|
|
3
|
+
import { createServer } from 'node:http';
|
|
4
|
+
import { getPackageVersion } from '../lib/package-version.js';
|
|
5
|
+
import { generateDashboardHtml } from './dashboard.js';
|
|
6
|
+
import { getStrategyMetadata } from './strategies/index.js';
|
|
7
|
+
import { broadcast, gitlabMrs, gitlabWorkItems, jiraIssues, jsonResponse, MAX_EVENTS_PER_PROJECT, projectEvents, projectStates, readBody, sseClients, } from './hub-state.js';
|
|
8
|
+
import { logTime } from './watcher-http.js';
|
|
9
|
+
async function handleRequest(req, res) {
|
|
10
|
+
const url = req.url ?? '/';
|
|
11
|
+
const method = req.method ?? 'GET';
|
|
12
|
+
if (url === '/' && method === 'GET') {
|
|
13
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
14
|
+
res.end(await generateDashboardHtml());
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (url === '/_logbook/health' && method === 'GET') {
|
|
18
|
+
jsonResponse(res, 200, {
|
|
19
|
+
logbook: true,
|
|
20
|
+
version: getPackageVersion(),
|
|
21
|
+
projects: projectStates.size,
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (url === '/_logbook/strategies' && method === 'GET') {
|
|
26
|
+
jsonResponse(res, 200, getStrategyMetadata());
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (url === '/_logbook/jira-issues' && method === 'GET') {
|
|
30
|
+
jsonResponse(res, 200, [...jiraIssues.values()]);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (url === '/_logbook/jira-issues' && method === 'POST') {
|
|
34
|
+
const body = await readBody(req);
|
|
35
|
+
try {
|
|
36
|
+
const payload = JSON.parse(body);
|
|
37
|
+
if (Array.isArray(payload.issues)) {
|
|
38
|
+
const baseUrl = payload.issues[0]?.jiraBaseUrl;
|
|
39
|
+
if (baseUrl) {
|
|
40
|
+
for (const [key] of jiraIssues) {
|
|
41
|
+
if (key.startsWith(`${baseUrl}::`))
|
|
42
|
+
jiraIssues.delete(key);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const issue of payload.issues)
|
|
46
|
+
jiraIssues.set(`${issue.jiraBaseUrl}::${issue.key}`, issue);
|
|
47
|
+
}
|
|
48
|
+
jsonResponse(res, 200, { ok: true });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (url === '/_logbook/gitlab-mrs' && method === 'GET') {
|
|
56
|
+
jsonResponse(res, 200, [...gitlabMrs.values()]);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (url === '/_logbook/gitlab-mrs' && method === 'POST') {
|
|
60
|
+
const body = await readBody(req);
|
|
61
|
+
try {
|
|
62
|
+
const payload = JSON.parse(body);
|
|
63
|
+
if (Array.isArray(payload.mrs)) {
|
|
64
|
+
const projUrl = payload.mrs[0]?.projectUrl;
|
|
65
|
+
if (projUrl) {
|
|
66
|
+
for (const [key] of gitlabMrs) {
|
|
67
|
+
if (key.startsWith(`${projUrl}::`))
|
|
68
|
+
gitlabMrs.delete(key);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const mr of payload.mrs)
|
|
72
|
+
gitlabMrs.set(`${mr.projectUrl}::${mr.iid}`, mr);
|
|
73
|
+
}
|
|
74
|
+
jsonResponse(res, 200, { ok: true });
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (url === '/_logbook/gitlab-work-items' && method === 'GET') {
|
|
82
|
+
jsonResponse(res, 200, [...gitlabWorkItems.values()]);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (url === '/_logbook/gitlab-work-items' && method === 'POST') {
|
|
86
|
+
const body = await readBody(req);
|
|
87
|
+
try {
|
|
88
|
+
const payload = JSON.parse(body);
|
|
89
|
+
if (Array.isArray(payload.workItems)) {
|
|
90
|
+
const projUrl = payload.workItems[0]?.projectUrl;
|
|
91
|
+
if (projUrl) {
|
|
92
|
+
for (const [key] of gitlabWorkItems) {
|
|
93
|
+
if (key.startsWith(`${projUrl}::`))
|
|
94
|
+
gitlabWorkItems.delete(key);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const wi of payload.workItems)
|
|
98
|
+
gitlabWorkItems.set(`${wi.projectUrl}::${wi.iid}`, wi);
|
|
99
|
+
}
|
|
100
|
+
jsonResponse(res, 200, { ok: true });
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (url === '/_logbook/events' && method === 'GET') {
|
|
108
|
+
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });
|
|
109
|
+
res.write('\n');
|
|
110
|
+
sseClients.add(res);
|
|
111
|
+
const eventsObj = {};
|
|
112
|
+
for (const [path, events] of projectEvents)
|
|
113
|
+
eventsObj[path] = events;
|
|
114
|
+
res.write(`data: ${JSON.stringify({ type: 'full-state', projects: [...projectStates.values()], events: eventsObj })}\n\n`);
|
|
115
|
+
req.on('close', () => sseClients.delete(res));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (url === '/_logbook/register' && method === 'POST') {
|
|
119
|
+
const body = await readBody(req);
|
|
120
|
+
try {
|
|
121
|
+
const payload = JSON.parse(body);
|
|
122
|
+
if (!payload.projectPath || !payload.projectName) {
|
|
123
|
+
jsonResponse(res, 400, { error: 'projectPath and projectName required' });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (projectStates.has(payload.projectPath)) {
|
|
127
|
+
console.log(`[${logTime()}] WARNING: another watcher already registered for ${payload.projectPath} — its status updates will overwrite this one. Kill stale 'logbook watch' processes.`);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
projectStates.set(payload.projectPath, {
|
|
131
|
+
projectPath: payload.projectPath,
|
|
132
|
+
projectName: payload.projectName,
|
|
133
|
+
branch: undefined,
|
|
134
|
+
activeTicket: undefined,
|
|
135
|
+
latestLog: undefined,
|
|
136
|
+
statuses: [],
|
|
137
|
+
lastActivity: new Date().toISOString(),
|
|
138
|
+
details: undefined,
|
|
139
|
+
renderedStory: undefined,
|
|
140
|
+
renderedLog: undefined,
|
|
141
|
+
renderedTicket: undefined,
|
|
142
|
+
mrUrl: undefined,
|
|
143
|
+
mrStatus: undefined,
|
|
144
|
+
jiraStatus: undefined,
|
|
145
|
+
jiraBaseUrl: undefined,
|
|
146
|
+
gitlabBaseUrl: undefined,
|
|
147
|
+
repositoryUrl: undefined,
|
|
148
|
+
primaryColor: undefined,
|
|
149
|
+
agentName: undefined,
|
|
150
|
+
glabLastUpdated: undefined,
|
|
151
|
+
jiraLastUpdated: undefined,
|
|
152
|
+
});
|
|
153
|
+
broadcast({ type: 'status-update', project: projectStates.get(payload.projectPath) });
|
|
154
|
+
}
|
|
155
|
+
jsonResponse(res, 200, { ok: true });
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (url === '/_logbook/status' && method === 'POST') {
|
|
163
|
+
const body = await readBody(req);
|
|
164
|
+
try {
|
|
165
|
+
const status = JSON.parse(body);
|
|
166
|
+
if (!status.projectPath) {
|
|
167
|
+
jsonResponse(res, 400, { error: 'projectPath required' });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
projectStates.set(status.projectPath, status);
|
|
171
|
+
broadcast({ type: 'status-update', project: status });
|
|
172
|
+
jsonResponse(res, 200, { ok: true });
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (url === '/_logbook/deregister' && method === 'POST') {
|
|
180
|
+
const body = await readBody(req);
|
|
181
|
+
try {
|
|
182
|
+
const payload = JSON.parse(body);
|
|
183
|
+
if (payload.projectPath) {
|
|
184
|
+
projectStates.delete(payload.projectPath);
|
|
185
|
+
broadcast({ type: 'project-removed', projectPath: payload.projectPath });
|
|
186
|
+
}
|
|
187
|
+
jsonResponse(res, 200, { ok: true });
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (url === '/_logbook/event' && method === 'POST') {
|
|
195
|
+
const body = await readBody(req);
|
|
196
|
+
try {
|
|
197
|
+
const event = JSON.parse(body);
|
|
198
|
+
if (!event.projectPath || !event.description) {
|
|
199
|
+
jsonResponse(res, 400, { error: 'projectPath and description required' });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const events = projectEvents.get(event.projectPath) ?? [];
|
|
203
|
+
const normalize = (d) => d.replace(/^Logged:\s*/, '');
|
|
204
|
+
if (events.length > 0 && normalize(events[0].description) === normalize(event.description)) {
|
|
205
|
+
jsonResponse(res, 200, { ok: true });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
events.unshift({
|
|
209
|
+
timestamp: event.timestamp || new Date().toISOString(),
|
|
210
|
+
description: event.description,
|
|
211
|
+
source: event.source || 'unknown',
|
|
212
|
+
});
|
|
213
|
+
if (events.length > MAX_EVENTS_PER_PROJECT)
|
|
214
|
+
events.length = MAX_EVENTS_PER_PROJECT;
|
|
215
|
+
projectEvents.set(event.projectPath, events);
|
|
216
|
+
broadcast({ type: 'activity-event', projectPath: event.projectPath, event: events[0] });
|
|
217
|
+
jsonResponse(res, 200, { ok: true });
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
jsonResponse(res, 400, { error: 'Invalid JSON' });
|
|
221
|
+
}
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
res.writeHead(404);
|
|
225
|
+
res.end('Not Found');
|
|
226
|
+
}
|
|
227
|
+
export function startHub(port) {
|
|
228
|
+
const server = createServer((req, res) => {
|
|
229
|
+
handleRequest(req, res).catch(() => {
|
|
230
|
+
if (!res.headersSent) {
|
|
231
|
+
res.writeHead(500);
|
|
232
|
+
res.end('Internal Server Error');
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
const shutdown = () => {
|
|
237
|
+
for (const client of sseClients)
|
|
238
|
+
client.end();
|
|
239
|
+
sseClients.clear();
|
|
240
|
+
server.close();
|
|
241
|
+
};
|
|
242
|
+
process.once('SIGINT', shutdown);
|
|
243
|
+
process.once('SIGTERM', shutdown);
|
|
244
|
+
return new Promise((resolve, reject) => {
|
|
245
|
+
server.on('error', reject);
|
|
246
|
+
server.listen(port, '127.0.0.1', () => {
|
|
247
|
+
const addr = server.address();
|
|
248
|
+
resolve(`http://127.0.0.1:${typeof addr === 'object' && addr ? addr.port : port}`);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=hub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub.js","sourceRoot":"","sources":["../../src/watch/hub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared log file utilities for logbook watch collectors.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Extract the last timestamped log entry from a log.md file.
|
|
6
|
+
*
|
|
7
|
+
* @param logPath - Absolute path to the log.md file.
|
|
8
|
+
* @returns The last entry's message and timestamp, or undefined if none found.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getLastLogEntry(logPath: string): {
|
|
11
|
+
message: string;
|
|
12
|
+
timestamp: string;
|
|
13
|
+
} | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared log file utilities for logbook watch collectors.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
5
|
+
/**
|
|
6
|
+
* Extract the last timestamped log entry from a log.md file.
|
|
7
|
+
*
|
|
8
|
+
* @param logPath - Absolute path to the log.md file.
|
|
9
|
+
* @returns The last entry's message and timestamp, or undefined if none found.
|
|
10
|
+
*/
|
|
11
|
+
export function getLastLogEntry(logPath) {
|
|
12
|
+
if (!existsSync(logPath))
|
|
13
|
+
return undefined;
|
|
14
|
+
const content = readFileSync(logPath, 'utf8');
|
|
15
|
+
const lines = content.split('\n').filter(Boolean).reverse();
|
|
16
|
+
for (const line of lines) {
|
|
17
|
+
const match = line.match(/^-\s+(\d{4}-\d{2}-\d{2}T[^:]+:[^:]+:[^:]+Z):\s+(.+)$/);
|
|
18
|
+
if (match) {
|
|
19
|
+
return { timestamp: match[1], message: match[2] };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=log-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-utils.js","sourceRoot":"","sources":["../../src/watch/log-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;QACjF,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hub notification helper for logbook commands.
|
|
3
|
+
*
|
|
4
|
+
* Provides a fire-and-forget function that commands (log, start, release, etc.)
|
|
5
|
+
* call to push activity events directly to the running hub. If no hub is
|
|
6
|
+
* running, the call silently no-ops — commands never fail because of watch.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Notify the logbook watch hub of a command activity event.
|
|
10
|
+
*
|
|
11
|
+
* This is fire-and-forget: if the hub is not running or the request fails,
|
|
12
|
+
* it resolves silently. Commands should never block or fail because of this.
|
|
13
|
+
*
|
|
14
|
+
* @param projectPath - Absolute path to the project root.
|
|
15
|
+
* @param description - Short description of what happened (e.g., "Logged: fixed auth bug").
|
|
16
|
+
* @param source - The command name that triggered this (e.g., "logbook log").
|
|
17
|
+
*/
|
|
18
|
+
export declare function notifyHub(projectPath: string, description: string, source: string): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hub notification helper for logbook commands.
|
|
3
|
+
*
|
|
4
|
+
* Provides a fire-and-forget function that commands (log, start, release, etc.)
|
|
5
|
+
* call to push activity events directly to the running hub. If no hub is
|
|
6
|
+
* running, the call silently no-ops — commands never fail because of watch.
|
|
7
|
+
*/
|
|
8
|
+
import { request } from 'node:http';
|
|
9
|
+
import { resolveWatchPort } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Notify the logbook watch hub of a command activity event.
|
|
12
|
+
*
|
|
13
|
+
* This is fire-and-forget: if the hub is not running or the request fails,
|
|
14
|
+
* it resolves silently. Commands should never block or fail because of this.
|
|
15
|
+
*
|
|
16
|
+
* @param projectPath - Absolute path to the project root.
|
|
17
|
+
* @param description - Short description of what happened (e.g., "Logged: fixed auth bug").
|
|
18
|
+
* @param source - The command name that triggered this (e.g., "logbook log").
|
|
19
|
+
*/
|
|
20
|
+
export function notifyHub(projectPath, description, source) {
|
|
21
|
+
const body = JSON.stringify({
|
|
22
|
+
projectPath,
|
|
23
|
+
description,
|
|
24
|
+
source,
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
});
|
|
27
|
+
const req = request({
|
|
28
|
+
hostname: '127.0.0.1',
|
|
29
|
+
port: resolveWatchPort(),
|
|
30
|
+
path: '/_logbook/event',
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
'Content-Length': Buffer.byteLength(body),
|
|
35
|
+
},
|
|
36
|
+
timeout: 1000,
|
|
37
|
+
}, (res) => {
|
|
38
|
+
res.resume();
|
|
39
|
+
});
|
|
40
|
+
req.on('error', () => { });
|
|
41
|
+
req.on('timeout', () => req.destroy());
|
|
42
|
+
req.write(body);
|
|
43
|
+
req.end();
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/watch/notify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,WAAmB,EAAE,MAAc;IAChF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,WAAW;QACX,WAAW;QACX,MAAM;QACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,OAAO,CACjB;QACE,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,gBAAgB,EAAE;QACxB,IAAI,EAAE,iBAAiB;QACvB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;SAC1C;QACD,OAAO,EAAE,IAAI;KACd,EACD,CAAC,GAAG,EAAE,EAAE;QACN,GAAG,CAAC,MAAM,EAAE,CAAC;IACf,CAAC,CACF,CAAC;IAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC1B,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChB,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared watcher state for logbook watch.
|
|
3
|
+
*
|
|
4
|
+
* This is the single source of truth that collectors write to and strategies
|
|
5
|
+
* read from. Each field is optional — a collector populates its subset, and
|
|
6
|
+
* strategies handle missing data gracefully (undefined = not available).
|
|
7
|
+
*
|
|
8
|
+
* The state is mutable. Collectors update it in-place on their own schedule.
|
|
9
|
+
* After any collector runs, strategies are re-evaluated against the current
|
|
10
|
+
* snapshot.
|
|
11
|
+
*/
|
|
12
|
+
import type { GitLabMr, GitLabWorkItem, JiraIssue, WatcherMetrics } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* The mutable watcher state. Extends WatcherMetrics with fields for future
|
|
15
|
+
* collectors (glab, acli, etc.).
|
|
16
|
+
*/
|
|
17
|
+
export interface WatcherState extends WatcherMetrics {
|
|
18
|
+
/** MR title if one exists. */
|
|
19
|
+
mrTitle?: string;
|
|
20
|
+
/** All open MRs for the project (for GitLab tab). */
|
|
21
|
+
glabOpenMrs?: GitLabMr[];
|
|
22
|
+
/** All open work items for the project (for GitLab Work Items tab). */
|
|
23
|
+
glabWorkItems?: GitLabWorkItem[];
|
|
24
|
+
/** Jira ticket assignee. */
|
|
25
|
+
jiraAssignee?: string;
|
|
26
|
+
/** All Jira issues assigned to the current user (for Jira tab). */
|
|
27
|
+
jiraAssignedIssues?: JiraIssue[];
|
|
28
|
+
/** ISO timestamp of last successful GitLab collector run. */
|
|
29
|
+
glabLastUpdated?: string;
|
|
30
|
+
/** ISO timestamp of last successful GitLab work items run. */
|
|
31
|
+
glabWorkItemsLastUpdated?: string;
|
|
32
|
+
/** ISO timestamp of last successful Jira collector run. */
|
|
33
|
+
jiraLastUpdated?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Create a fresh empty state with safe defaults.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createEmptyState(): WatcherState;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared watcher state for logbook watch.
|
|
3
|
+
*
|
|
4
|
+
* This is the single source of truth that collectors write to and strategies
|
|
5
|
+
* read from. Each field is optional — a collector populates its subset, and
|
|
6
|
+
* strategies handle missing data gracefully (undefined = not available).
|
|
7
|
+
*
|
|
8
|
+
* The state is mutable. Collectors update it in-place on their own schedule.
|
|
9
|
+
* After any collector runs, strategies are re-evaluated against the current
|
|
10
|
+
* snapshot.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Create a fresh empty state with safe defaults.
|
|
14
|
+
*/
|
|
15
|
+
export function createEmptyState() {
|
|
16
|
+
return {
|
|
17
|
+
branch: undefined,
|
|
18
|
+
defaultBranch: 'main',
|
|
19
|
+
hasActiveTicket: false,
|
|
20
|
+
activeTicketId: undefined,
|
|
21
|
+
activeTicketSlug: undefined,
|
|
22
|
+
latestLog: undefined,
|
|
23
|
+
latestLogTimestamp: undefined,
|
|
24
|
+
isDirty: false,
|
|
25
|
+
stagedFiles: 0,
|
|
26
|
+
unstagedFiles: 0,
|
|
27
|
+
isAheadOfRemote: false,
|
|
28
|
+
hasNarrativePlaceholders: false,
|
|
29
|
+
isReleased: false,
|
|
30
|
+
hasLockfile: false,
|
|
31
|
+
isSquashMerged: false,
|
|
32
|
+
commitsBehindDefault: 0,
|
|
33
|
+
lastActivityTimestamp: new Date().toISOString(),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/watch/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgCH;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,aAAa,EAAE,MAAM;QACrB,eAAe,EAAE,KAAK;QACtB,cAAc,EAAE,SAAS;QACzB,gBAAgB,EAAE,SAAS;QAC3B,SAAS,EAAE,SAAS;QACpB,kBAAkB,EAAE,SAAS;QAC7B,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,CAAC;QACd,aAAa,EAAE,CAAC;QAChB,eAAe,EAAE,KAAK;QACtB,wBAAwB,EAAE,KAAK;QAC/B,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,KAAK;QAClB,cAAc,EAAE,KAAK;QACrB,oBAAoB,EAAE,CAAC;QACvB,qBAAqB,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAChD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behind Default — the current branch is behind the default branch.
|
|
3
|
+
*/
|
|
4
|
+
export const behindDefaultCheck = {
|
|
5
|
+
id: 'behind-default',
|
|
6
|
+
source: 'Git',
|
|
7
|
+
description: 'The current branch is behind the default branch. Consider rebasing or merging.',
|
|
8
|
+
blockedBy: ['squash-merged', 'released'],
|
|
9
|
+
check(metrics) {
|
|
10
|
+
if (metrics.commitsBehindDefault > 0) {
|
|
11
|
+
return {
|
|
12
|
+
id: 'behind-default',
|
|
13
|
+
label: 'Behind Default',
|
|
14
|
+
severity: 'warning',
|
|
15
|
+
detail: `${metrics.commitsBehindDefault} commit${metrics.commitsBehindDefault !== 1 ? 's' : ''} behind ${metrics.defaultBranch}`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=behind-default.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behind-default.js","sourceRoot":"","sources":["../../../src/watch/strategies/behind-default.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAmB;IAChD,EAAE,EAAE,gBAAgB;IACpB,MAAM,EAAE,KAAK;IACb,WAAW,EAAE,gFAAgF;IAC7F,SAAS,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC;IACxC,KAAK,CAAC,OAAO;QACX,IAAI,OAAO,CAAC,oBAAoB,GAAG,CAAC,EAAE,CAAC;YACrC,OAAO;gBACL,EAAE,EAAE,gBAAgB;gBACpB,KAAK,EAAE,gBAAgB;gBACvB,QAAQ,EAAE,SAAS;gBACnB,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,UAAU,OAAO,CAAC,oBAAoB,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,OAAO,CAAC,aAAa,EAAE;aACjI,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idle — no active ticket and no dirty state.
|
|
3
|
+
*/
|
|
4
|
+
export const idleCheck = {
|
|
5
|
+
id: 'idle',
|
|
6
|
+
source: 'LOGBOOK',
|
|
7
|
+
description: 'No active ticket and no uncommitted changes.',
|
|
8
|
+
blockedBy: ['squash-merged', 'released'],
|
|
9
|
+
check(metrics) {
|
|
10
|
+
if (!metrics.hasActiveTicket && !metrics.isDirty) {
|
|
11
|
+
return {
|
|
12
|
+
id: 'idle',
|
|
13
|
+
label: 'Idle',
|
|
14
|
+
severity: 'info',
|
|
15
|
+
detail: 'No active ticket. All clean.',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=idle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idle.js","sourceRoot":"","sources":["../../../src/watch/strategies/idle.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAmB;IACvC,EAAE,EAAE,MAAM;IACV,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,8CAA8C;IAC3D,SAAS,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC;IACxC,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,OAAO,CAAC,eAAe,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACjD,OAAO;gBACL,EAAE,EAAE,MAAM;gBACV,KAAK,EAAE,MAAM;gBACb,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,8BAA8B;aACvC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In Progress — an active ticket is present but no other blocking state.
|
|
3
|
+
*/
|
|
4
|
+
export const inProgressCheck = {
|
|
5
|
+
id: 'in-progress',
|
|
6
|
+
source: 'LOGBOOK',
|
|
7
|
+
description: 'An active ticket is present and work is in progress.',
|
|
8
|
+
blockedBy: ['squash-merged', 'released'],
|
|
9
|
+
check(metrics) {
|
|
10
|
+
if (metrics.hasActiveTicket) {
|
|
11
|
+
return {
|
|
12
|
+
id: 'in-progress',
|
|
13
|
+
label: 'In Progress',
|
|
14
|
+
severity: 'info',
|
|
15
|
+
detail: `Working on ${metrics.activeTicketId ?? metrics.activeTicketSlug ?? 'unknown'}`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=in-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-progress.js","sourceRoot":"","sources":["../../../src/watch/strategies/in-progress.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAmB;IAC7C,EAAE,EAAE,aAAa;IACjB,MAAM,EAAE,SAAS;IACjB,WAAW,EAAE,sDAAsD;IACnE,SAAS,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC;IACxC,KAAK,CAAC,OAAO;QACX,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC5B,OAAO;gBACL,EAAE,EAAE,aAAa;gBACjB,KAAK,EAAE,aAAa;gBACpB,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,cAAc,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,gBAAgB,IAAI,SAAS,EAAE;aACxF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy registry and evaluator for logbook watch.
|
|
3
|
+
*
|
|
4
|
+
* Strategies are evaluated in declared order. The `blockedBy` mechanism
|
|
5
|
+
* suppresses a strategy if any of its listed blocker IDs are already active.
|
|
6
|
+
*/
|
|
7
|
+
import type { StatusResult, StatusSeverity, WatcherMetrics } from '../types.js';
|
|
8
|
+
import type { StrategySource } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Evaluate all strategies against the given metrics.
|
|
11
|
+
*
|
|
12
|
+
* Strategies are evaluated in order. If a strategy declares `blockedBy` IDs
|
|
13
|
+
* and any of those are already in the results, that strategy is suppressed.
|
|
14
|
+
*
|
|
15
|
+
* @param metrics - The collected watcher metrics.
|
|
16
|
+
* @returns All applicable, non-blocked status results.
|
|
17
|
+
*/
|
|
18
|
+
export declare function evaluateStatuses(metrics: WatcherMetrics): StatusResult[];
|
|
19
|
+
/** Static metadata for a strategy (used by the Help tab API). */
|
|
20
|
+
interface StrategyMeta {
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
severity: StatusSeverity;
|
|
24
|
+
source: StrategySource;
|
|
25
|
+
description: string;
|
|
26
|
+
blockedBy: string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get static metadata for all registered strategies (for Help tab API).
|
|
30
|
+
*
|
|
31
|
+
* @returns Array of strategy metadata objects sorted by source then severity.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getStrategyMetadata(): StrategyMeta[];
|
|
34
|
+
export {};
|