project-logbook 1.3.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/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 +18 -2
- 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/status.js +3 -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/index.js +37 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.js +10 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/template-helpers.d.ts +2 -1
- package/dist/lib/template-helpers.js +29 -0
- package/dist/lib/template-helpers.js.map +1 -1
- package/dist/lib/template-types.d.ts +12 -0
- package/dist/lib/templates.js +9 -1
- 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/qna.d.ts +3 -0
- package/dist/linters/qna.js +120 -0
- package/dist/linters/qna.js.map +1 -0
- package/dist/templates/hub.js +123 -8
- package/dist/templates/qna.md +11 -0
- package/dist/templates/steer.txt +2 -0
- package/dist/templates/styles.css +53 -0
- 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/collectors/acli.js +2 -2
- package/dist/watch/collectors/acli.js.map +1 -1
- package/dist/watch/collectors/entries.js +3 -3
- package/dist/watch/collectors/entries.js.map +1 -1
- package/dist/watch/collectors/glab.js +126 -37
- package/dist/watch/collectors/glab.js.map +1 -1
- package/dist/watch/collectors/jira.js +3 -2
- package/dist/watch/collectors/jira.js.map +1 -1
- package/dist/watch/dashboard-html.js +8 -0
- package/dist/watch/dashboard-html.js.map +1 -1
- package/dist/watch/git-utils.d.ts +10 -4
- package/dist/watch/git-utils.js +22 -6
- package/dist/watch/git-utils.js.map +1 -1
- package/dist/watch/hub-state.d.ts +3 -1
- package/dist/watch/hub-state.js +2 -0
- package/dist/watch/hub-state.js.map +1 -1
- package/dist/watch/hub.js +35 -2
- package/dist/watch/hub.js.map +1 -1
- package/dist/watch/state.d.ts +5 -1
- package/dist/watch/state.js.map +1 -1
- package/dist/watch/types.d.ts +21 -0
- package/dist/watch/types.js.map +1 -1
- package/dist/watch/watcher.js +13 -2
- package/dist/watch/watcher.js.map +1 -1
- package/package.json +7 -2
- package/src/templates/hub.js +123 -8
- package/src/templates/qna.md +11 -0
- package/src/templates/steer.txt +2 -0
- package/src/templates/styles.css +53 -0
package/dist/lib/templates.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ATTR_PAGE_SLUG } from './html-attributes.js';
|
|
2
2
|
import { escapeHtml } from './html-escape.js';
|
|
3
|
-
import { html, renderTimelineEntryItem, renderTimelineCommitItem, renderTimelineTagItem, renderTimelineAdrItem, paginationLinks, } from './template-helpers.js';
|
|
3
|
+
import { html, renderTimelineEntryItem, renderTimelineCommitItem, renderTimelineTagItem, renderTimelineAdrItem, renderQnaCard, paginationLinks, } from './template-helpers.js';
|
|
4
4
|
import { renderCustomCard } from './custom-card-renderer.js';
|
|
5
5
|
import { autolinkReferences, getRegisteredResearchEntries, linkGitlabReferences } from './autolink.js';
|
|
6
6
|
export { postTemplate } from './post-template.js';
|
|
@@ -96,6 +96,14 @@ export const timelineTemplate = (props) => {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
+
if (props.qnaItems && props.qnaItems.length > 0) {
|
|
100
|
+
const unansweredCount = props.qnaItems.filter((q) => q.status === 'asked').length;
|
|
101
|
+
const tabTitle = unansweredCount > 0 ? `QnA (${unansweredCount})` : 'QnA';
|
|
102
|
+
const qnaTabHtml = html `
|
|
103
|
+
<div class="timeline">${props.qnaItems.map((item) => renderQnaCard(item)).join('')}</div>
|
|
104
|
+
`;
|
|
105
|
+
tabs.push({ id: 'qna', title: tabTitle, content: qnaTabHtml });
|
|
106
|
+
}
|
|
99
107
|
tabs.push({ id: 'readme', title: 'Project Readme', content: readmeHtml || '<p>No README available.</p>' }, { id: 'about', title: 'About this Logbook', content: aboutHtml || '<p>No information available.</p>' });
|
|
100
108
|
const { tabsHtml, sectionsHtml } = tabsComponent(tabs, 0);
|
|
101
109
|
const header = html `<header>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/lib/templates.ts"],"names":[],"mappings":"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"}
|
package/dist/linters/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import links from './links.js';
|
|
|
5
5
|
import lockfile from './lockfile.js';
|
|
6
6
|
import placeholders from './placeholders.js';
|
|
7
7
|
import projectIntegrity from './project-integrity.js';
|
|
8
|
+
import qna from './qna.js';
|
|
8
9
|
import readability from './readability.js';
|
|
9
10
|
import technicalLog from './technical-log.js';
|
|
10
11
|
import workspaces from './workspaces.js';
|
|
@@ -16,6 +17,7 @@ export const linters = [
|
|
|
16
17
|
lockfile,
|
|
17
18
|
placeholders,
|
|
18
19
|
projectIntegrity,
|
|
20
|
+
qna,
|
|
19
21
|
readability,
|
|
20
22
|
technicalLog,
|
|
21
23
|
workspaces,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/linters/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,wBAAwB,CAAC;AACrD,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,gBAAgB,MAAM,wBAAwB,CAAC;AACtD,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAEzC,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,eAAe;IACf,WAAW;IACX,UAAU;IACV,KAAK;IACL,QAAQ;IACR,YAAY;IACZ,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,UAAU;CACX,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/linters/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,wBAAwB,CAAC;AACrD,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,gBAAgB,MAAM,wBAAwB,CAAC;AACtD,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAEzC,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,eAAe;IACf,WAAW;IACX,UAAU;IACV,KAAK;IACL,QAAQ;IACR,YAAY;IACZ,gBAAgB;IAChB,GAAG;IACH,WAAW;IACX,YAAY;IACZ,UAAU;CACX,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
import { getQnaDirPath } from '../lib/config.js';
|
|
5
|
+
import { parseQnaContent } from '../utils/qna.js';
|
|
6
|
+
const linter = {
|
|
7
|
+
name: 'qna',
|
|
8
|
+
description: 'Validates QnA file naming, frontmatter, and mandatory subtitles',
|
|
9
|
+
async check(context) {
|
|
10
|
+
if (context.entryName)
|
|
11
|
+
return [];
|
|
12
|
+
const issues = [];
|
|
13
|
+
const qnaDir = getQnaDirPath(context.config) || join(process.cwd(), 'docs/qna');
|
|
14
|
+
if (!(await fs.pathExists(qnaDir))) {
|
|
15
|
+
return issues;
|
|
16
|
+
}
|
|
17
|
+
const files = await fs.readdir(qnaDir);
|
|
18
|
+
for (const file of files) {
|
|
19
|
+
const filePath = join(qnaDir, file);
|
|
20
|
+
const stat = await fs.stat(filePath);
|
|
21
|
+
if (stat.isDirectory())
|
|
22
|
+
continue;
|
|
23
|
+
if (!file.endsWith('.md')) {
|
|
24
|
+
issues.push({
|
|
25
|
+
level: 'warning',
|
|
26
|
+
category: 'qna',
|
|
27
|
+
message: `${file}: Unexpected non-markdown file in QnA directory.`,
|
|
28
|
+
});
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!/^\d{5}-[\w-]+\.md$/.test(file)) {
|
|
32
|
+
issues.push({
|
|
33
|
+
level: 'error',
|
|
34
|
+
category: 'qna',
|
|
35
|
+
message: `${file}: File name must match format '00001-question-slug.md'`,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const raw = await fs.readFile(filePath, 'utf8');
|
|
40
|
+
const { data, content } = matter(raw);
|
|
41
|
+
if (data.id === undefined || typeof data.id !== 'number') {
|
|
42
|
+
issues.push({
|
|
43
|
+
level: 'error',
|
|
44
|
+
category: 'qna',
|
|
45
|
+
message: `${file}: Missing or invalid numeric 'id' in frontmatter.`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const validStatuses = ['asked', 'answered', 'deprecated'];
|
|
49
|
+
if (!data.status || !validStatuses.includes(String(data.status))) {
|
|
50
|
+
issues.push({
|
|
51
|
+
level: 'error',
|
|
52
|
+
category: 'qna',
|
|
53
|
+
message: `${file}: 'status' must be one of: asked, answered, deprecated.`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (!data.dateAsked) {
|
|
57
|
+
issues.push({
|
|
58
|
+
level: 'error',
|
|
59
|
+
category: 'qna',
|
|
60
|
+
message: `${file}: Missing required 'dateAsked' in frontmatter.`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (data.status === 'answered' && !data.dateAnswered) {
|
|
64
|
+
issues.push({
|
|
65
|
+
level: 'error',
|
|
66
|
+
category: 'qna',
|
|
67
|
+
message: `${file}: 'dateAnswered' is required when status is 'answered'.`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (data.status === 'deprecated' && !data.dateDeprecated) {
|
|
71
|
+
issues.push({
|
|
72
|
+
level: 'error',
|
|
73
|
+
category: 'qna',
|
|
74
|
+
message: `${file}: 'dateDeprecated' is required when status is 'deprecated'.`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// Subtitle checks (markdown subtitles are mandatory)
|
|
78
|
+
if (!/###\s+Question/i.test(content)) {
|
|
79
|
+
issues.push({
|
|
80
|
+
level: 'error',
|
|
81
|
+
category: 'qna',
|
|
82
|
+
message: `${file}: Mandatory subtitle '### Question' is missing.`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (!/###\s+Answer/i.test(content)) {
|
|
86
|
+
issues.push({
|
|
87
|
+
level: 'error',
|
|
88
|
+
category: 'qna',
|
|
89
|
+
message: `${file}: Mandatory subtitle '### Answer' is missing.`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const { question, answer } = parseQnaContent(content);
|
|
93
|
+
if (!question) {
|
|
94
|
+
issues.push({
|
|
95
|
+
level: 'error',
|
|
96
|
+
category: 'qna',
|
|
97
|
+
message: `${file}: Question content under '### Question' cannot be empty.`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (data.status === 'answered' && !answer) {
|
|
101
|
+
issues.push({
|
|
102
|
+
level: 'error',
|
|
103
|
+
category: 'qna',
|
|
104
|
+
message: `${file}: Answer content under '### Answer' is empty for answered question.`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
issues.push({
|
|
110
|
+
level: 'error',
|
|
111
|
+
category: 'qna',
|
|
112
|
+
message: `${file}: Failed to parse markdown/frontmatter: ${err instanceof Error ? err.message : String(err)}`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return issues;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
export default linter;
|
|
120
|
+
//# sourceMappingURL=qna.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qna.js","sourceRoot":"","sources":["../../src/linters/qna.ts"],"names":[],"mappings":"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"}
|
package/dist/templates/hub.js
CHANGED
|
@@ -176,8 +176,12 @@
|
|
|
176
176
|
|
|
177
177
|
function renderTicketMeta(p) {
|
|
178
178
|
var ticket = p.activeTicket || 'none';
|
|
179
|
-
var
|
|
180
|
-
|
|
179
|
+
var isGl = ticket.charAt(0) === '#' && p.gitlabBaseUrl;
|
|
180
|
+
var ticketUrl = isGl
|
|
181
|
+
? p.gitlabBaseUrl.replace(/\/+$/, '') +
|
|
182
|
+
'/' +
|
|
183
|
+
encodeURIComponent(ticket.replace(/^#/, '').match(/^\d+/)?.[0] || ticket)
|
|
184
|
+
: p.jiraBaseUrl && p.activeTicket
|
|
181
185
|
? p.jiraBaseUrl.replace(/\/+$/, '') + '/browse/' + encodeURIComponent(p.activeTicket)
|
|
182
186
|
: null;
|
|
183
187
|
var value = ticketUrl
|
|
@@ -187,7 +191,7 @@
|
|
|
187
191
|
escapeHtml(ticket) +
|
|
188
192
|
'<span class="link-icon">\u00A0↗</span></a>'
|
|
189
193
|
: escapeHtml(ticket);
|
|
190
|
-
var jiraLabel = p.jiraStatus ? ' <span class="jira-status">' + escapeHtml(p.jiraStatus) + '</span>' : '';
|
|
194
|
+
var jiraLabel = !isGl && p.jiraStatus ? ' <span class="jira-status">' + escapeHtml(p.jiraStatus) + '</span>' : '';
|
|
191
195
|
return (
|
|
192
196
|
'<div class="meta-item"><span class="meta-label">ticket:</span> <span class="meta-value">' +
|
|
193
197
|
value +
|
|
@@ -506,10 +510,16 @@
|
|
|
506
510
|
html +=
|
|
507
511
|
'<table class="help-table"><thead><tr><th>Title</th><th>Status</th><th>Comments</th><th>Branch</th></tr></thead><tbody>';
|
|
508
512
|
items.forEach(function (m) {
|
|
509
|
-
var statusBadge
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
+
var statusBadge;
|
|
514
|
+
if (m.status === 'draft') {
|
|
515
|
+
statusBadge = '<span class="badge badge-info">Draft</span>';
|
|
516
|
+
} else if (m.status === 'merged') {
|
|
517
|
+
statusBadge = '<span class="badge badge-success">Merged</span>';
|
|
518
|
+
} else if (m.status === 'closed') {
|
|
519
|
+
statusBadge = '<span class="badge badge-warning">Closed</span>';
|
|
520
|
+
} else {
|
|
521
|
+
statusBadge = '<span class="badge badge-info">Open</span>';
|
|
522
|
+
}
|
|
513
523
|
var branchUrl = projUrl ? projUrl.replace(/\/$/, '') + '/-/tree/' + encodeURIComponent(m.sourceBranch) : '';
|
|
514
524
|
var branchCell = branchUrl
|
|
515
525
|
? '<a class="meta-link" href="' +
|
|
@@ -553,6 +563,87 @@
|
|
|
553
563
|
loadGitLabMrs();
|
|
554
564
|
setInterval(loadGitLabMrs, 5 * 60 * 1000);
|
|
555
565
|
|
|
566
|
+
// --- GitLab Work Items tab ---
|
|
567
|
+
function loadWorkItems() {
|
|
568
|
+
fetch('/_logbook/gitlab-work-items')
|
|
569
|
+
.then(function (r) {
|
|
570
|
+
return r.json();
|
|
571
|
+
})
|
|
572
|
+
.then(function (items) {
|
|
573
|
+
var container = document.getElementById('workitems-content');
|
|
574
|
+
var countEl4 = document.getElementById('workitems-count');
|
|
575
|
+
var count = items ? items.length : 0;
|
|
576
|
+
countEl4.textContent = count;
|
|
577
|
+
countEl4.style.display = count > 0 ? '' : 'none';
|
|
578
|
+
if (!items || items.length === 0) {
|
|
579
|
+
container.innerHTML =
|
|
580
|
+
'<div class="placeholder-msg">No open work items found.<br>Install the <code>glab</code> CLI and run <code>glab auth login</code> to connect.</div>';
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
var grouped = {};
|
|
584
|
+
items.forEach(function (w) {
|
|
585
|
+
if (!grouped[w.projectUrl]) grouped[w.projectUrl] = [];
|
|
586
|
+
grouped[w.projectUrl].push(w);
|
|
587
|
+
});
|
|
588
|
+
var html = '';
|
|
589
|
+
for (var projUrl in grouped) {
|
|
590
|
+
if (!grouped.hasOwnProperty(projUrl)) continue;
|
|
591
|
+
var wis = grouped[projUrl];
|
|
592
|
+
var fullName = wis[0].projectName || projUrl;
|
|
593
|
+
var projName = fullName.includes(' / ') ? fullName.split(' / ').pop() : fullName;
|
|
594
|
+
html +=
|
|
595
|
+
'<h3 class="group-heading">' +
|
|
596
|
+
'<a href="' +
|
|
597
|
+
escapeHtml(projUrl) +
|
|
598
|
+
'" target="_blank" rel="noopener">' +
|
|
599
|
+
escapeHtml(projName) +
|
|
600
|
+
'<span class="group-link-icon"> ↗</span></a></h3>';
|
|
601
|
+
html +=
|
|
602
|
+
'<table class="help-table"><thead><tr><th>#</th><th>Summary</th><th>State</th><th>Last Update</th></tr></thead><tbody>';
|
|
603
|
+
wis.forEach(function (w) {
|
|
604
|
+
var titleCell = w.url
|
|
605
|
+
? '<a class="meta-link" href="' +
|
|
606
|
+
escapeHtml(w.url) +
|
|
607
|
+
'" target="_blank" rel="noopener">' +
|
|
608
|
+
escapeHtml(w.title) +
|
|
609
|
+
'<span class="link-icon">\u00A0↗</span></a>'
|
|
610
|
+
: escapeHtml(w.title);
|
|
611
|
+
var stateBadge =
|
|
612
|
+
w.status === 'opened'
|
|
613
|
+
? '<span class="badge badge-info">Open</span>'
|
|
614
|
+
: '<span class="badge badge-' +
|
|
615
|
+
(w.status === 'closed' ? 'success' : 'warning') +
|
|
616
|
+
'">' +
|
|
617
|
+
escapeHtml(w.status) +
|
|
618
|
+
'</span>';
|
|
619
|
+
html +=
|
|
620
|
+
'<tr>' +
|
|
621
|
+
'<td class="cell-mono">#' +
|
|
622
|
+
w.iid +
|
|
623
|
+
'</td>' +
|
|
624
|
+
'<td>' +
|
|
625
|
+
titleCell +
|
|
626
|
+
'</td>' +
|
|
627
|
+
'<td>' +
|
|
628
|
+
stateBadge +
|
|
629
|
+
'</td>' +
|
|
630
|
+
'<td class="cell-time">' +
|
|
631
|
+
relativeTime(w.updated) +
|
|
632
|
+
'</td>' +
|
|
633
|
+
'</tr>';
|
|
634
|
+
});
|
|
635
|
+
html += '</tbody></table>';
|
|
636
|
+
}
|
|
637
|
+
container.innerHTML = html;
|
|
638
|
+
})
|
|
639
|
+
.catch(function () {
|
|
640
|
+
document.getElementById('workitems-content').innerHTML =
|
|
641
|
+
'<div class="placeholder-msg">Failed to load work items.</div>';
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
loadWorkItems();
|
|
645
|
+
setInterval(loadWorkItems, 5 * 60 * 1000);
|
|
646
|
+
|
|
556
647
|
// --- SSE connection ---
|
|
557
648
|
function connect() {
|
|
558
649
|
var es = new EventSource('/_logbook/events');
|
|
@@ -565,6 +656,20 @@
|
|
|
565
656
|
var data = JSON.parse(e.data);
|
|
566
657
|
if (data.type === 'status-update') {
|
|
567
658
|
projects[data.project.projectPath] = data.project;
|
|
659
|
+
console.log(
|
|
660
|
+
'[logbook-debug] status-update',
|
|
661
|
+
data.project.projectPath,
|
|
662
|
+
'mrStatus=',
|
|
663
|
+
data.project.mrStatus,
|
|
664
|
+
'mrUrl=',
|
|
665
|
+
data.project.mrUrl,
|
|
666
|
+
'statuses=',
|
|
667
|
+
(data.project.statuses || [])
|
|
668
|
+
.map(function (s) {
|
|
669
|
+
return s.id;
|
|
670
|
+
})
|
|
671
|
+
.join(','),
|
|
672
|
+
);
|
|
568
673
|
renderProjects();
|
|
569
674
|
updateTabFooters();
|
|
570
675
|
} else if (data.type === 'project-removed') {
|
|
@@ -572,7 +677,17 @@
|
|
|
572
677
|
delete projectEvents[data.projectPath];
|
|
573
678
|
renderProjects();
|
|
574
679
|
} else if (data.type === 'full-state') {
|
|
575
|
-
for (var i = 0; i < data.projects.length; i++)
|
|
680
|
+
for (var i = 0; i < data.projects.length; i++) {
|
|
681
|
+
projects[data.projects[i].projectPath] = data.projects[i];
|
|
682
|
+
console.log(
|
|
683
|
+
'[logbook-debug] full-state',
|
|
684
|
+
data.projects[i].projectPath,
|
|
685
|
+
'mrStatus=',
|
|
686
|
+
data.projects[i].mrStatus,
|
|
687
|
+
'mrUrl=',
|
|
688
|
+
data.projects[i].mrUrl,
|
|
689
|
+
);
|
|
690
|
+
}
|
|
576
691
|
if (data.events)
|
|
577
692
|
for (var path in data.events) {
|
|
578
693
|
if (data.events.hasOwnProperty(path)) projectEvents[path] = data.events[path];
|
package/dist/templates/steer.txt
CHANGED
|
@@ -6,6 +6,7 @@ Do NOT run `logbook new` or `logbook release` — these are prompter responsibil
|
|
|
6
6
|
Phase 1: Understand
|
|
7
7
|
1. Read `ticket.md` in the active entry. This is your source of truth for requirements.
|
|
8
8
|
2. Review `AGENTS.md` and `CONTRIBUTING.md` if you need architectural or workflow context.
|
|
9
|
+
3. Check existing QnAs with `logbook answers` or check open questions with `logbook unanswered`.
|
|
9
10
|
|
|
10
11
|
Phase 2: Execute & Trace
|
|
11
12
|
|
|
@@ -29,6 +30,7 @@ You MUST log your work continuously using `logbook log "<message>"`. This is not
|
|
|
29
30
|
3. **One message per command call.** For multiple entries, call the command multiple times.
|
|
30
31
|
4. Do NOT reconstruct the log at the end. If the log is empty when you finish, you did it wrong.
|
|
31
32
|
5. Stick to the active entry; never modify past entries in the logbook folder.
|
|
33
|
+
6. For short technical questions and findings, record them via `logbook ask "<question>"` and resolve them with `logbook answer <id> "<answer>"`.
|
|
32
34
|
|
|
33
35
|
Phase 3: Synthesize
|
|
34
36
|
1. When implementation is finished, write the narrative in `index.md`.
|
|
@@ -578,6 +578,16 @@ footer .build-time a:hover {
|
|
|
578
578
|
color: #4b5563;
|
|
579
579
|
}
|
|
580
580
|
|
|
581
|
+
.tag-asked {
|
|
582
|
+
background: #fef3c7;
|
|
583
|
+
color: #92400e;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.tag-answered {
|
|
587
|
+
background: #dcfce7;
|
|
588
|
+
color: #166534;
|
|
589
|
+
}
|
|
590
|
+
|
|
581
591
|
/* Timeline card tag styling */
|
|
582
592
|
.timeline-card .tags-wrapper {
|
|
583
593
|
margin-top: 0.5rem;
|
|
@@ -1017,3 +1027,46 @@ article img[src$='.svg'] {
|
|
|
1017
1027
|
.timeline-card--adr .tags-wrapper {
|
|
1018
1028
|
margin-top: 0.5rem;
|
|
1019
1029
|
}
|
|
1030
|
+
|
|
1031
|
+
/* QnA card styles */
|
|
1032
|
+
.qna-card {
|
|
1033
|
+
display: block;
|
|
1034
|
+
background: var(--card-bg, #ffffff);
|
|
1035
|
+
border: 1px solid var(--border, #e5e7eb);
|
|
1036
|
+
border-radius: 8px;
|
|
1037
|
+
padding: 1.25rem 1.5rem;
|
|
1038
|
+
margin-bottom: 1.5rem;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.qna-card.unanswered {
|
|
1042
|
+
border-left: 4px solid #f59e0b;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.qna-card.answered {
|
|
1046
|
+
border-left: 4px solid #10b981;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.qna-meta {
|
|
1050
|
+
font-size: 0.8125rem;
|
|
1051
|
+
color: var(--text-muted);
|
|
1052
|
+
margin-bottom: 0.75rem;
|
|
1053
|
+
display: flex;
|
|
1054
|
+
align-items: center;
|
|
1055
|
+
gap: 0.5rem;
|
|
1056
|
+
flex-wrap: wrap;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.qna-card h3 {
|
|
1060
|
+
font-size: 0.95rem;
|
|
1061
|
+
font-weight: 700;
|
|
1062
|
+
margin: 0.75rem 0 0.25rem 0;
|
|
1063
|
+
text-transform: uppercase;
|
|
1064
|
+
letter-spacing: 0.05em;
|
|
1065
|
+
color: var(--text-muted);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
.qna-card .markdown-body {
|
|
1069
|
+
color: var(--text);
|
|
1070
|
+
font-size: 0.9375rem;
|
|
1071
|
+
line-height: 1.6;
|
|
1072
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type QnaStatus = 'asked' | 'answered' | 'deprecated';
|
|
2
|
+
export interface QnaItem {
|
|
3
|
+
id: number;
|
|
4
|
+
status: QnaStatus;
|
|
5
|
+
dateAsked: string;
|
|
6
|
+
dateAnswered?: string;
|
|
7
|
+
dateDeprecated?: string;
|
|
8
|
+
question: string;
|
|
9
|
+
answer: string;
|
|
10
|
+
questionHtml?: string;
|
|
11
|
+
answerHtml?: string;
|
|
12
|
+
filename: string;
|
|
13
|
+
filepath: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function resolveQnaEntry(qnaDir: string, idInput: string): Promise<{
|
|
16
|
+
id: number;
|
|
17
|
+
item: QnaItem;
|
|
18
|
+
filepath: string;
|
|
19
|
+
} | {
|
|
20
|
+
error: string;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function sortQnaItems<T extends {
|
|
23
|
+
status: QnaStatus;
|
|
24
|
+
dateAsked: string;
|
|
25
|
+
id: number;
|
|
26
|
+
}>(items: T[]): T[];
|
|
27
|
+
export declare function slugifyQuestion(text: string, maxLen?: number): string;
|
|
28
|
+
export declare function parseQnaContent(body: string): {
|
|
29
|
+
question: string;
|
|
30
|
+
answer: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function formatQnaMarkdown(params: {
|
|
33
|
+
id: number;
|
|
34
|
+
status: QnaStatus;
|
|
35
|
+
dateAsked: string;
|
|
36
|
+
dateAnswered?: string;
|
|
37
|
+
dateDeprecated?: string;
|
|
38
|
+
question: string;
|
|
39
|
+
answer?: string;
|
|
40
|
+
}): string;
|
|
41
|
+
export declare function getAllQna(qnaDir: string): Promise<QnaItem[]>;
|
|
42
|
+
export declare function getNextQnaId(qnaDir: string): Promise<number>;
|
|
43
|
+
export declare function findQnaById(qnaDir: string, id: number): Promise<{
|
|
44
|
+
item: QnaItem;
|
|
45
|
+
filepath: string;
|
|
46
|
+
} | null>;
|