fix(lint): only unwrap whole-page code fences, not mid-document blocks (takeover of #1417)

Detection used /m regexes (a fence anywhere) while the fixer used
string-anchored regexes, so a note that merely CONTAINS a ```markdown block
lost only its closing fence and was re-corrupted every autopilot lint cycle.
Detection and fix now share a single analyzeMarkdownWrap check: a page is
wrapped only when the entire body (after frontmatter) is one fence.

Salvaged from PR #1417 with the unrelated plugin.json + perplexity-research
commits dropped (off-mission, reference a private external system).

Co-authored-by: trinh-macbook <trinh-macbook@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-07-21 14:43:11 -07:00
co-authored by trinh-macbook Claude Fable 5
parent ed1563983f
commit 393369090b
2 changed files with 70 additions and 5 deletions
+51 -5
View File
@@ -68,6 +68,49 @@ const LLM_PREAMBLES = [
/^Absolutely\.?\s*Here[^.\n]*\.?\s*\n*/gim,
];
// ── Whole-page code-fence wrap (LLM artifact) ───────────────────────
//
// An LLM sometimes returns an ENTIRE page wrapped in a ```markdown fence.
// Strip that wrap — but ONLY when the whole body is wrapped, never when a note
// merely *contains* a ```markdown block mid-document (e.g. a Notion export that
// fences a config snippet). The earlier code detected the wrap with /m regexes
// (a fence anywhere) but stripped the closing fence with a string-anchored
// regex, so a mid-document block lost only its trailing ``` and was left with
// an open fence — re-corrupted on every autopilot lint cycle. Detection and fix
// now share this single check so they can't drift apart again.
function frontmatterLength(content: string): number {
const m = /^---\r?\n[\s\S]*?\r?\n---[ \t]*\r?\n?/.exec(content);
return m ? m[0].length : 0;
}
/**
* Treat a page as fence-wrapped only when the entire body (after any YAML
* frontmatter) is a single ```markdown fence: the first non-blank body line
* opens it, the last non-blank body line closes it, and no bare ``` appears
* between them (which would mean the fence closed early — not a whole-page
* wrap). Returns the unwrapped content (frontmatter preserved) when wrapped.
*/
function analyzeMarkdownWrap(content: string): { wrapped: boolean; unwrapped: string } {
const fmLen = frontmatterLength(content);
const head = content.slice(0, fmLen);
const lines = content.slice(fmLen).split('\n');
let first = 0;
while (first < lines.length && lines[first].trim() === '') first++;
let last = lines.length - 1;
while (last >= 0 && lines[last].trim() === '') last--;
if (first >= last) return { wrapped: false, unwrapped: content };
if (!/^```(?:markdown|md)\s*$/.test(lines[first].trim())) return { wrapped: false, unwrapped: content };
if (lines[last].trim() !== '```') return { wrapped: false, unwrapped: content };
for (let i = first + 1; i < last; i++) {
if (lines[i].trim().startsWith('```')) return { wrapped: false, unwrapped: content };
}
return { wrapped: true, unwrapped: head + lines.slice(first + 1, last).join('\n') };
}
// ── Rules ──────────────────────────────────────────────────────────
/**
@@ -126,8 +169,10 @@ export function lintContent(content: string, filePath: string, opts: LintContent
}
}
// Rule: Wrapping code fences (```markdown ... ```)
if (content.match(/^```(?:markdown|md)\s*\n/m) && content.match(/\n```\s*$/m)) {
// Rule: Wrapping code fences — the WHOLE page body wrapped in ```markdown
// ``` (an LLM artifact). A ```markdown block mid-document is legitimate and
// must NOT trigger this (see analyzeMarkdownWrap).
if (analyzeMarkdownWrap(content).wrapped) {
issues.push({
file: filePath, line: 1, rule: 'code-fence-wrap',
message: 'Page wrapped in ```markdown code fences (LLM artifact)',
@@ -291,9 +336,10 @@ export function fixContent(content: string): string {
fixed = fixed.replace(pattern, '');
}
// Fix wrapping code fences
fixed = fixed.replace(/^```(?:markdown|md)\s*\n/, '');
fixed = fixed.replace(/\n```\s*$/, '');
// Fix wrapping code fences — only a genuine whole-page wrap (see
// analyzeMarkdownWrap); never strip the closing fence of a mid-note block.
const wrap = analyzeMarkdownWrap(fixed);
if (wrap.wrapped) fixed = wrap.unwrapped;
// Clean up excessive blank lines left by fixes
fixed = fixed.replace(/\n{3,}/g, '\n\n');
+19
View File
@@ -32,6 +32,14 @@ describe('lintContent', () => {
expect(issues.some(i => i.rule === 'code-fence-wrap')).toBe(true);
});
test('does not flag a mid-document markdown code block as a page wrap', () => {
// Regression: a note that merely CONTAINS a ```markdown block (e.g. a
// Notion export fencing a config snippet) is not a whole-page wrap.
const content = '---\ntitle: Notes\ntype: note\ncreated: 2026-05-25\n---\n\nIntro paragraph.\n\n```markdown\nKEY=value\nPORT=3002\n```\n';
const issues = lintContent(content, 'test.md');
expect(issues.some(i => i.rule === 'code-fence-wrap')).toBe(false);
});
test('detects placeholder dates', () => {
const content = '---\ntitle: Test\ntype: person\ncreated: YYYY-MM-DD\n---\n\n# Test';
const issues = lintContent(content, 'test.md');
@@ -97,6 +105,17 @@ describe('fixContent', () => {
expect(fixed).toContain('# Title');
});
test('leaves a mid-document markdown code block intact (keeps its closing fence)', () => {
// Regression for the autopilot churn: fixContent used to strip only the
// trailing ```, leaving the fence open and the note re-corrupted each cycle.
const input = '---\ntitle: Notes\ntype: note\ncreated: 2026-05-25\n---\n\nIntro paragraph.\n\n```markdown\nKEY=value\nPORT=3002\n```\n';
const fixed = fixContent(input);
const fenceLines = (fixed.match(/^```/gm) ?? []).length;
expect(fenceLines).toBe(2);
expect(fixed).toContain('```markdown');
expect(fixed.trimEnd().endsWith('```')).toBe(true);
});
test('cleans up excessive blank lines after fix', () => {
const input = 'Of course. Here is the brain page.\n\n\n\n# Title\n\nContent.';
const fixed = fixContent(input);