Skip to content

fix(heal): exclude comment lines from inline-Caddyfile guard + drop trailing split element - #189

Merged
samo-agent merged 2 commits into
mainfrom
fix/heal-correctness-bugs
Jul 21, 2026
Merged

fix(heal): exclude comment lines from inline-Caddyfile guard + drop trailing split element#189
samo-agent merged 2 commits into
mainfrom
fix/heal-correctness-bugs

Conversation

@samo-agent

Copy link
Copy Markdown
Collaborator

Root-cause analysis

Two correctness bugs found in buildConfigHealScript after PR #188 merged:

BUG-1 — inline-Caddyfile guard misfires on comment lines

Root cause: The guard detecting whether app.mainHost appears as an inline site block in /etc/caddy/Caddyfile used:

if grep -qF 'samograph.samo.team' /etc/caddy/Caddyfile 2>/dev/null; then

This matches ANY line containing the host — including comment lines. samograph's Caddyfile has a comment mentioning 'samograph.samo.team' (historical note from when the site block lived inline), so the guard was misfiring with inline-caddyfile outcome even though the real vhost is correctly in sites.d with a provenance header.

Fix: Strip comment lines (lines whose first non-whitespace char is #) before the host check:

if grep -v '^[[:space:]]*#' /etc/caddy/Caddyfile 2>/dev/null | grep -qF 'samograph.samo.team'; then

Only a real structural (non-comment) line can now trigger the guard.

BUG-2 — trailing empty element from .split("\n") adds extra blank line in heredoc

Root cause: renderVhost() returns a string ending in "\n" (standard POSIX newline termination). Calling .split("\n") on it produces a trailing empty-string element "", which becomes an extra blank line between } and the heredoc closing delimiter — i.e., }\n\n instead of }\n.

The live file written by the same heredoc also had the extra blank line, so re-runs of heal still matched via cmp. But it is a byte discrepancy versus renderVhost's own output — if any external tool writes the "correct" file (without the double trailing newline), the next heal run would detect spurious drift.

Fix: Strip the trailing newline before splitting at all three call sites:

...regeneratedMainVhost!.replace(/\n$/, "").split("\n"),

Tests

New file: test/heal-correctness-bugs.test.ts — 8 tests.

BUG-1 regression tests (2 cases):

  • Comment line containing the mainHost does NOT trigger the guard
  • Real inline site block for the mainHost does still trigger the guard

BUG-2 regression tests:

  • Confirms renderVhost ends with \n (root cause documentation)
  • Heredoc write-to-temp branch has no trailing blank line after }
  • Heredoc fresh-write branch has no trailing blank line after }
  • Embedded heredoc lines are byte-identical to renderVhost output

TDD discipline: RED commit a07ea5d (failing tests) → GREEN commit 7c6811a (fixes applied).

Full suite result: 2311 pass, 1 expected PG-integration skip (requires PG_TEST_URL), tsc --noEmit clean.

Intentionally NOT changed

  • The SAMOHOST_APP_HEAL gate — not touched per brief
  • All other heal behaviors — strictly surgical, no scope creep

🤖 Generated with Claude Code

samo-agent and others added 2 commits July 20, 2026 21:56
…split trailing element

BUG-1: inline-Caddyfile guard uses bare `grep -qF <mainHost>` which
matches comment lines — samograph's Caddyfile has a comment containing
'samograph.samo.team', causing the guard to misfire with 'inline-caddyfile'
even though the real vhost is correctly in sites.d.

BUG-2: renderVhost returns a string ending in "\n"; .split("\n") produces
a trailing empty element that adds an extra blank line inside the heredoc
(double trailing newline after the closing "}").

8 tests added (6 must fail before the fix, 2 document root cause facts).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…railing split element

BUG-1 fix: the inline-Caddyfile guard for the app mainHost was using bare
`grep -qF <mainHost> /etc/caddy/Caddyfile` which matched comment lines too.
samograph's Caddyfile had a comment containing 'samograph.samo.team', causing
the guard to misfire with 'inline-caddyfile' outcome even though the real vhost
was correctly in sites.d with a provenance header.

Fix: pipe through `grep -v '^[[:space:]]*#'` before the mainHost grep, so only
structural (non-comment) lines can trigger the guard.

BUG-2 fix: renderVhost returns a string ending in "\n". Calling .split("\n") on
it produces a trailing empty-string element that adds an extra blank line inside
the heredoc (double trailing newline after the closing "}"). Fixed at all three
call sites by stripping the trailing newline before splitting: .replace(/\n$/, "").split("\n").

The live file written by the same heredoc also had the extra blank line so
re-runs still matched — but this was a byte discrepancy vs renderVhost output
that would mislead cmp comparisons against any externally-written file.

Tests: 8 tests in test/heal-correctness-bugs.test.ts, all passing GREEN.
Full suite: 2311 pass (1 PG-integration skip expected in local env without DB).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@samo-agent
samo-agent merged commit 640c2d1 into main Jul 21, 2026
1 check passed
@samo-agent
samo-agent deleted the fix/heal-correctness-bugs branch July 21, 2026 03:43
samo-agent added a commit that referenced this pull request Jul 21, 2026
…rigger CI

Merge origin/main into fix/domain-add-cp-http80-and-409-idempotent to
resolve the routing.md doc conflict (both sides added new ##-sections after
line 74) and ensure the PR has a clean merge commit for CI to run against.

All tests pass (2316 pass; packages/auth/pg.test.ts skipped locally —
requires Postgres service, provided by CI).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant