wendkeep 0.54.0 → 0.55.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/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to **wendkeep** are documented here. Format based on
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this project follows
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.55.0] — 2026-07-25
8
+
9
+ ### Fixed
10
+
11
+ - **O `[derivadas]` do doctor deixa de acusar nota já correta.** O `doctor` reportava
12
+ `5 link(s) faltando` numa nota onde os cinco estavam presentes; o
13
+ `note repair-sections --apply` rodava, não mudava nada (`unchanged`), e o doctor voltava a
14
+ acusar — um vermelho que nenhum reparo fechava. Causa: detector e reparador localizavam a
15
+ seção por critérios diferentes — `## <heading>` como substring solta contra
16
+ `\n## <heading>\n` ancorado. Numa nota de sessão isso é fatal, porque ela transcreve a
17
+ conversa, e uma conversa **sobre** as seções cita os nomes delas: o detector casava a
18
+ menção em prosa e lia o texto errado. Agora existe um localizador único
19
+ (`findSectionBounds`) por onde detector e reparo obrigatoriamente passam — corrigir apenas
20
+ o marcador deixaria dois localizadores independentes, que foi como o bug nasceu.
21
+ Capability `vault-doctor` (DIAG-7).
22
+
7
23
  ## [0.54.0] — 2026-07-25
8
24
 
9
25
  ### Added
@@ -108,11 +108,25 @@ export function listSessionNotes(vaultBase) {
108
108
  return out;
109
109
  }
110
110
 
111
+ // Localizador ÚNICO da seção — detector e reparador passam por aqui.
112
+ //
113
+ // Um heading Markdown começa em coluna zero; casar `## X` como substring solta encontra
114
+ // qualquer menção em prosa. A nota de sessão é justamente o lugar onde isso acontece: ela
115
+ // transcreve a conversa, e uma conversa SOBRE as seções cita os nomes delas. Foi assim que
116
+ // o detector passou a acusar links faltando que estavam presentes na seção verdadeira,
117
+ // enquanto o reparo (que já usava o marcador ancorado) não achava nada a fazer.
118
+ export function findSectionBounds(content, heading) {
119
+ const marker = `\n## ${heading}\n`;
120
+ const start = content.indexOf(marker);
121
+ if (start === -1) return null;
122
+ const bodyStart = start + marker.length;
123
+ const nextRel = content.slice(bodyStart).search(/\n## /);
124
+ return { start, bodyStart, bodyEnd: nextRel === -1 ? content.length : bodyStart + nextRel };
125
+ }
126
+
111
127
  const sectionBody = (content, heading) => {
112
- const i = content.indexOf(`## ${heading}`);
113
- if (i < 0) return null;
114
- const j = content.indexOf('\n## ', i + 3);
115
- return content.slice(i, j < 0 ? content.length : j);
128
+ const at = findSectionBounds(content, heading);
129
+ return at ? content.slice(at.start, at.bodyEnd) : null;
116
130
  };
117
131
 
118
132
  // O que a nota DEVERIA listar mas não lista. Excedente (link posto à mão) não é sintoma
@@ -185,12 +199,9 @@ export const isDerivedPlaceholder = (line) => /^-?\s*Nenhum[ao]?\s+\S+.*registra
185
199
  // vault escreveu na seção não pode sumir num conserto automático.
186
200
  function defaultUpsert(content, heading, lines) {
187
201
  if (!lines.length) return content;
188
- const marker = `\n## ${heading}\n`;
189
- const start = content.indexOf(marker);
190
- if (start === -1) return content; // heading ausente: nunca inventa seção em nota alheia
191
- const bodyStart = start + marker.length;
192
- const nextRel = content.slice(bodyStart).search(/\n## /);
193
- const bodyEnd = nextRel === -1 ? content.length : bodyStart + nextRel;
202
+ const at = findSectionBounds(content, heading);
203
+ if (!at) return content; // heading ausente: nunca inventa seção em nota alheia
204
+ const { bodyStart, bodyEnd } = at;
194
205
 
195
206
  const prose = [];
196
207
  const items = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wendkeep",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "description": "A persistent-memory harness for AI coding agents on your Obsidian vault: turn-by-turn session capture plus a native, zero-dependency spec→change→verify→archive loop (sensor-gated, independent verdict, mutation discrimination). Local-first, agent-agnostic (Claude Code, Codex, Cursor…).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -46,6 +46,6 @@
46
46
  "url": "https://github.com/rogersialves/wendkeep/issues"
47
47
  },
48
48
  "devDependencies": {
49
- "wendkeep": "^0.52.0"
49
+ "wendkeep": "^0.54.0"
50
50
  }
51
51
  }