chore: version packages#39
Merged
Merged
Conversation
jacekradko
previously requested changes
May 29, 2026
jacekradko
left a comment
Contributor
There was a problem hiding this comment.
Blocking the initial publish
github-actions
Bot
force-pushed
the
changeset-release/main
branch
23 times, most recently
from
June 5, 2026 01:48
ec71843 to
94c3160
Compare
clerk-cookie
force-pushed
the
changeset-release/main
branch
from
June 5, 2026 11:38
94c3160 to
45bc986
Compare
commit: |
Contributor
Author
API Changes Report
Summary
No API Changes DetectedAll packages have stable APIs with no detected changes. Report generated by Break Check |
clerk-cookie
force-pushed
the
changeset-release/main
branch
3 times, most recently
from
June 5, 2026 17:12
7133999 to
adc5986
Compare
clerk-cookie
force-pushed
the
changeset-release/main
branch
2 times, most recently
from
June 5, 2026 19:49
a9ceb9e to
cc31e54
Compare
clerk-cookie
force-pushed
the
changeset-release/main
branch
from
June 5, 2026 20:03
cc31e54 to
6ac6eee
Compare
jacekradko
dismissed
their stale review
June 8, 2026 16:12
Stale self-block; repo is now public and 0.1.0 is ready to publish.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@clerk/break-check@0.1.0
Minor Changes
#18
edca94cThanks @jacekradko! - Add opt-in AI-powered analysis of detected API changes. WhenBREAK_CHECK_ANTHROPIC_API_KEYis set, break-check sends each package's rule-based change list and a compact view of the baseline/current API surface to Anthropic's Claude. The model re-classifies changes (overriding the rule-based verdict in either direction, with rationale and migration guidance) and scans for breaks the rules missed. Failures fall back to rule-based output, so the CLI exit code never depends on AI availability. By default the AI call is skipped for diffs that the rule-based pass classified as pure additions; setBREAK_CHECK_AI_STRICT=1(orai.strict: truein config, or pass--ai-strict) to run the deeper scan in those cases too. Configurable via a newaiblock inbreak-check.config.jsonand the--no-ai/--ai-model/--ai-strictCLI flags.#57
e6f0b3eThanks @jacekradko! - Stop the AI reviewer confirming two backwards-compatible changes as breaking, and add a config escape hatch for the rest.Adding an optional property (including one widened into a
Pick/Omit) was confirmed breaking because the prompt never said it was safe and never forbade a verdict left conditional on a fact already in context. New classification rules fix that. Adding a required field to a read-only output type was confirmed breaking because the model only ever saw a type's forward references, never its callers, so it couldn't tell an input type from an output one. The focused verdict context now also carries a "Usage sites" block: the signatures that reference each changed type, gathered across the package's sibling subpath surfaces (the type and the function returning it usually live in different rollups). Both fixes only ever enable a downgrade, which still stays gated behind--ai-apply-downgrades.New
acknowledgedChangesconfig option: list a breaking change by name (OAuthConsentInfo,@clerk/shared#OAuthConsentInfo, or aClerk.__internal_*glob) to downgrade it to non-breaking and tag itacknowledgedin the report. Unlike an AI downgrade this is unconditional.Fixes #56.
#51
98cb225Thanks @jacekradko! - Rework the AI reviewer around the downgrade decision and split the oldstrictflag into two orthogonal opt-ins.The verdict call now sends a focused context instead of the whole API surface: for each change, only the definitions of the types its signature references (resolved transitively through API Extractor's canonical references), with a referenced type's baseline definition included where it changed so equivalence can be judged old-vs-new. On a large package that is a handful of types instead of hundreds of signatures. The change list is compact JSON and rationales are capped at one sentence.
Downgrades are no longer applied by default. A
breaking -> non-breakingverdict is the only operation that can clear a flagged break, so by default it is recorded as a suggestion (the change stays breaking) and applied only with--ai-apply-downgrades/BREAK_CHECK_AI_APPLY_DOWNGRADES/ai.applyDowngrades. The default path therefore cannot turn a flagged break into a non-break, and if a referenced type can't be resolved the model is told to keep "breaking", so a thin context costs a missed downgrade (noise), never a shipped break.The old
strictflag is removed. Its missed-breaks audit (which sends both the baseline and current surfaces so the model can diff old vs new, and reviews additions-only diffs) is now its own opt-in:--ai-scan/BREAK_CHECK_AI_SCAN/ai.scanForMissed. Applying downgrades and running the audit are independent; combine them for the most thorough run.Migration:
--ai-strictandai.strictno longer exist. The flag errors as an unknown option, and a config that still setsai.strictnow fails validation with an "unrecognized key" error (theaiblock rejects unknown keys) instead of silently doing nothing. Replace it withai.scanForMissed: true(the audit) and/orai.applyDowngrades: true(relax verdicts).#5
dcabe04Thanks @jacekradko! - Rewrite the API diff analyzer to use structured comparison instead of joined-token string diffs. Parameter renames and whitespace differences no longer surface as breaking changes; optional/required parameter flips, added optional parameters, return-type changes, and property-type changes are now classified individually. Interface body edits are no longer double-counted at the container level.#25
14ec529Thanks @jacekradko! - Composite Action can now consume a baseline snapshot uploaded from a separatepush-to-main workflow, instead of always rebuilding the base ref. Set the new
baseline-artifact-nameinput to the artifact name; the Action downloads themost recent matching artifact on
base-refand uses it as the baseline. Fallsback to the worktree rebuild on miss, expiry, or download failure, so existing
configurations keep working unchanged. Optional
baseline-max-age(hours)caps how old a downloaded artifact may be before falling back. See the
"Larger monorepos" section of the README for the producer workflow.
#27
11da46cThanks @jacekradko! - Snapshot metadata (break-check.snapshot.json) now records the producingbreakCheckVersionandapiExtractorVersionunderschemaVersion: 3. Onbreak-check detect, a baseline whose recorded@microsoft/api-extractormajor differs from the running one is refused with a structured error, since the hand-rolled.api.jsonreader is not guaranteed compatible across API Extractor majors and would otherwise produce silently nonsensical diffs. Pre-stamp baselines (schemaVersion 1 or 2) still load, with a stderr warning suggesting regeneration.parseApiJsonalso gained a shape check that throws on an unrecognized.api.jsonstructure rather than returning an empty surface.#59
aae2962Thanks @jacekradko! - Make the report breaking-first and stop silently trusting incomplete AI reviews.A single AI review call that fails (the classic trigger: one huge type whose
before/after snippet dominated the request) used to leave every change in that
subpath with its pessimistic rule-based verdict and no annotation, while the
report still claimed full AI coverage. The analyzer now caps oversized
before/after snippets and bounds the focused-surface block by size so the call
fits, splits-and-retries a failed batch into smaller ones, and records any
review it still can't complete. Those gaps surface in the report: the "reviewed
by" stamp is marked
(partial)and a callout lists the affected subpaths.The report also leads with breaking changes: a breaking-changes index up front
(survives the size-budget truncation), packages and subpaths ordered
breaking-first, breaking sections never collapsed, and non-breaking sections
collapsed behind
<details>in large reports.#9
126506dThanks @jacekradko! - Ship a reusable GitHub Action. Consumers can replace a hand-rolled snapshot/detect/comment workflow withuses: clerk/break-check@v1after their checkout/node/pnpm setup. The Action uses a git worktree for the baseline (so the PR checkout is never disturbed), runsbreak-checkviapnpm dlx, and posts (or updates) a single PR comment with the report. Inputs cover the config path, base ref, setup command, break-check version, comment toggle, andfail-on-breaking; outputs exposehas-breaking-changesand the report path.#41
d8abb51Thanks @jacekradko! - Stop reporting coverage/discovery growth as phantom API additions, and boundthe total report size.
When an already-baselined package gained subpaths (a coverage bump, a genuine
new export, or a discovery change such as wildcard subpath expansion),
detectdiffed each new subpath against an empty baseline and emitted one addition per
exported member. On
@clerk/sharedthat meant a ~440 KB report claimingthousands of additions, none of them real API changes, which then exceeded
GitHub's 65 KB comment limit and failed to post. Three fixes:
now collapsed to a single "New subpath export" addition instead of one per
member (symmetric with the existing subpath-removal handling). Brand-new
packages still stay silent on first run.
discoveryVersion(schemaVersion: 4).detectrefuses a baseline whose discovery version is older than the runningbreak-check, and refuses a producer-stamped baseline that predates the field, with
the same "regenerate against the base ref" error the API Extractor major gate
uses. break-check's Action regenerates the baseline every run, so it is unaffected;
consumers caching a baseline across a break-check upgrade must regenerate once.
maxReportChars,default 60,000): whole package sections are included until the budget is
reached, then the remainder is dropped with a notice pointing at the full
JSON report, so an oversized diff still posts a valid comment.
break-check detectnow exits with code 3 (distinct from the generic error exit 1)when it refuses a baseline as incompatible, so CI can recognize the condition.
The GitHub Action recovers automatically: on an incompatible-baseline refuse it
rebuilds the baseline with the current break-check and retries instead of failing.
Fixes #40.
#14
e7ece09Thanks @jacekradko! - Breaking:ConfigSchemais no longer exported from the package root. It was an internal validation detail used byloadConfig, and re-exporting it forced consumers to upgrade zod in lockstep whenever zod'sZodObject/ZodArray/ZodEnumgeneric shapes change (which is exactly what v3 → v4 just did, and what break-check's self-dogfood flagged). UseBreakCheckConfig(the inferred output type) instead; that export is unchanged.Also bumps zod from 3 to 4.
#36
6b60743Thanks @jacekradko! - Make per-entry extraction failures non-fatal.Previously, a single subpath that API Extractor couldn't process (ambient-global augmentations like
@clerk/testing/cypress, root-level.d.tsfiles like@clerk/astro/env, anything that triggered anInternalErrorfrom AE) tanked the entiresnapshotordetectrun. Common Cypress, Playwright, and Astro patterns made break-check unusable on real monorepos.Per-entry failures now emit a
[break-check] warning: skipping <pkg> <subpath>: <reason>line on stderr, are collected on the detector (detector.lastSkippedEntries), and surface in the detect report as a "could not snapshot N subpaths" callout above the diff so reviewers don't mistake an omitted surface for a clean one. The run continues with whatever extracted. Package-level fatals (missingpackage.json, zero discoverable entries) still throw, since those usually mean the config is wrong rather than one subpath is weird.AnalysisResultgains an optionalskippedEntriesarray ({ packageName, subpath, reason }[]); JSON consumers can read it directly. Bothsnapshotanddetectaccept--fail-on-skipped, which turns any skip back into a non-zero exit, the safer setting when producing a committed baseline where a silently-omitted surface would otherwise read as "no changes."Fixes #34 (ambient-global crash on
@clerk/testing/cypress).Fixes #33 (
Unable to determine modulecrash on@clerk/astro/env).#50
d2f9d66Thanks @jacekradko! - Stop reporting content-hashed bundler chunks under"./*"as breaking add/remove subpaths.When a wildcard export globs into a bundler output dir, the shared chunks emitted by rolldown/tsdown/esbuild/rollup (
index-Dq-_K2VH.mjs,url-CcPzUbGM.mjs, ...) were each turned into a public subpath by the #26 wildcard expansion. Those chunks are not public API and their content hash flips every build, so any real change renamed them and surfaced as a removed subpath (breaking) plus an added one, recommending a phantom major.Wildcard expansion now drops matches whose basename ends in a high-entropy
-<8 base64url chars>suffix, controlled by a newignoreHashedChunksconfig field (on by default). The filter runs on both the current discovery and the baseline read, so an older baseline that recorded chunk subpaths reconciles without a forced regeneration (noDISCOVERY_VERSIONbump).ignoreSubpathsnow also accepts globs (./internal-*,./chunk-*) as the explicit escape hatch for anything the heuristic misses.Fixes #49.
#42
3008f95Thanks @jacekradko! - Rename the package to@clerk/break-checkand the CLI binary tobreak-check. The default config file is nowbreak-check.config.jsonand per-package snapshot metadata is written asbreak-check.snapshot.json; the pre-renamesnapi.config.jsonandsnapi.snapshot.jsonare still read as deprecated fallbacks. Environment variables are renamed fromSNAPI_*toBREAK_CHECK_*, and the GitHub Action's PR comment marker is nowbreak-check-action.#22
48383ccThanks @jacekradko! - AddBREAK_CHECK_AI_MODELenvironment variable for selecting the AI reviewer's model from CI without editing config. Priority is--ai-model>BREAK_CHECK_AI_MODEL>ai.modelinbreak-check.config.json>claude-sonnet-4-6. The README now documents the AI reviewer's env vars, theaiconfig block, and when to opt into Opus 4.7.#19
ce9211cThanks @jacekradko! - Snapshot every subpath export, not just the package root. Break Check now walks the fullexportsmap per package and produces one API snapshot per non-wildcard subpath (e.g.@clerk/shared's./react,./errors,./utils, etc.). Wildcard patterns (./*,./internal/foo/*) are skipped with a warning since they're not single API surfaces. Each snapshot lives in<safe-pkg>/<safe-pkg>__<subpath>.api.jsonand a per-packagebreak-check.snapshot.json(schema v2) lists every entry. Diffs report changes per subpath, including a synthesized BREAKING change when an entire subpath is removed. Old v1 baseline directories with a single root snapshot continue to read correctly during the transition. A new top-levelignoreSubpaths: string[]config option drops matching subpaths from discovery (exact match, e.g."./internal").#61
eb295f1Thanks @jacekradko! - Stop the AI reviewer from downgrading a reference to an export-blocked dependency subpath.When a bundler moves a re-exported type into an internal chunk the dependency blocks in its
exports(e.g.@clerk/shareddeclares"./_chunks/*": null), a public.d.tscan emitimport("@clerk/shared/_chunks/index-DcO1-lAR").Jwt. The structural shape is unchanged, but the specifier does not resolve for consumers: undernodenextit errors (TS2307), and withskipLibCheck: trueit silently degrades toany. The rule pass flagged this breaking, but the AI reviewer downgraded it as a "build artifact rename", so with--ai-apply-downgradesit shipped green.break-check now extracts the inline
import("...")specifiers a new signature introduces (present in the after snippet, absent in the before) and classifies each against the target dependency'spackage.jsonexports: a subpath that resolves tonull, or matches no key, is non-resolvable. When the dependency can't be located on disk it falls back to a/_chunks/and content-hash heuristic. A change carrying such a reference is pinned breaking and the AI may not relax it, even under--ai-apply-downgrades; the report shows a callout naming the specifier and drops the "re-run with --ai-apply-downgrades" nudge for it. The note bypasses break-check's own canonicalization, which discards the subpath before the diff or AI ever see it, so the signal is read from the raw.d.tstext.New
resolvableSpecifiersconfig option: specifier globs to exempt from the guard when a referenced subpath is a legitimate public entry point the heuristic mis-flags. An explicitacknowledgedChangesentry also clears it.Fixes #60.
#37
8558b8eThanks @jacekradko! - Expand wildcard subpath exports (e.g."./*": "./dist/runtime/*.d.mts") instead of silently skipping them.Packages like
@clerk/sharedexpose most of their public surface through a single wildcard subpath. break-check was dropping every wildcard key infindEntryPointsand only logging it at verbose level, so breaking changes under@clerk/shared/file,@clerk/shared/url, etc. never showed up in reports.The discovery layer now globs the wildcard's value against the package directory, derives the captured portion of each match, and substitutes it back into the key pattern to synthesize one concrete
PackageEntryper file (single-segment*only; multi-segment nested wildcards remain unhandled and skip silently). Expanded entries are sorted by subpath so the resultingbreak-check.snapshot.jsonis byte-stable across runners (fs.globSyncordering is not guaranteed). Concrete keys still win over wildcard-expanded ones if both produce the same subpath. Both the wildcard key itself and individual expanded subpaths can still be excluded viaignoreSubpaths.Fixes #26.
Patch Changes
#35
01ed12dThanks @jacekradko! - Action: anchor the baseline on the PR'sbase.sha, notbase_ref.The composite Action defaulted
base-refto${{ github.base_ref }}(a branch name) and then rangit worktree add ... "origin/$BASE_REF". That checks out the current tip of the base branch at the moment the workflow runs, not the commit the PR was actually opened against. Whenmainadvanced between the PR being opened and the check running, break-check diffed against a tree the PR author never saw, producing inverted or fabricated change reports.The default is now
${{ github.event.pull_request.base.sha || github.base_ref }}and the fetch/worktree step checks outFETCH_HEADso it works for both SHAs and branch names. The dogfood workflow (.github/workflows/api-check.yml) gets the same treatment.Fixes #32.
#43
aa433aeThanks @jacekradko! - Action: pin the "current" side of the diff to the PR head SHA, not therefs/pull/N/mergeref.The composite Action (and the dogfood workflow) built whatever the caller checked out as the "current" side. On
pull_requesteventsactions/checkoutresolvesrefs/pull/N/mergeby default: the PR head merged into the moving tip of the base branch. Once the base branch advanced, that merged tree absorbed unrelated changes and break-check reported them as the PR's own, e.g. a phantomconfigureSSOMobileNavbaraddition on a CI-only PR (#32). Anchoring the baseline onbase.shawas necessary but not sufficient; the current side floated too.The Action now takes a
head-refinput (default${{ github.event.pull_request.head.sha }}), builds it in an isolated worktree symmetric with the baseline, and runs detect there. Non-PR events fall back to building the workspace..github/workflows/api-check.ymlgets the same treatment.Completes the fix for #32.
#30
763ad1bThanks @jacekradko! - Keep PR comments under GitHub's 65 KB limit, and reject bogusadditionverdicts from the AI reviewer.
and wraps them in a
<details>block (snippetMaxLines, default 60).instead of repeating the full type body twice; the diff block already
carries the detail.
additionverdict tonon-breakingwhen therule-based pass flagged an in-place modification.
additionis reservedfor brand-new exports.
#58
a0e406bThanks @jacekradko! - Bump@anthropic-ai/sdkfrom 0.97.1 to 0.100.1. The intervening releases addclaude-opus-4-8, mid-conversation system blocks,usage.output_tokens_details, and a few streaming fixes. break-check only touches theAnthropicconstructor andmessages.create, whose signatures are unchanged, so the AI reviewer's behavior is unaffected.#55
59f1c4fThanks @jacekradko! - Bump commander from 14 to 15. v15 is ESM-only and requires Node >=22.12; break-check is already ESM and pins Node >=22.13, so neither constraint tightens for consumers. The only behavioral change that touches our CLI is v15's--no-*handling, and it only affects options that define both a positive and negative form.--no-aiis a lone negative option, so it still defaults totrueand theoptions.ai === falsecheck is unchanged.#54
6d15131Thanks @jacekradko! - Stop publishing source maps. The build no longer emits.js.mapor.d.ts.mapfiles; they previously shipped in the package but pointed atsrc/, which is not included in the tarball, so they were dangling. The published package now contains only.jsand.d.ts.#70
fe548ecThanks @jacekradko! - Detect rest-parameter changes. API Extractor's.api.jsondoes not emit anisRestflag, so the callable diff never saw rest-ness: turningx: T[]into...x: T[](a breaking change) went unreported, and adding a...restparameter was misclassified as a new required parameter.
isRestis nowrecovered from the parameter excerpt, so rest-ness flips are flagged breaking
and adding a rest parameter reads as a non-breaking optional add.
#45
a4db93aThanks @jacekradko! - Normalize equivalent import-reference notation in the static differ.API Extractor resolves a namespace-import alias (
_ns.Foo) and an inline import type (import("pkg").Foo) to the same canonical reference, but emits whichever spelling the package's.d.tsbuild produced. The differ compared the raw token text, so a baseline and head built with different declaration strategies surfaced every imported type as a spurious breaking change. We now rewrite each resolvedReferencetoken to a singleimport("pkg").Namespelling (dropping the redundant inline-import prefix) before diffing, so this class of false positive is caught in the static layer instead of relying on the AI reviewer.Fixes #44.
#5
dcabe04Thanks @jacekradko! - Add MIT LICENSE file and wire up the changesets release pipeline.#8
d6b71beThanks @jacekradko! - Stop API Extractor from writing a stray<package>.api.mdfile at the project root duringbreak-check snapshot. The temp report folder now matches the configured report folder, so every generated file lives under the snapshot output directory.#64
02d5167Thanks @jacekradko! - Three hardening fixes from the pre-open-source sweep.types/exportspath that resolves outside the package root, instead of pulling an out-of-package.d.tsinto the snapshot, report, and AI payload. A package.json is attacker-controlled when the Action builds a PR, so this closes a path-traversal read (issue #7).policy-modeinput. With it on, the Action enforcesbreak-check.config.jsonfrom the base ref, so a PR can no longer suppress its own breaking change by editing its config (dropping the package, self-acknowledging, widening the ignore lists). Recommended when the Action is a required merge gate (issue #1).break-check --versionnow reports the installed version instead of a hardcoded0.0.1.#3
f86aaa9Thanks @jacekradko! - Harden production usage by failing invalid snapshots, fixing config-relative baseline resolution, preserving snapshot metadata, and adding regression checks.#29
87362c1Thanks @jacekradko! - Markdown report now labels the rule-based description as Static analyzer: and re-labels the AI block by source (AI review (reclassified as ...),(confirmed), or(additional finding)) when the AI reviewer ran. Resolves the apparent contradiction when an AI verdict overrides the static analyzer (e.g. a "Breaking change in..." line rendered under a non-breaking heading).#29
87362c1Thanks @jacekradko! - Markdown report no longer rendersVersion: X → Xwhen the PR hasn't bumped the version yet. Instead it showsCurrent version: Xand projects the target on the recommended-bump line, e.g.Recommended bump: MINOR → 4.14.0. When the PR does bump, the existingVersion: X → Yform is preserved.#48
952a4bbThanks @jacekradko! - Reject baseline metadata entries whoseapiJsonFile/apiReportFileare notplain, contained filenames.
detectpreviouslypath.joined these recordednames onto the package directory without validation, so a tampered or committed
break-check.snapshot.jsoncould traverse out (e.g.../../) and have anarbitrary file read into the diff or the AI surface payload. Such entries are
now dropped. Also declares
publishConfig(access: public,provenance: true)so npm publishing is explicit rather than relying on implicit defaults.
#62
61b1f0dThanks @jacekradko! - Close fail-open and secret-exposure gaps in the Action and CI workflows.The Action's
has-breaking-changesoutput is now derived from a JSON detect pass that fails closed: a swallowed non-zero exit or an unparseable report no longer defaults the flag to false and letsfail-on-breakingpass on a real break. The baseline-artifact lookup is bound to the PR's exact base SHA (workflow_run.head_sha) instead of the base branch name, so it cannot diff against a newer snapshot than the PR was opened against. And the nightly AI smoke workflow only exposes the Anthropic key onmain, so a write-capable actor cannot dispatch a modified branch to read it.#62
61b1f0dThanks @jacekradko! - Fix three cases where detection could miss a breaking change or pass a scan it never actually ran.When every entry in the current build failed extraction,
detectreturned an empty result before recording the skips, so--fail-on-skippedsaw nothing and the run reported "no changes" for a surface it never read. It now records the skipped entries (and fails when asked to). The rule-based diff keyed nested members by their immediate parent only, soA.Inner.valueandB.Inner.valuecollided and one silently overwrote the other; the key now carries the full parent chain. And a reference to a dependency whose package root is export-blocked withexports: { ".": null }is no longer assumed resolvable (a top-levelexports: nullstill falls back to legacy resolution, so it is left inconclusive rather than flagged).#4
92524c8Thanks @dependabot! - Pin transitive ajv, lodash, and minimatch to versions that address recent advisories.#62
61b1f0dThanks @jacekradko! - Harden the markdown report and the AI audit against untrusted input.Package names, symbol names, descriptions, and AI rationales are now escaped before they enter the report (the Action posts it verbatim as a PR comment), so a crafted public API name can no longer forge a heading, table row, or link. A single very long declaration line is capped so it can't push the comment past GitHub's size limit, and the missed-breaks audit caps the API surface it sends rather than serializing an unbounded prompt. When that audit fails on an additions-only diff, or runs against a surface trimmed to fit the cap, the report now flags the partial coverage instead of claiming a complete review.
#31
2479ffcThanks @jacekradko! - Markdown reporter now renders before/after snippets as a unified diff anchoredon the aligned common prefix and suffix, with a few lines of context and an
elision marker for the unchanged bulk. Previously, large mostly-identical
snippets were truncated head+tail on each side independently, which buried
the actual change in the elided middle and produced ~120 lines of duplicate
content for a 1-line edit. When the two sides share no structure, the
reporter still falls back to per-side head+tail truncation.