---
summary: "Field-test refinements to two `format()` output paths. `hn_get_stories` now distinguishes offset-past-end from genuinely-empty feeds. `hn_get_user` no longer duplicates the item type when rendering a typeless submission. Also migrates the project to the framework's directory-based changelog convention."
breaking: false
security: false
---

# 0.5.3 — 2026-05-21

## Changed

- `hn_get_stories` `format()`: three-branch empty-result handling. When `stories=[] && total>0 && offset>=total`, render `"<feed> feed — offset N is past the end (feed has M items)"` instead of bare `"<feed> feed — no stories"`. When `offset<total` but the page still came back empty (all items filtered out as dead/deleted), render `"<feed> feed — no live stories on this page (offset:N, feed total:M)"`. The original `"<feed> feed — no stories"` text is now reserved for `total===0`. Closes a parity gap between `structuredContent.total` and the `content[]` text — format-only clients (Claude Desktop) previously had no way to tell an over-paginated query apart from an empty feed.
- `hn_get_user` `format()`: submission rendering no longer duplicates the item type. The meta line skips the type token when the title fell back to `[${s.type}]`, so a typeless comment now renders as `**[comment]** — id:N | ...` instead of `**[comment]** — id:N | comment | ...`. Titled stories continue to carry the type token in meta (still shown exactly once). Title fallback also switched from `??` to `||` so an empty-string title (theoretical: HN-supplied title that strips to nothing) falls through to `[${s.type}]` instead of producing `**** — id:N | ...` with no type at all. Test invariant: type appears exactly once on every submission line.

## Added

- `changelog/<major.minor>.x/<version>.md` directory-based per-version changelog convention (framework standard). All 18 historical entries migrated from the monolithic `CHANGELOG.md` via `scripts/split-changelog.ts` and backfilled with `summary`/`breaking`/`security` frontmatter. `CHANGELOG.md` is now a 75-line navigation index regenerated by `bun run changelog:build`. `bun run changelog:check` gates devcheck against drift.
- `package.json` scripts: `changelog:build` and `changelog:check`.
- `changelog/template.md` pristine reference synced from `@cyanheads/mcp-ts-core/templates/changelog/template.md`.

## Tests

- 153 passing (up from 150). Added three branches to `get-stories.tool.test.ts` covering offset-past-end (with singular/plural item count), and the all-filtered-on-page case. Added an `it.each` parametric test to `get-user.tool.test.ts` that asserts the item type is rendered exactly once across undefined, empty, and real title shapes.

## Maintenance

- `@types/node ^25.8.0 → ^25.9.1`, `vitest ^4.1.6 → ^4.1.7` (both patch). No application impact.
- `scripts/devcheck.ts` resynced from `@cyanheads/mcp-ts-core` — `bun outdated` parser refactored into two filter passes with an extracted `stripWorkspaceMarker` helper. Functionally equivalent.
