living-documentation 8.14.0 → 8.16.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/src/frontend/confirm-modal.js +10 -1
- package/dist/src/frontend/documents.js +4 -0
- package/dist/src/frontend/i18n/en.json +8 -0
- package/dist/src/frontend/i18n/fr.json +8 -0
- package/dist/src/frontend/index.html +21 -0
- package/dist/src/frontend/metadata.js +27 -1
- package/dist/src/frontend/validate.js +107 -0
- package/dist/src/lib/status.d.ts +9 -0
- package/dist/src/lib/status.d.ts.map +1 -0
- package/dist/src/lib/status.js +72 -0
- package/dist/src/lib/status.js.map +1 -0
- package/dist/src/mcp/tools/metadata.d.ts.map +1 -1
- package/dist/src/mcp/tools/metadata.js +4 -0
- package/dist/src/mcp/tools/metadata.js.map +1 -1
- package/dist/src/routes/metadata.d.ts.map +1 -1
- package/dist/src/routes/metadata.js +24 -0
- package/dist/src/routes/metadata.js.map +1 -1
- package/dist/starter-doc/AI/PROJECT-INSTRUCTIONS.md +21 -4
- package/dist/starter-doc/AI/default/AGENTS.md +3 -2
- package/dist/starter-doc/AI/default/CLAUDE.md +3 -2
- package/dist/starter-doc/AI/rules/track-current-work.md +23 -0
- package/dist/starter-doc/WORKLOG/current-task.md +57 -0
- package/dist/starter-doc-fr/AI/PROJECT-INSTRUCTIONS.md +21 -2
- package/dist/starter-doc-fr/AI/default/AGENTS.md +3 -2
- package/dist/starter-doc-fr/AI/default/CLAUDE.md +3 -2
- package/dist/starter-doc-fr/AI/rules/track-current-work.md +23 -0
- package/dist/starter-doc-fr/WORKLOG/current-task.md +57 -0
- package/package.json +1 -1
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
// ── Generic confirmation modal ──────────────────────────────────────────────
|
|
2
2
|
// Promise-based replacement for window.confirm(). Any module can call:
|
|
3
|
-
// const ok = await showConfirm({ title, message, detail, confirmLabel, danger });
|
|
3
|
+
// const ok = await showConfirm({ title, message, detail, confirmLabel, danger, detailTone });
|
|
4
4
|
// The modal sits at z-[60] so it stacks above other app modals (z-50).
|
|
5
|
+
// `detailTone: "warning"` renders the detail block as an amber callout when the
|
|
6
|
+
// secondary message carries a consequence the user should not miss.
|
|
5
7
|
|
|
6
8
|
let _confirmResolve = null;
|
|
7
9
|
|
|
10
|
+
const _DETAIL_NEUTRAL_CLS =
|
|
11
|
+
"text-xs text-gray-500 dark:text-gray-400 italic break-all";
|
|
12
|
+
const _DETAIL_WARNING_CLS =
|
|
13
|
+
"text-xs text-amber-800 dark:text-amber-200 break-all bg-amber-50 dark:bg-amber-900/30 border-l-4 border-amber-500 rounded-r px-3 py-2";
|
|
14
|
+
|
|
8
15
|
function _confirmT(key, fallback) {
|
|
9
16
|
return window.t ? window.t(key) : fallback;
|
|
10
17
|
}
|
|
@@ -49,6 +56,8 @@ function showConfirm(opts) {
|
|
|
49
56
|
messageEl.style.display = o.message ? "" : "none";
|
|
50
57
|
detailEl.textContent = o.detail || "";
|
|
51
58
|
detailEl.style.display = o.detail ? "" : "none";
|
|
59
|
+
detailEl.className =
|
|
60
|
+
o.detailTone === "warning" ? _DETAIL_WARNING_CLS : _DETAIL_NEUTRAL_CLS;
|
|
52
61
|
|
|
53
62
|
cancelBtn.textContent = o.cancelLabel || _confirmT("common.cancel", "Cancel");
|
|
54
63
|
okBtn.textContent = o.confirmLabel || _confirmT("common.confirm", "Confirm");
|
|
@@ -322,6 +322,10 @@ async function openDocument(id, skipHistory = false, fromLink = false, anchor =
|
|
|
322
322
|
_lastDocIdRendered = id;
|
|
323
323
|
_wireDocContent(doc.html);
|
|
324
324
|
|
|
325
|
+
if (typeof updateValidateButtonForCurrentDoc === "function") {
|
|
326
|
+
updateValidateButtonForCurrentDoc();
|
|
327
|
+
}
|
|
328
|
+
|
|
325
329
|
// Load annotations for this document
|
|
326
330
|
loadAnnotations(id);
|
|
327
331
|
|
|
@@ -66,6 +66,14 @@
|
|
|
66
66
|
"sidebar.file_attachment_badge": "attachment",
|
|
67
67
|
"sidebar.file_attached_docs_badge": "document with attachments",
|
|
68
68
|
|
|
69
|
+
"doc.validate_mode": "Validate document — flip frontmatter status from \"To be validated\" to \"Accepted\"",
|
|
70
|
+
"doc.validate_btn": "Validate",
|
|
71
|
+
"doc.validate_title": "Validate this document?",
|
|
72
|
+
"doc.validate_message": "The frontmatter status will change from \"To be validated\" to \"Accepted\".",
|
|
73
|
+
"doc.validate_detail_low_accuracy": "Reliability is currently {accuracy}. Confirming will also re-baseline source-file hashes, bringing reliability back to 100%.",
|
|
74
|
+
"doc.validate_confirm": "Validate",
|
|
75
|
+
"doc.validate_failed": "Validation failed: ",
|
|
76
|
+
"metadata.readonly_banner": "Read-only — this document is SuperSeeded. Source metadata can still be viewed but not edited.",
|
|
69
77
|
"doc.marker_mode": "Marker mode — highlight to annotate",
|
|
70
78
|
"doc.marker_btn": "Marker",
|
|
71
79
|
"doc.toggle_width": "Toggle full width",
|
|
@@ -66,6 +66,14 @@
|
|
|
66
66
|
"sidebar.file_attachment_badge": "pièce jointe",
|
|
67
67
|
"sidebar.file_attached_docs_badge": "document contenant des pièces jointes",
|
|
68
68
|
|
|
69
|
+
"doc.validate_mode": "Valider le document — passer le statut frontmatter de « To be validated » à « Accepted »",
|
|
70
|
+
"doc.validate_btn": "Valider",
|
|
71
|
+
"doc.validate_title": "Valider ce document ?",
|
|
72
|
+
"doc.validate_message": "Le statut frontmatter va passer de « To be validated » à « Accepted ».",
|
|
73
|
+
"doc.validate_detail_low_accuracy": "La fiabilité actuelle est de {accuracy}. Confirmer va aussi réinitialiser les hashes des fichiers source, ramenant la fiabilité à 100 %.",
|
|
74
|
+
"doc.validate_confirm": "Valider",
|
|
75
|
+
"doc.validate_failed": "Échec de la validation : ",
|
|
76
|
+
"metadata.readonly_banner": "Lecture seule — ce document est SuperSeeded. Les métadonnées source peuvent être consultées mais pas modifiées.",
|
|
69
77
|
"doc.marker_mode": "Mode Marqueur — surligner pour annoter",
|
|
70
78
|
"doc.marker_btn": "Marqueur",
|
|
71
79
|
"doc.toggle_width": "Basculer la largeur",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
<script defer src="/annotations.js"></script>
|
|
52
52
|
<script defer src="/metadata.js"></script>
|
|
53
53
|
<script defer src="/accuracy-gauge.js"></script>
|
|
54
|
+
<script defer src="/validate.js"></script>
|
|
54
55
|
<script defer src="/export.js"></script>
|
|
55
56
|
<script defer src="/diagram-link-modal.js"></script>
|
|
56
57
|
<script defer src="/new-folder-modal.js"></script>
|
|
@@ -620,6 +621,16 @@
|
|
|
620
621
|
<div class="flex items-center gap-2 flex-wrap ml-auto">
|
|
621
622
|
<!-- View mode actions -->
|
|
622
623
|
<div id="view-actions" class="flex items-center gap-2">
|
|
624
|
+
<button
|
|
625
|
+
onclick="validateCurrentDoc()"
|
|
626
|
+
id="validate-btn"
|
|
627
|
+
data-i18n-title="doc.validate_mode"
|
|
628
|
+
title="Validate document"
|
|
629
|
+
class="hidden no-print text-sm px-3 py-1.5 rounded-lg border border-green-700 bg-green-600 text-white font-semibold hover:bg-green-700 transition-colors"
|
|
630
|
+
>
|
|
631
|
+
<i class="fa-solid fa-check" aria-hidden="true" style="margin-right: 4px"></i>
|
|
632
|
+
<span data-i18n="doc.validate_btn">Validate</span>
|
|
633
|
+
</button>
|
|
623
634
|
<button
|
|
624
635
|
onclick="toggleMarker()"
|
|
625
636
|
id="stabilo-btn"
|
|
@@ -900,6 +911,15 @@
|
|
|
900
911
|
class="text-xs text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-gray-800 rounded-lg px-3 py-2"
|
|
901
912
|
></div>
|
|
902
913
|
|
|
914
|
+
<!-- Read-only banner (SuperSeeded documents) -->
|
|
915
|
+
<div
|
|
916
|
+
id="metadata-readonly-banner"
|
|
917
|
+
data-i18n="metadata.readonly_banner"
|
|
918
|
+
class="hidden text-xs text-amber-800 dark:text-amber-200 bg-amber-50 dark:bg-amber-900/30 border-l-4 border-amber-500 rounded-r px-3 py-2"
|
|
919
|
+
>
|
|
920
|
+
Read-only — this document is SuperSeeded. Source metadata can still be viewed but not edited.
|
|
921
|
+
</div>
|
|
922
|
+
|
|
903
923
|
<!-- List -->
|
|
904
924
|
<div class="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
|
|
905
925
|
<div
|
|
@@ -919,6 +939,7 @@
|
|
|
919
939
|
<div class="flex items-center gap-2 flex-wrap">
|
|
920
940
|
<button
|
|
921
941
|
onclick="metadataToggleBrowser()"
|
|
942
|
+
id="metadata-add-btn"
|
|
922
943
|
class="text-sm px-3 py-1.5 rounded-lg border border-blue-200 dark:border-blue-700 text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/30 transition-colors"
|
|
923
944
|
>
|
|
924
945
|
<i class="fa-solid fa-plus"></i> <span data-i18n="metadata.add">Add source file</span>
|
|
@@ -75,7 +75,7 @@ function renderMetadataList() {
|
|
|
75
75
|
onclick="metadataRemovePath('${safePath.replace(/'/g, "\\'")}')"
|
|
76
76
|
data-i18n-title="metadata.remove"
|
|
77
77
|
title="Remove"
|
|
78
|
-
class="text-xs px-2 py-1 rounded-lg border border-red-200 dark:border-red-700 text-red-500 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/40 transition-colors"
|
|
78
|
+
class="metadata-row-remove text-xs px-2 py-1 rounded-lg border border-red-200 dark:border-red-700 text-red-500 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/40 transition-colors"
|
|
79
79
|
>
|
|
80
80
|
<i class="fa-solid fa-trash"></i>
|
|
81
81
|
</button>
|
|
@@ -84,8 +84,33 @@ function renderMetadataList() {
|
|
|
84
84
|
.join("");
|
|
85
85
|
|
|
86
86
|
if (typeof window.applyI18n === "function") window.applyI18n();
|
|
87
|
+
applyMetadataReadOnlyMode();
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
// Hide the three metadata-mutation controls (and the row-level trash icons)
|
|
91
|
+
// when the current document's frontmatter status is `SuperSeeded`. The server
|
|
92
|
+
// also rejects these mutations independently — this is purely UX. Re-applied
|
|
93
|
+
// after every list re-render so dynamically generated rows stay consistent.
|
|
94
|
+
function applyMetadataReadOnlyMode() {
|
|
95
|
+
const readOnly =
|
|
96
|
+
typeof window.getDocStatus === "function" &&
|
|
97
|
+
window.getDocStatus(
|
|
98
|
+
typeof currentDocContent !== "undefined" ? currentDocContent : "",
|
|
99
|
+
) === "SuperSeeded";
|
|
100
|
+
|
|
101
|
+
const refreshBtn = document.getElementById("metadata-refresh-btn");
|
|
102
|
+
const addBtn = document.getElementById("metadata-add-btn");
|
|
103
|
+
const banner = document.getElementById("metadata-readonly-banner");
|
|
104
|
+
if (refreshBtn) refreshBtn.classList.toggle("hidden", readOnly);
|
|
105
|
+
if (addBtn) addBtn.classList.toggle("hidden", readOnly);
|
|
106
|
+
if (banner) banner.classList.toggle("hidden", !readOnly);
|
|
107
|
+
document
|
|
108
|
+
.querySelectorAll("#metadata-list .metadata-row-remove")
|
|
109
|
+
.forEach((el) => el.classList.toggle("hidden", readOnly));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
window.applyMetadataReadOnlyMode = applyMetadataReadOnlyMode;
|
|
113
|
+
|
|
89
114
|
function renderMetadataSummary() {
|
|
90
115
|
const el = document.getElementById("metadata-summary");
|
|
91
116
|
if (!el) return;
|
|
@@ -110,6 +135,7 @@ async function openMetadataModal() {
|
|
|
110
135
|
metadataBrowseCurrent = "";
|
|
111
136
|
metadataBrowseCache = null;
|
|
112
137
|
document.getElementById("metadata-browser").classList.add("hidden");
|
|
138
|
+
applyMetadataReadOnlyMode();
|
|
113
139
|
}
|
|
114
140
|
|
|
115
141
|
function closeMetadataModal() {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// ── Document validation ──────────────────────────────────────────────────────
|
|
2
|
+
// Wires the "Validate" toolbar button: visible only when the loaded document's
|
|
3
|
+
// frontmatter contains `**status:** To be validated`. Clicking flips the status
|
|
4
|
+
// to `Accepted` via PUT /api/documents/:id; if the document's reliability is
|
|
5
|
+
// below 100%, the confirmation modal also warns that source-file hashes will be
|
|
6
|
+
// re-baselined, and POST /api/metadata/:id/refresh is called after the PUT.
|
|
7
|
+
|
|
8
|
+
// Frontmatter on this project is a `---`-fenced block of `**key:** value` lines
|
|
9
|
+
// (not standard YAML). The status line is the only field this module touches.
|
|
10
|
+
const _STATUS_LINE_RE = /^(\*\*status:\*\*\s*).+?\s*$/m;
|
|
11
|
+
|
|
12
|
+
function getDocStatus(content) {
|
|
13
|
+
if (typeof content !== "string") return null;
|
|
14
|
+
const fence = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
15
|
+
if (!fence) return null;
|
|
16
|
+
const m = fence[1].match(/^\*\*status:\*\*\s*(.+?)\s*$/m);
|
|
17
|
+
return m ? m[1].trim() : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function _replaceStatus(content, newStatus) {
|
|
21
|
+
return content.replace(_STATUS_LINE_RE, `$1${newStatus}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function updateValidateButtonForCurrentDoc() {
|
|
25
|
+
const btn = document.getElementById("validate-btn");
|
|
26
|
+
if (!btn) return;
|
|
27
|
+
const status = getDocStatus(
|
|
28
|
+
typeof currentDocContent !== "undefined" ? currentDocContent : "",
|
|
29
|
+
);
|
|
30
|
+
if (status === "To be validated") {
|
|
31
|
+
btn.classList.remove("hidden");
|
|
32
|
+
} else {
|
|
33
|
+
btn.classList.add("hidden");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function validateCurrentDoc() {
|
|
38
|
+
const id = typeof currentDocId !== "undefined" ? currentDocId : null;
|
|
39
|
+
if (!id) return;
|
|
40
|
+
|
|
41
|
+
// Snapshot accuracy now so the confirm modal warns when re-baselining is implied.
|
|
42
|
+
let accuracy = 1;
|
|
43
|
+
try {
|
|
44
|
+
const r = await fetch("/api/metadata/" + encodeURIComponent(id));
|
|
45
|
+
if (r.ok) {
|
|
46
|
+
const rep = await r.json();
|
|
47
|
+
if (typeof rep.accuracy === "number") accuracy = rep.accuracy;
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
// Fall through with accuracy = 1; worst case we skip the warning. The
|
|
51
|
+
// refresh step is still gated on the same value, so semantics stay aligned.
|
|
52
|
+
}
|
|
53
|
+
const pct = Math.round(accuracy * 100);
|
|
54
|
+
const lowAccuracy = pct < 100;
|
|
55
|
+
const detail = lowAccuracy
|
|
56
|
+
? window.t("doc.validate_detail_low_accuracy").replace("{accuracy}", pct + "%")
|
|
57
|
+
: "";
|
|
58
|
+
|
|
59
|
+
const ok = await window.showConfirm({
|
|
60
|
+
title: window.t("doc.validate_title"),
|
|
61
|
+
message: window.t("doc.validate_message"),
|
|
62
|
+
detail,
|
|
63
|
+
detailTone: lowAccuracy ? "warning" : undefined,
|
|
64
|
+
confirmLabel: window.t("doc.validate_confirm"),
|
|
65
|
+
});
|
|
66
|
+
if (!ok) return;
|
|
67
|
+
|
|
68
|
+
const btn = document.getElementById("validate-btn");
|
|
69
|
+
if (btn) btn.disabled = true;
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const newContent = _replaceStatus(currentDocContent, "Accepted");
|
|
73
|
+
if (newContent === currentDocContent) {
|
|
74
|
+
throw new Error("status line not found in frontmatter");
|
|
75
|
+
}
|
|
76
|
+
const putRes = await fetch("/api/documents/" + encodeURIComponent(id), {
|
|
77
|
+
method: "PUT",
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
body: JSON.stringify({ content: newContent }),
|
|
80
|
+
});
|
|
81
|
+
if (!putRes.ok) throw new Error(putRes.statusText || "save failed");
|
|
82
|
+
|
|
83
|
+
if (lowAccuracy) {
|
|
84
|
+
const refRes = await fetch(
|
|
85
|
+
"/api/metadata/" + encodeURIComponent(id) + "/refresh",
|
|
86
|
+
{ method: "POST" },
|
|
87
|
+
);
|
|
88
|
+
if (!refRes.ok) throw new Error(refRes.statusText || "refresh failed");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (typeof openDocument === "function") {
|
|
92
|
+
await openDocument(id, /* skipHistory */ true);
|
|
93
|
+
}
|
|
94
|
+
if (typeof loadMetadataReport === "function") {
|
|
95
|
+
await loadMetadataReport(id);
|
|
96
|
+
}
|
|
97
|
+
} catch (err) {
|
|
98
|
+
const msg = err && err.message ? err.message : String(err);
|
|
99
|
+
alert(window.t("doc.validate_failed") + msg);
|
|
100
|
+
} finally {
|
|
101
|
+
if (btn) btn.disabled = false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
window.validateCurrentDoc = validateCurrentDoc;
|
|
106
|
+
window.updateValidateButtonForCurrentDoc = updateValidateButtonForCurrentDoc;
|
|
107
|
+
window.getDocStatus = getDocStatus;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function parseDocStatus(content: string): string | null;
|
|
2
|
+
export declare function readDocStatus(docsPath: string, decodedDocId: string, extraFiles: string[]): string | null;
|
|
3
|
+
export declare const SUPERSEEDED_STATUS = "SuperSeeded";
|
|
4
|
+
export declare class DocumentSuperSeededError extends Error {
|
|
5
|
+
readonly code = "DOCUMENT_SUPERSEEDED";
|
|
6
|
+
constructor(message?: string);
|
|
7
|
+
}
|
|
8
|
+
export declare function assertNotSuperSeeded(docsPath: string, decodedDocId: string): void;
|
|
9
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/lib/status.ts"],"names":[],"mappings":"AAcA,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM7D;AAmBD,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAAE,GACnB,MAAM,GAAG,IAAI,CAQf;AAED,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAKhD,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,0BAA0B;gBAErC,OAAO,SAAoD;CAK9D;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,IAAI,CAKN"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ── Frontmatter status helpers ───────────────────────────────────────────────
|
|
3
|
+
// The project's frontmatter is not standard YAML: each line is `**key:** value`
|
|
4
|
+
// inside a `---`-fenced block. This module reads only the `status` line — used
|
|
5
|
+
// to gate mutations based on the doc lifecycle (e.g. block metadata writes on
|
|
6
|
+
// a SuperSeeded ADR). The `assertNotSuperSeeded` guard is consumed both by the
|
|
7
|
+
// HTTP routes and by the MCP tools — they share the same source of truth.
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DocumentSuperSeededError = exports.SUPERSEEDED_STATUS = void 0;
|
|
13
|
+
exports.parseDocStatus = parseDocStatus;
|
|
14
|
+
exports.readDocStatus = readDocStatus;
|
|
15
|
+
exports.assertNotSuperSeeded = assertNotSuperSeeded;
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const config_1 = require("./config");
|
|
19
|
+
const STATUS_LINE_RE = /^\*\*status:\*\*\s*(.+?)\s*$/m;
|
|
20
|
+
const FRONTMATTER_FENCE_RE = /^---\s*\n([\s\S]*?)\n---/;
|
|
21
|
+
function parseDocStatus(content) {
|
|
22
|
+
if (typeof content !== "string")
|
|
23
|
+
return null;
|
|
24
|
+
const fence = content.match(FRONTMATTER_FENCE_RE);
|
|
25
|
+
if (!fence)
|
|
26
|
+
return null;
|
|
27
|
+
const m = fence[1].match(STATUS_LINE_RE);
|
|
28
|
+
return m ? m[1].trim() : null;
|
|
29
|
+
}
|
|
30
|
+
// Resolve a doc id (already decoded) to its .md file path, honouring the same
|
|
31
|
+
// rules the documents route uses: extraFiles for absolute ids, safe-path for
|
|
32
|
+
// regular ids. Returns null if the file is not readable or escapes docsPath.
|
|
33
|
+
function resolveDocFilePath(docsPath, decodedDocId, extraFiles) {
|
|
34
|
+
if (path_1.default.isAbsolute(decodedDocId)) {
|
|
35
|
+
const candidate = decodedDocId + ".md";
|
|
36
|
+
return extraFiles.includes(candidate) ? candidate : null;
|
|
37
|
+
}
|
|
38
|
+
const resolved = path_1.default.resolve(docsPath, decodedDocId + ".md");
|
|
39
|
+
if (!resolved.startsWith(path_1.default.resolve(docsPath) + path_1.default.sep))
|
|
40
|
+
return null;
|
|
41
|
+
return resolved;
|
|
42
|
+
}
|
|
43
|
+
function readDocStatus(docsPath, decodedDocId, extraFiles) {
|
|
44
|
+
const filePath = resolveDocFilePath(docsPath, decodedDocId, extraFiles);
|
|
45
|
+
if (!filePath || !fs_1.default.existsSync(filePath))
|
|
46
|
+
return null;
|
|
47
|
+
try {
|
|
48
|
+
return parseDocStatus(fs_1.default.readFileSync(filePath, "utf-8"));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.SUPERSEEDED_STATUS = "SuperSeeded";
|
|
55
|
+
// Typed error so callers (HTTP routes, MCP tool wrapper) can distinguish a
|
|
56
|
+
// lifecycle rejection from a generic failure and map it to the right response
|
|
57
|
+
// envelope (403 for HTTP, MCP `isError: true` content wrapper).
|
|
58
|
+
class DocumentSuperSeededError extends Error {
|
|
59
|
+
constructor(message = "Document is SuperSeeded; metadata is read-only.") {
|
|
60
|
+
super(message);
|
|
61
|
+
this.code = "DOCUMENT_SUPERSEEDED";
|
|
62
|
+
this.name = "DocumentSuperSeededError";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.DocumentSuperSeededError = DocumentSuperSeededError;
|
|
66
|
+
function assertNotSuperSeeded(docsPath, decodedDocId) {
|
|
67
|
+
const { extraFiles = [] } = (0, config_1.readConfig)(docsPath);
|
|
68
|
+
if (readDocStatus(docsPath, decodedDocId, extraFiles) === exports.SUPERSEEDED_STATUS) {
|
|
69
|
+
throw new DocumentSuperSeededError();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/lib/status.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,gFAAgF;AAChF,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;;;;;;AAS1E,wCAMC;AAmBD,sCAYC;AAiBD,oDAQC;AArED,4CAAoB;AACpB,gDAAwB;AACxB,qCAAsC;AAEtC,MAAM,cAAc,GAAG,+BAA+B,CAAC;AACvD,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAExD,SAAgB,cAAc,CAAC,OAAe;IAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACzC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC;AAED,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,SAAS,kBAAkB,CACzB,QAAgB,EAChB,YAAoB,EACpB,UAAoB;IAEpB,IAAI,cAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,YAAY,GAAG,KAAK,CAAC;QACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,CAAC;IACD,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,cAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAgB,aAAa,CAC3B,QAAgB,EAChB,YAAoB,EACpB,UAAoB;IAEpB,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IACxE,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAEY,QAAA,kBAAkB,GAAG,aAAa,CAAC;AAEhD,2EAA2E;AAC3E,8EAA8E;AAC9E,gEAAgE;AAChE,MAAa,wBAAyB,SAAQ,KAAK;IAEjD,YACE,OAAO,GAAG,iDAAiD;QAE3D,KAAK,CAAC,OAAO,CAAC,CAAC;QAJR,SAAI,GAAG,sBAAsB,CAAC;QAKrC,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AARD,4DAQC;AAED,SAAgB,oBAAoB,CAClC,QAAgB,EAChB,YAAoB;IAEpB,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,IAAA,mBAAU,EAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,KAAK,0BAAkB,EAAE,CAAC;QAC7E,MAAM,IAAI,wBAAwB,EAAE,CAAC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../../src/mcp/tools/metadata.ts"],"names":[],"mappings":"AA8CA,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;;EAKtE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;;EAMrE;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;;EAkD5E;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;;EAcrB;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;EA4BnC;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;;EAwBnC;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM;;;;;EAsDzD"}
|
|
@@ -14,6 +14,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
14
14
|
const fs_1 = __importDefault(require("fs"));
|
|
15
15
|
const metadata_1 = require("../../lib/metadata");
|
|
16
16
|
const hash_1 = require("../../lib/hash");
|
|
17
|
+
const status_1 = require("../../lib/status");
|
|
17
18
|
const documents_1 = require("./documents");
|
|
18
19
|
const ACCURACY_THRESHOLD = 0.8;
|
|
19
20
|
const FULL_ACCURACY = 1;
|
|
@@ -108,6 +109,7 @@ function toolReviewAdrRelevance(docsPath, args) {
|
|
|
108
109
|
}
|
|
109
110
|
function toolRefreshMetadata(docsPath, args) {
|
|
110
111
|
const docId = decodeDocId(args?.id);
|
|
112
|
+
(0, status_1.assertNotSuperSeeded)(docsPath, docId);
|
|
111
113
|
const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
|
|
112
114
|
const entries = (0, metadata_1.getDocEntries)(docsPath, docId).map((e) => {
|
|
113
115
|
const abs = path_1.default.resolve(sourceRoot, e.path);
|
|
@@ -122,6 +124,7 @@ function toolRefreshMetadata(docsPath, args) {
|
|
|
122
124
|
}
|
|
123
125
|
function toolAddMetadata(docsPath, args) {
|
|
124
126
|
const docId = decodeDocId(args?.id);
|
|
127
|
+
(0, status_1.assertNotSuperSeeded)(docsPath, docId);
|
|
125
128
|
if (!args.path)
|
|
126
129
|
throw new Error("path is required");
|
|
127
130
|
const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
|
|
@@ -151,6 +154,7 @@ function toolAddMetadata(docsPath, args) {
|
|
|
151
154
|
}
|
|
152
155
|
function toolRemoveMetadata(docsPath, args) {
|
|
153
156
|
const docId = decodeDocId(args?.id);
|
|
157
|
+
(0, status_1.assertNotSuperSeeded)(docsPath, docId);
|
|
154
158
|
if (!args.path)
|
|
155
159
|
throw new Error("path is required");
|
|
156
160
|
const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../../src/mcp/tools/metadata.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../../src/mcp/tools/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/routes/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/routes/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAmCpD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiGvD"}
|
|
@@ -9,6 +9,24 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const metadata_1 = require("../lib/metadata");
|
|
11
11
|
const hash_1 = require("../lib/hash");
|
|
12
|
+
const status_1 = require("../lib/status");
|
|
13
|
+
// SuperSeeded documents are read-only as far as metadata is concerned: an ADR
|
|
14
|
+
// that has been replaced should keep the source bindings that prove what the
|
|
15
|
+
// original decision described, frozen at the moment of supersession. The guard
|
|
16
|
+
// itself lives in `lib/status.ts` so MCP tools share the same check.
|
|
17
|
+
function rejectIfSuperSeeded(docsPath, docId, res) {
|
|
18
|
+
try {
|
|
19
|
+
(0, status_1.assertNotSuperSeeded)(docsPath, docId);
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
if (err instanceof status_1.DocumentSuperSeededError) {
|
|
24
|
+
res.status(403).json({ error: err.message });
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
12
30
|
function metadataRouter(docsPath) {
|
|
13
31
|
const router = (0, express_1.Router)();
|
|
14
32
|
// GET /api/metadata/:docId → { items, total, unchanged, modified, missing, accuracy }
|
|
@@ -29,6 +47,8 @@ function metadataRouter(docsPath) {
|
|
|
29
47
|
// POST /api/metadata/:docId body: { path }
|
|
30
48
|
router.post("/:docId", (req, res) => {
|
|
31
49
|
const docId = decodeURIComponent(req.params.docId);
|
|
50
|
+
if (rejectIfSuperSeeded(docsPath, docId, res))
|
|
51
|
+
return;
|
|
32
52
|
const { path: rawPath } = req.body;
|
|
33
53
|
if (!rawPath || typeof rawPath !== "string") {
|
|
34
54
|
return res.status(400).json({ error: "path is required" });
|
|
@@ -64,6 +84,8 @@ function metadataRouter(docsPath) {
|
|
|
64
84
|
// DELETE /api/metadata/:docId body: { path }
|
|
65
85
|
router.delete("/:docId", (req, res) => {
|
|
66
86
|
const docId = decodeURIComponent(req.params.docId);
|
|
87
|
+
if (rejectIfSuperSeeded(docsPath, docId, res))
|
|
88
|
+
return;
|
|
67
89
|
const { path: rel } = req.body;
|
|
68
90
|
if (!rel)
|
|
69
91
|
return res.status(400).json({ error: "path is required" });
|
|
@@ -83,6 +105,8 @@ function metadataRouter(docsPath) {
|
|
|
83
105
|
// POST /api/metadata/:docId/refresh → recompute stored hashes from current file state
|
|
84
106
|
router.post("/:docId/refresh", (req, res) => {
|
|
85
107
|
const docId = decodeURIComponent(req.params.docId);
|
|
108
|
+
if (rejectIfSuperSeeded(docsPath, docId, res))
|
|
109
|
+
return;
|
|
86
110
|
try {
|
|
87
111
|
const sourceRoot = (0, metadata_1.resolveSourceRoot)(docsPath);
|
|
88
112
|
const entries = (0, metadata_1.getDocEntries)(docsPath, docId).map((e) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/routes/metadata.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/routes/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,10 +14,9 @@ Before changing the project:
|
|
|
14
14
|
4. Read `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md` to know the development, build, test, lint, and setup commands.
|
|
15
15
|
5. Read `memory/MEMORY.md` and load only the memory files relevant to the task.
|
|
16
16
|
6. Read every rule in `DOCS_FOLDER/AI/rules/*.md`.
|
|
17
|
-
7.
|
|
18
|
-
8.
|
|
19
|
-
|
|
20
|
-
Replace `DOCS_FOLDER` with the real documentation folder used by this project, for example `documentation`, `docs`, or `doc`.
|
|
17
|
+
7. Read `DOCS_FOLDER/WORKLOG/current-task.md` if present to resume the state of the current task.
|
|
18
|
+
8. Inspect existing ADRs: list `DOCS_FOLDER/ADRS/`, read only `description` and `tags` first, then open the full ADR only when relevant.
|
|
19
|
+
9. Check whether the Living Documentation MCP server is available before creating or modifying documentation.
|
|
21
20
|
|
|
22
21
|
## Living Documentation MCP
|
|
23
22
|
|
|
@@ -52,6 +51,24 @@ Create or update a document when the change:
|
|
|
52
51
|
|
|
53
52
|
Do not create durable documentation for trivial fixes, mechanical renames, or formatting-only changes.
|
|
54
53
|
|
|
54
|
+
## Progress Tracking
|
|
55
|
+
|
|
56
|
+
The `DOCS_FOLDER/WORKLOG/` folder holds the operational state of in-progress tasks and the resume points between AI assistants. It does not replace ADRs.
|
|
57
|
+
|
|
58
|
+
`DOCS_FOLDER/WORKLOG/current-task.md` is the shared resume point. Every assistant must read it before resuming a task and update it before handing over when it has started, finished, interrupted, or left a known follow-up.
|
|
59
|
+
|
|
60
|
+
The worklog must stay factual and useful for the next agent:
|
|
61
|
+
|
|
62
|
+
- current status;
|
|
63
|
+
- task in progress;
|
|
64
|
+
- in-scope and out-of-scope items if needed;
|
|
65
|
+
- files or areas concerned;
|
|
66
|
+
- verifications performed;
|
|
67
|
+
- remaining verifications;
|
|
68
|
+
- next recommended action.
|
|
69
|
+
|
|
70
|
+
Create a dedicated document under `DOCS_FOLDER/WORKLOG/` for an MVP ticket when more detailed tracking becomes necessary. Durable decisions stay in ADRs.
|
|
71
|
+
|
|
55
72
|
## ADRs
|
|
56
73
|
|
|
57
74
|
ADRs are the log of architecture and design decisions. They should stay short, traceable, and useful for deciding what to change later.
|
|
@@ -9,8 +9,9 @@ Before making changes:
|
|
|
9
9
|
3. Read `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md` to know the development, build, test, lint, and setup commands.
|
|
10
10
|
4. Read `memory/MEMORY.md` and load only useful memory files.
|
|
11
11
|
5. Read rules in `DOCS_FOLDER/AI/rules/*.md`.
|
|
12
|
-
6.
|
|
13
|
-
7.
|
|
12
|
+
6. Read `DOCS_FOLDER/WORKLOG/current-task.md` if present to resume the state of the current task.
|
|
13
|
+
7. Inspect ADRs in `DOCS_FOLDER/ADRS/` by reading `description` and `tags` first, then open the full ADR only when relevant.
|
|
14
|
+
8. Check whether the `living-documentation` MCP is available and use it to create, update, and keep documentation reliable when the task touches a decision, rule, command, stack, or technical document.
|
|
14
15
|
|
|
15
16
|
## Living Documentation MCP
|
|
16
17
|
|
|
@@ -9,8 +9,9 @@ Before making changes:
|
|
|
9
9
|
3. Read `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md` to know the development, build, test, lint, and setup commands.
|
|
10
10
|
4. Read `memory/MEMORY.md` and load only useful memory files.
|
|
11
11
|
5. Read rules in `DOCS_FOLDER/AI/rules/*.md`.
|
|
12
|
-
6.
|
|
13
|
-
7.
|
|
12
|
+
6. Read `DOCS_FOLDER/WORKLOG/current-task.md` if present to resume the state of the current task.
|
|
13
|
+
7. Inspect ADRs in `DOCS_FOLDER/ADRS/` by reading `description` and `tags` first, then open the full ADR only when relevant.
|
|
14
|
+
8. Check whether the `living-documentation` MCP is available and use it to create, update, and keep documentation reliable when the task touches a decision, rule, command, stack, or technical document.
|
|
14
15
|
|
|
15
16
|
## Living Documentation MCP
|
|
16
17
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: track-current-work
|
|
3
|
+
title: Track the current task in WORKLOG
|
|
4
|
+
severity: required
|
|
5
|
+
description: AI assistants must read and maintain the current-task worklog to enable reliable handoff between agents.
|
|
6
|
+
tags: ["worklog", "handoff", "ai-agents", "progress", "documentation"]
|
|
7
|
+
appliesTo: ["**/*"]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Before resuming or modifying the project, read `DOCS_FOLDER/WORKLOG/current-task.md` if the file exists.
|
|
11
|
+
|
|
12
|
+
When a task is started, interrupted, finished, or left with known follow-ups, update `DOCS_FOLDER/WORKLOG/current-task.md` with:
|
|
13
|
+
|
|
14
|
+
- the current status;
|
|
15
|
+
- the task in progress;
|
|
16
|
+
- the files or areas concerned;
|
|
17
|
+
- the verifications performed;
|
|
18
|
+
- the remaining verifications;
|
|
19
|
+
- the next recommended action.
|
|
20
|
+
|
|
21
|
+
For an MVP ticket that has actually started, create or update a dedicated document under `DOCS_FOLDER/WORKLOG/` if the tracking no longer fits clearly in `current-task.md`.
|
|
22
|
+
|
|
23
|
+
The worklog does not replace ADRs: it describes operational progress and resume points, not durable decisions.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
**date:** 2026-01-02
|
|
3
|
+
**status:** Idle
|
|
4
|
+
**description:** Shared resume point between AI assistants to track the current task, its status, the files touched, the verifications, and the next action.
|
|
5
|
+
**tags:** worklog, handoff, progress, resume, ai-agents
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Current task
|
|
9
|
+
|
|
10
|
+
This document is the shared resume point between AI assistants. Every agent must read it before continuing a task and update it before handing over.
|
|
11
|
+
|
|
12
|
+
## Current status
|
|
13
|
+
|
|
14
|
+
Idle
|
|
15
|
+
|
|
16
|
+
## Current task
|
|
17
|
+
|
|
18
|
+
No application implementation task is currently in progress.
|
|
19
|
+
|
|
20
|
+
## Last action performed
|
|
21
|
+
|
|
22
|
+
Added the progress-tracking convention between AI assistants:
|
|
23
|
+
|
|
24
|
+
- created this current worklog;
|
|
25
|
+
- created the mandatory rule `track-current-work`;
|
|
26
|
+
- added the worklog read step in `AGENTS.md`, `CLAUDE.md` and `PROJECT-INSTRUCTIONS.md`.
|
|
27
|
+
|
|
28
|
+
## Next recommended action
|
|
29
|
+
|
|
30
|
+
Start Ticket 01: initialize the React + TypeScript + Vite + Tailwind frontend project, then update this worklog with the files created, the verifications run, and any resume points.
|
|
31
|
+
|
|
32
|
+
## Files or areas concerned
|
|
33
|
+
|
|
34
|
+
- `AGENTS.md`
|
|
35
|
+
- `CLAUDE.md`
|
|
36
|
+
- `DOCS_FOLDER/AI/PROJECT-INSTRUCTIONS.md`
|
|
37
|
+
- `DOCS_FOLDER/AI/rules/track-current-work.md`
|
|
38
|
+
- `DOCS_FOLDER/WORKLOG/current-task.md`
|
|
39
|
+
- `DOCS_FOLDER/PRODUCT/`
|
|
40
|
+
- `DOCS_FOLDER/TECHNICAL/`
|
|
41
|
+
- `DOCS_FOLDER/ROADMAP/`
|
|
42
|
+
- `DOCS_FOLDER/ADRS/`
|
|
43
|
+
- `DOCS_FOLDER/AI/PROJECT-STACK.md`
|
|
44
|
+
- `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md`
|
|
45
|
+
|
|
46
|
+
## Recent verifications
|
|
47
|
+
|
|
48
|
+
- Living Documentation MCP available.
|
|
49
|
+
- `WORKLOG/current-task` visible in the MCP inventory.
|
|
50
|
+
- `AI/rules/track-current-work` visible in the MCP inventory.
|
|
51
|
+
- ADRs created with metadata and accuracy `1`.
|
|
52
|
+
- `PROJECT-STACK` with metadata and accuracy `1`.
|
|
53
|
+
- No ADR below the reliability threshold.
|
|
54
|
+
|
|
55
|
+
## Resume notes
|
|
56
|
+
|
|
57
|
+
The repository does not contain any application code yet. Do not assume the existence of `package.json`, `src/`, npm scripts, tests, or Tailwind configuration before Ticket 01.
|
|
@@ -14,8 +14,9 @@ Avant de modifier le projet :
|
|
|
14
14
|
4. Lire `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md` pour connaître les commandes de développement, build, test, lint et setup.
|
|
15
15
|
5. Lire `memory/MEMORY.md` et charger seulement les fichiers mémoire utiles à la tâche.
|
|
16
16
|
6. Lire toutes les règles dans `DOCS_FOLDER/AI/rules/*.md`.
|
|
17
|
-
7.
|
|
18
|
-
8.
|
|
17
|
+
7. Lire `DOCS_FOLDER/WORKLOG/current-task.md` si présent pour reprendre l'état de la tâche courante.
|
|
18
|
+
8. Inspecter les ADR existants : lister `DOCS_FOLDER/ADRS/`, lire d'abord `description` et `tags`, puis ouvrir l'ADR complet seulement s'il est pertinent.
|
|
19
|
+
9. Vérifier si le MCP `living-documentation` est disponible avant de créer ou modifier de la documentation.
|
|
19
20
|
|
|
20
21
|
## Rôle du MCP Living Documentation
|
|
21
22
|
|
|
@@ -50,6 +51,24 @@ Créer ou mettre à jour un document lorsque le changement :
|
|
|
50
51
|
|
|
51
52
|
Ne pas créer de documentation durable pour les corrections triviales, renommages mécaniques ou changements de formatage.
|
|
52
53
|
|
|
54
|
+
## Suivi de progression
|
|
55
|
+
|
|
56
|
+
Le dossier `DOCS_FOLDER/WORKLOG/` contient l'état opérationnel des tâches en cours et les points de reprise entre assistants IA. Il ne remplace pas les ADR.
|
|
57
|
+
|
|
58
|
+
`DOCS_FOLDER/WORKLOG/current-task.md` est le point de reprise partagé. Tout assistant doit le lire avant de reprendre une tâche et le mettre à jour avant de rendre la main lorsqu'il a commencé, terminé, interrompu ou laissé une suite connue.
|
|
59
|
+
|
|
60
|
+
Le worklog doit rester factuel et utile pour l'agent suivant :
|
|
61
|
+
|
|
62
|
+
- statut courant ;
|
|
63
|
+
- tâche en cours ;
|
|
64
|
+
- scope inclus et exclu si nécessaire ;
|
|
65
|
+
- fichiers ou zones concernés ;
|
|
66
|
+
- vérifications réalisées ;
|
|
67
|
+
- vérifications restantes ;
|
|
68
|
+
- prochaine action recommandée.
|
|
69
|
+
|
|
70
|
+
Créer un document dédié dans `DOCS_FOLDER/WORKLOG/` pour un ticket MVP lorsqu'un suivi plus détaillé devient nécessaire. Les décisions durables restent dans les ADR.
|
|
71
|
+
|
|
53
72
|
## ADR
|
|
54
73
|
|
|
55
74
|
Les ADR sont le journal des décisions d'architecture et de conception. Ils doivent rester courts, traçables et utiles pour décider quoi modifier plus tard.
|
|
@@ -9,8 +9,9 @@ Avant toute modification :
|
|
|
9
9
|
3. Lire `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md` pour connaître les commandes de développement, build, test, lint et setup.
|
|
10
10
|
4. Lire `memory/MEMORY.md` et charger seulement les fichiers mémoire utiles à la tâche.
|
|
11
11
|
5. Lire toutes les règles dans `DOCS_FOLDER/AI/rules/*.md`.
|
|
12
|
-
6.
|
|
13
|
-
7.
|
|
12
|
+
6. Lire `DOCS_FOLDER/WORKLOG/current-task.md` si présent pour reprendre l'état de la tâche courante.
|
|
13
|
+
7. Inspecter les ADR dans `DOCS_FOLDER/ADRS/` en lisant d'abord `description` et `tags`, puis ouvrir l'ADR complet seulement s'il est pertinent.
|
|
14
|
+
8. Vérifier si le MCP `living-documentation` est disponible et l'utiliser pour créer, mettre à jour et fiabiliser la documentation lorsque la tâche touche une décision, une règle, une commande, la stack ou un document technique.
|
|
14
15
|
|
|
15
16
|
## MCP Living Documentation
|
|
16
17
|
|
|
@@ -9,8 +9,9 @@ Avant toute modification :
|
|
|
9
9
|
3. Lire `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md` pour connaître les commandes de développement, build, test, lint et setup.
|
|
10
10
|
4. Lire `memory/MEMORY.md` et charger seulement les fichiers mémoire utiles à la tâche.
|
|
11
11
|
5. Lire toutes les règles dans `DOCS_FOLDER/AI/rules/*.md`.
|
|
12
|
-
6.
|
|
13
|
-
7.
|
|
12
|
+
6. Lire `DOCS_FOLDER/WORKLOG/current-task.md` si présent pour reprendre l'état de la tâche courante.
|
|
13
|
+
7. Inspecter les ADR dans `DOCS_FOLDER/ADRS/` en lisant d'abord `description` et `tags`, puis ouvrir l'ADR complet seulement s'il est pertinent.
|
|
14
|
+
8. Vérifier si le MCP `living-documentation` est disponible et l'utiliser pour créer, mettre à jour et fiabiliser la documentation lorsque la tâche touche une décision, une règle, une commande, la stack ou un document technique.
|
|
14
15
|
|
|
15
16
|
## MCP Living Documentation
|
|
16
17
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: track-current-work
|
|
3
|
+
title: Suivre la tâche courante dans WORKLOG
|
|
4
|
+
severity: required
|
|
5
|
+
description: Les assistants IA doivent lire et maintenir le worklog de tâche courante pour permettre une reprise fiable entre agents.
|
|
6
|
+
tags: ["worklog", "handoff", "agents-ia", "progression", "documentation"]
|
|
7
|
+
appliesTo: ["**/*"]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Avant de reprendre ou modifier le projet, lire `DOCS_FOLDER/WORKLOG/current-task.md` si le fichier existe.
|
|
11
|
+
|
|
12
|
+
Quand une tâche est commencée, interrompue, terminée ou laissée avec des suites connues, mettre à jour `DOCS_FOLDER/WORKLOG/current-task.md` avec :
|
|
13
|
+
|
|
14
|
+
- le statut courant ;
|
|
15
|
+
- la tâche en cours ;
|
|
16
|
+
- les fichiers ou zones concernés ;
|
|
17
|
+
- les vérifications réalisées ;
|
|
18
|
+
- les vérifications restantes ;
|
|
19
|
+
- la prochaine action recommandée.
|
|
20
|
+
|
|
21
|
+
Pour un ticket MVP réellement commencé, créer ou mettre à jour un document dédié dans `DOCS_FOLDER/WORKLOG/` si le suivi ne tient plus clairement dans `current-task.md`.
|
|
22
|
+
|
|
23
|
+
Le worklog ne remplace pas les ADR : il décrit l'avancement opérationnel et les points de reprise, pas les décisions durables.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
**date:** 2026-01-02
|
|
3
|
+
**status:** Idle
|
|
4
|
+
**description:** Point de reprise partagé entre assistants IA pour suivre la tâche courante, son statut, les fichiers touchés, les vérifications et la prochaine action.
|
|
5
|
+
**tags:** worklog, handoff, progression, reprise, agents-ia
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Current task
|
|
9
|
+
|
|
10
|
+
Ce document est le point de reprise entre assistants IA. Tout agent doit le lire avant de continuer une tâche et le mettre à jour avant de rendre la main.
|
|
11
|
+
|
|
12
|
+
## Statut courant
|
|
13
|
+
|
|
14
|
+
Idle
|
|
15
|
+
|
|
16
|
+
## Tâche courante
|
|
17
|
+
|
|
18
|
+
Aucune tâche d'implémentation applicative n'est en cours.
|
|
19
|
+
|
|
20
|
+
## Dernière action réalisée
|
|
21
|
+
|
|
22
|
+
Ajout de la convention de suivi de progression entre assistants IA :
|
|
23
|
+
|
|
24
|
+
- création de ce worklog courant ;
|
|
25
|
+
- création de la règle obligatoire `track-current-work` ;
|
|
26
|
+
- ajout de la lecture du worklog dans `AGENTS.md`, `CLAUDE.md` et `PROJECT-INSTRUCTIONS.md`.
|
|
27
|
+
|
|
28
|
+
## Prochaine action recommandée
|
|
29
|
+
|
|
30
|
+
Démarrer le Ticket 01 : initialiser le projet frontend React + TypeScript + Vite + Tailwind, puis mettre à jour ce worklog avec les fichiers créés, les vérifications lancées et les éventuels points de reprise.
|
|
31
|
+
|
|
32
|
+
## Fichiers ou zones concernés
|
|
33
|
+
|
|
34
|
+
- `AGENTS.md`
|
|
35
|
+
- `CLAUDE.md`
|
|
36
|
+
- `DOCS_FOLDER/AI/PROJECT-INSTRUCTIONS.md`
|
|
37
|
+
- `DOCS_FOLDER/AI/rules/track-current-work.md`
|
|
38
|
+
- `DOCS_FOLDER/WORKLOG/current-task.md`
|
|
39
|
+
- `DOCS_FOLDER/PRODUCT/`
|
|
40
|
+
- `DOCS_FOLDER/TECHNICAL/`
|
|
41
|
+
- `DOCS_FOLDER/ROADMAP/`
|
|
42
|
+
- `DOCS_FOLDER/ADRS/`
|
|
43
|
+
- `DOCS_FOLDER/AI/PROJECT-STACK.md`
|
|
44
|
+
- `DOCS_FOLDER/AI/PROJECT-USEFUL-COMMANDS.md`
|
|
45
|
+
|
|
46
|
+
## Vérifications récentes
|
|
47
|
+
|
|
48
|
+
- MCP Living Documentation disponible.
|
|
49
|
+
- `WORKLOG/current-task` visible dans l'inventaire MCP.
|
|
50
|
+
- `AI/rules/track-current-work` visible dans l'inventaire MCP.
|
|
51
|
+
- ADR créés avec métadonnées et accuracy `1`.
|
|
52
|
+
- `PROJECT-STACK` avec métadonnées et accuracy `1`.
|
|
53
|
+
- Aucun ADR sous le seuil de fiabilité.
|
|
54
|
+
|
|
55
|
+
## Notes de reprise
|
|
56
|
+
|
|
57
|
+
Le dépôt ne contient pas encore de code applicatif. Ne pas supposer l'existence de `package.json`, `src/`, scripts npm, tests ou configuration Tailwind avant le Ticket 01.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "living-documentation",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.16.0",
|
|
4
4
|
"description": "Local Markdown documentation hub with a built-in MCP server — coding agents create ADRs, draw diagrams and detect drift while you code.",
|
|
5
5
|
"main": "dist/src/server.js",
|
|
6
6
|
"bin": {
|