Repository navigation
Raw-text elements pass through the inline render path
- The preview now shows the authored value of a self-closing raw-text element such as
<textarea/>. markdown-it has no HTML parser, so that spelling used the inline path. The per-text-node source-offset spans then appeared inside the element's value as literal text. - A new inline rule turns a raw-text open tag and everything up to its end tag into a single token. It covers
script,style,textarea,title,xmp,noembed,noframesandiframe. An element with no end tag continues to the end of the block, matching browser display. - The renderer still stamps ordinary inline text with source offsets, and comment highlighting is unchanged.
Markdown links open in a Penmark tab; frontmatter card keeps its state
- Relative links to markdown files now open in a new Penmark preview tab. The opener is
vscode.openWithonpenmark.previewEditor, withvscode.openas fallback. Extensionless wiki-links resolve via an existence probe:.mdsuffix first, then the workspace root. mailto:andftp:links open in the system handler.file:URIs open inside the IDE. Neither is resolved as a relative file path. Untitled and remote documents skip existence probing, since there is no local directory to probe.- The frontmatter card keeps its collapse state across preview re-renders and tab switches. Persistence is
getState/setStatewhile the tab is open. Cards with more than three keys still start collapsed. Version 0.6.0.
OSS repository safeguards
- CI now uses immutable action and browser-container references, explicit least-privilege permissions, timeouts, pull-request run cancellation, and a stable
requiredaggregate check while preserving the full operating-system and VS Code-version matrix. - Release verification now runs under
bashwithsafe.directory,--shm-size=2g, and built-in Node ZIP manifest extraction inside the pinned Playwright container, accepts only three-component version tags, repeats the complete suite on the tagged commit, checks VSIX contents and version coherence, writes a checksum, creates an artifact build-provenance attestation (actions/attest-build-provenance), and smoke-tests the downloaded release asset; manual dispatch remains verification-only. - Added public runtime dependency notices and removed internal path examples from public artifacts.
Dependabot can read the lockfile again
package-lock.jsonheld conflict markers inside the innerpackages[""]version hunk. Every Dependabot update job stopped withdependency_file_not_parseable, so no dependency update reached a pull request.- The hunk now resolves to 0.6.0, which matches
package.jsonand the lockfile's own top-level version.
Agent-authored character entities render as punctuation
Agent-generated review comments can encode punctuation as decimal HTML character references, such as - for a hyphen. Penmark decoded only its own paired-hyphen storage sentinel (--), so a single reference reached the drawer and popover as visible source text. Penmark now renders any valid decimal reference as the character it denotes, using markdown-it's own validity rule so surrogates, NUL, control characters and noncharacters stay literal rather than becoming ill-formed text a save could write into the file.
This rendering is a presentation pass, applied where a note is handed to the preview and where one is exported for an agent. An entry's quote is exempt: it stays byte-faithful all the way to the drawer, which renders it at the point of display. Re-anchor re-adds the same quote at a new location, so a rendered quote would be stored and could never match the document again, and the next anchor loss would orphan a comment that would otherwise recover. It is deliberately not part of the storage codec. Decoding at parse time instead would have broken two things: quote recovery matches an entry's quote against raw document bytes, so a quoted passage that itself contains a reference would stop matching and the comment would orphan; and because the writer escapes only --, each read-and-save cycle would strip one more level from text the user never edited. Keeping the pass at the display seam leaves the spec's round-trip guarantee intact for every string. The validity rule is written out rather than imported: pulling markdown-it's helper into the eager extension entry took dist/extension.js from 53 KB to 136 KB, against a sub-50 ms activation budget. A test pins the copy to markdown-it across every code point. Format spec §6 gains a non-normative reader-side rule; regression tests cover the sentinel, standalone references, each rejected range, and the three consumers that need raw bytes.
Commenting no longer breaks the formatting it wraps
Commenting a bullet that opens in bold left the asterisks showing in the preview: **Subscription-billed.** rendered literally instead of bold. Reported from a real review session.
- An anchor at the start of a line no longer starts an HTML block — CommonMark treats any line beginning with
<!--as raw HTML through the closing-->, so the whole line skipped inline parsing. This was never specific to bold: inline code, links and italics on that line all rendered as source. It fired wherever inline-safety snapping pushed a span opener to the start of a block's content — bullets and ordered items (including nested ones), paragraphs, blockquotes, a paragraph's continuation line, and a closer landing at a line start. The renderer now declines the HTML-block rule for a line that leads with a pmk anchor and still carries content, so those lines take the inline path where the marker passes through verbatim at the exact extent (ADR 0006). Lines holding nothing but a marker keep the old behaviour, becausepmk:bandpmk:ranchors own their line by design (§4.2), and a hand-written<!-- note -->still behaves as stock CommonMark. - A highlight spanning list items stays visible past the first one — a bullet list is one block, so commenting three of five bullets is a span, not a range. The single
<mark>wrapped</li><li>, which is invalid nesting; because<mark>is not an HTML formatting element the browser closes it at</li>and discards the stray closer, silently dropping the highlight from every item after the first. The extent is now split into one<mark>per inline run, all sharing the comment id. An extent inside a single block still produces exactly one<mark>, byte-for-byte as before. - The split reads as one control — the fragments of a split highlight would otherwise each become a tab stop announcing the same comment. Only the first carries the keyboard affordance and the gutter dot; clicking any fragment still opens the popover, and all fragments light up together when the comment is active.
- Tests cover the boundary cases the fixtures missed — the anchored-doc fixture had no line-start anchor, so no snapshot could have caught this. New tests pin each block context that broke, both marker-only-line behaviours, a non-pmk comment at a line start, and the cross-block split down to whitespace handling.
Multi-block selections were already correct and are unchanged: a heading, paragraph, fenced code and list selected together still become one range wrapper with their formatting intact.
What's Changed
- fix(comments): keep markdown formatting intact around inline anchors by @carlosboeing in #50
- chore(git): add the private-workbench pre-commit guard by @carlosboeing in #53
- chore: gitignore local git worktrees by @carlosboeing in #54
- docs: scope worktrees to implementation work by @carlosboeing in #56
- docs: stop instructing agents to cite private design docs in public by @carlosboeing in #57
- Decode agent-authored decimal character references by @carlosboeing in #59
- chore(governance): align repository with OSS house standard by @carlosboeing in #61
- chore(governance): add SUPPORT.md to house standard by @carlosboeing in #62
- feat(preview): open markdown links in new tab and persist frontmatter state by @carlosboeing in #44
- fix(deps): remove merge markers from package-lock.json by @carlosboeing in #63
- chore(deps): bump dompurify from 3.4.11 to 3.4.14 by @dependabot[bot] in #48
- chore(deps-dev): bump undici from 7.28.0 to 7.29.0 by @dependabot[bot] in #45
- chore(deps-dev): bump fast-uri from 3.1.2 to 3.1.6 by @dependabot[bot] in #46
- chore(deps-dev): bump postcss from 8.5.16 to 8.5.26 by @dependabot[bot] in #52
- chore(deps-dev): bump js-yaml from 4.2.0 to 4.3.2 by @dependabot[bot] in #60
- chore(deps): bump mermaid from 11.16.0 to 11.16.1 by @dependabot[bot] in #47
- chore(deps-dev): bump brace-expansion from 2.1.1 to 2.1.4 by @dependabot[bot] in #66
- chore(deps): bump Playwright to 1.62.1 with container image by @carlosboeing in #67
- chore(deps): bump the minor-and-patch group across 1 directory with 13 updates by @dependabot[bot] in #68
- fix(render): keep raw-text elements whole on the inline path by @carlosboeing in #69
- docs(changelog): record raw-text inline fix as Unreleased by @carlosboeing in #70
- chore(githooks): install the drift-guard pre-push hook by @carlosboeing in #71
- docs(changelog): record the lockfile parse fix by @carlosboeing in #72
- chore(githooks): add post-merge and refresh housekeep by @carlosboeing in #73
- chore(githooks): scope check C to the Recently shipped section by @carlosboeing in #74
- chore(repo): add housekeep audit and reconcile shipped roadmap items by @carlosboeing in #95
- chore(release): prepare v0.6.0 changelog and roadmap by @carlosboeing in #96
- ci(release): set bash default shell for container steps by @carlosboeing in #97
- ci(release): fix container git safe.directory, shm-size, and VSIX extraction by @carlosboeing in #98
- ci(release): use actions/attest-build-provenance for VSIX attestation by @carlosboeing in #99
Full Changelog: v0.5.3...v0.6.0