fix(board): track an open HTML comment through to its closer
Skipping lines that START with the comment opener is not the same as skipping a comment. Every continuation line of a wrapped comment under the NESTE heading still looked like prose, so the excerpt became comment internals instead of the next step. Both the board line and the route line wrap easily; measured, 1 of 28 repos was affected, with the symptom held down only by the convention of keeping those comments one-line. An open comment is now tracked to its closer, and a NESTE block that is nothing but a comment reports an empty block rather than promoting the comment's own text. Two limits are the format, not leftovers: an HTML comment body may not contain the closer at all, so a rationale quoting it still ends its own comment early. The fixture is the real shape - one-line, wrapped, one-line, prose - because a lone wrapped comment passes even with a flag that never resets, and the continuation marker sits at the start of its line because the table's 38-char cut would otherwise truncate it away and the check would pass against the broken code too. board-selftest 138 -> 142. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014K262DRWBJzEpWoMsBjB8J
This commit is contained in:
parent
d0a5ffe515
commit
123d40e4b4
10 changed files with 96 additions and 10 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "repo-mailbox",
|
||||
"version": "0.20.0",
|
||||
"version": "0.20.1",
|
||||
"description": "Local mailbox for coordination between Claude Code sessions in different repositories. Directed messages and broadcasts as plain Markdown files on your own disk, injected as context at session start. Local, private, no network.",
|
||||
"author": {
|
||||
"name": "Kjell Tore Guttormsen"
|
||||
|
|
|
|||
27
CHANGELOG.md
27
CHANGELOG.md
|
|
@ -5,6 +5,33 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.20.1] - 2026-08-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- **A multi-line HTML comment under the NESTE heading no longer leaks into the
|
||||
next-step excerpt.** `board.sh` skipped lines that *started* with the comment
|
||||
opener, which is not the same thing as skipping a comment: every continuation
|
||||
line of a wrapped comment still looked like prose, so the excerpt became
|
||||
comment internals — `scope=local; rationale=...` where the next step should
|
||||
have been. An open comment is now tracked through to its closer. Both the
|
||||
board line and the route line wrap easily, and the affected repo was this one
|
||||
(1 of 28 measured), where the symptom was held down only by the convention of
|
||||
writing those comments on a single line.
|
||||
|
||||
Two limits are the format, not leftovers. An HTML comment body may not contain
|
||||
`-->` at all, so a route rationale that quotes the closer still terminates its
|
||||
own comment early — no fix here can change that. And a NESTE block consisting
|
||||
of nothing but a comment now reports an empty block rather than promoting the
|
||||
comment's own text, which is what it always should have said.
|
||||
|
||||
`board-selftest.sh` 138 → 142 checks. The fixture is the real shape on
|
||||
purpose — one-line comment, wrapped comment, one-line comment, prose — because
|
||||
a lone wrapped comment would pass even with an open-comment flag that never
|
||||
resets. The continuation marker sits at the start of its line for the same
|
||||
reason: further in, the table's 38-character cut would truncate it away and
|
||||
the check would pass against the broken code too.
|
||||
|
||||
## [0.20.0] - 2026-08-03
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ marketplace plugin. Three components, one boundary:
|
|||
- **Board (`scripts/board.sh`):** cross-repo attention board. Reads STATE.md
|
||||
next-step blocks + board lines, `git status`, and mailbox pending counts, and
|
||||
prints one line per repo. Read-only by construction: it writes to no repo, no
|
||||
STATE.md and no mailbox. Pinned by `board-selftest.sh` (138 checks).
|
||||
STATE.md and no mailbox. Pinned by `board-selftest.sh` (142 checks).
|
||||
|
||||
**It lives here because the mailbox is one of its three inputs, and it carries
|
||||
the same axis distinction the mailbox does.** A pending count means *others
|
||||
|
|
@ -287,7 +287,7 @@ obligations in another repo.
|
|||
builtins only in hook and tests.
|
||||
- TDD: no behavior change without a failing selftest check first.
|
||||
`bash scripts/coord-selftest.sh` must exit 0 (183/183),
|
||||
`bash scripts/board-selftest.sh` must exit 0 (138/138) and
|
||||
`bash scripts/board-selftest.sh` must exit 0 (142/142) and
|
||||
`bash scripts/route-selftest.sh` must exit 0 (73/73).
|
||||
- English for all code, docs, and commit messages (public repo). Norwegian
|
||||
trigger aliases in the skill description are deliberate.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
*AI-generated: all code produced by Claude Code through dialog-driven development.*
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
|
@ -151,7 +151,7 @@ Note that raising the inbox's priority (Rule 7) deliberately does **not** widen
|
|||
## Development
|
||||
|
||||
bash scripts/coord-selftest.sh # 183 checks against a throwaway mailbox
|
||||
bash scripts/board-selftest.sh # 138 checks against a throwaway repo tree
|
||||
bash scripts/board-selftest.sh # 142 checks against a throwaway repo tree
|
||||
bash scripts/route-selftest.sh # 73 checks, incl. the route->board round trip
|
||||
npm test # all three selftests via node --test
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "repo-mailbox",
|
||||
"version": "0.20.0",
|
||||
"version": "0.20.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
|
|
|
|||
|
|
@ -366,6 +366,55 @@ check "NESTE marker anchored to heading, not any content line mentioning it" $?
|
|||
printf '%s' "$NESTE_OUT" | grep -qE 'repo-neste-lookalike.*tilfeldig linje'
|
||||
[ $? -ne 0 ]; check "content line mentioning NESTE is not mistaken for the marker" $?
|
||||
|
||||
# A MULTI-LINE HTML comment under NESTE must be skipped THROUGH TO ITS CLOSER,
|
||||
# not just on its opening line. Skipping only lines that START with the opener
|
||||
# leaves every continuation line looking like prose, so the excerpt becomes
|
||||
# comment internals - measured on the real tree, this repo was 1 of 28 affected
|
||||
# and held the symptom down by keeping its comments one-line.
|
||||
# The fixture is the REAL shape deliberately: one-line, multi-line, one-line,
|
||||
# prose. A lone multi-line comment would prove enter-and-exit but not that the
|
||||
# open-comment flag RESETS - a flag stuck on would still pass that weaker
|
||||
# fixture by falling through to the same prose.
|
||||
# NOTE: an HTML comment body cannot contain '-->' at all (that is the format,
|
||||
# not a board.sh limit), so a rationale that quotes the closer still ends the
|
||||
# comment early. That constraint survives this fix by construction.
|
||||
mkrepo "$ROOT/repo-multiline-comment"
|
||||
{
|
||||
echo "# STATE - repo-multiline-comment"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Opus 5/high -->"
|
||||
# The marker sits at the START of the continuation line on purpose: the table
|
||||
# cuts the excerpt at 38 characters, so a marker further in would be truncated
|
||||
# away and the check would pass against the BROKEN code too.
|
||||
echo "<!-- route: path=known; verification=strong; reversibility=cheap;"
|
||||
echo " FORTSETTELSESLINJE som ikke er noe neste steg;"
|
||||
echo " scope=local; rationale=brer seg over flere linjer. -->"
|
||||
echo "<!-- route-last: model=Opus 5; effort=high; completed=yes -->"
|
||||
echo "Det ekte neste steget staar under kommentarblokken."
|
||||
} > "$ROOT/repo-multiline-comment/STATE.md"
|
||||
ML_OUT="$("$BOARD" --roots "$ROOT" 2>/dev/null)"
|
||||
printf '%s' "$ML_OUT" | grep -qE 'repo-multiline-comment.*ekte neste steget'
|
||||
check "multi-line HTML comment skipped through to its closer" $?
|
||||
printf '%s' "$ML_OUT" | grep -q 'FORTSETTELSESLINJE'
|
||||
[ $? -ne 0 ]; check "comment continuation line never becomes the NESTE excerpt" $?
|
||||
# The board line still parses: it is read by its own anchored grep, so the
|
||||
# excerpt fix must not disturb it.
|
||||
printf '%s' "$ML_OUT" | grep -qE 'repo-multiline-comment.*planned'
|
||||
check "board line still parsed alongside a wrapped route comment" $?
|
||||
|
||||
# A NESTE block that is NOTHING BUT a multi-line comment has no next step, and
|
||||
# must say so rather than promote comment internals to the excerpt.
|
||||
mkrepo "$ROOT/repo-comment-only"
|
||||
{
|
||||
echo "# STATE - repo-comment-only"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- route: path=known; verification=strong;"
|
||||
echo " scope=local; rationale=BARE EN KOMMENTAR her. -->"
|
||||
} > "$ROOT/repo-comment-only/STATE.md"
|
||||
CO_OUT="$("$BOARD" --roots "$ROOT" 2>/dev/null)"
|
||||
printf '%s' "$CO_OUT" | grep -qE 'repo-comment-only.*tom NESTE-blokk'
|
||||
check "NESTE block of only a multi-line comment reports an empty block" $?
|
||||
|
||||
"$BOARD" --help >/dev/null 2>&1; check "--help exits 0" $?
|
||||
|
||||
# Unreadable root is a no-op, not a crash.
|
||||
|
|
|
|||
|
|
@ -274,11 +274,21 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
|
|||
# the heading itself; strip markdown bold/bullet noise. Anchored to the
|
||||
# heading form (measured 26/27 real repos, decided 2026-08-02) so a prose
|
||||
# line that merely mentions the word is never mistaken for the marker.
|
||||
#
|
||||
# A comment is tracked to its CLOSER, not just recognised on its opening line.
|
||||
# Skipping only lines that start with the opener left every continuation line
|
||||
# of a wrapped comment looking like prose, so the excerpt became comment
|
||||
# internals - the board line and the route line both wrap easily, and this
|
||||
# repo was the one of 28 that hit it, held down only by writing them on one
|
||||
# line. What this does NOT do, and cannot: an HTML comment body may not
|
||||
# contain the closer at all, so a route rationale that quotes it still ends
|
||||
# its own comment early. That is the format, not a defect left here.
|
||||
neste="$(awk '
|
||||
/^#+[[:space:]].*NESTE/ { flag=1; next }
|
||||
flag {
|
||||
if (incomment) { if ($0 ~ /-->/) incomment=0; next }
|
||||
if ($0 ~ /^[[:space:]]*$/) next
|
||||
if ($0 ~ /^[[:space:]]*<!--/) next
|
||||
if ($0 ~ /^[[:space:]]*<!--/) { if ($0 !~ /-->/) incomment=1; next }
|
||||
if ($0 ~ /^#/) next
|
||||
print; exit
|
||||
}' "$state" 2>/dev/null \
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ description: >-
|
|||
user names no repo and no tool — choosing *between* repos is this skill. Not for
|
||||
"where were we" inside the current repo: that is this repo's own STATE.md,
|
||||
already injected at session start.
|
||||
version: "0.20.0"
|
||||
version: "0.20.1"
|
||||
---
|
||||
|
||||
# board — which repo deserves the next session
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ description: >-
|
|||
covers retiring a broadcast that has become wrong or obsolete: "retract that
|
||||
broadcast", "that announcement is outdated, pull it", "trekk tilbake kringkastingen",
|
||||
"den broadcasten er utdatert".
|
||||
version: "0.20.0"
|
||||
version: "0.20.1"
|
||||
---
|
||||
|
||||
# coord-send — natural-language front door for inter-repo messages
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ description: >-
|
|||
the operator names no model and no tool — choosing the model for the next
|
||||
session IS this skill. Not for choosing which REPO gets the next session:
|
||||
that is the `board` skill.
|
||||
version: "0.20.0"
|
||||
version: "0.20.1"
|
||||
---
|
||||
|
||||
# route — what the next session should run with
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue