Releases: DrBaher/compare-cli
compare-cli-mcp v0.1.4
Fixed
- Shorten
server.jsondescriptionto ≤100 chars (MCP Registry validation
limit) so the registry publish succeeds. 0.1.3 published to npm but failed the
registry step on length; no runtime change.
compare-cli-mcp v0.1.3
Added
- Listed on the official MCP Registry. Added
server.json+ themcpName
field (io.github.DrBaher/compare-cli-mcp) and a registry-publish step (GitHub
OIDC) to themcp-v*release workflow, so agent runtimes can discover the
compare/drift MCP server and it stays version-current. No runtime/API changes.
v0.4.2
Security/robustness fixes from a follow-up source audit.
Fixed
- Terminal-injection hardening. C0 control characters (except
\n/\t) are stripped
from counterparty-controlled strings in the human formatter (clause titles/bodies,
intra-diff text, and docx track-change author names) to prevent ANSI/terminal injection
on a TTY.--json/SARIF output is unaffected. --catalog/--completionfast-paths now resolve even with--require-signoffsset
(they no longer trip the negotiation guard).- Structured error envelopes preserved. The
--jsoninput-error envelope is
pretty-printed and carriesexit_class:"error"; an--outputwrite failure in
--json/--sarifmode emits a structured error envelope instead of plain text.
compare-cli-mcp v0.1.2
Robustness fixes from a follow-up source audit.
Fixed
- Error mapping. A missing negotiation file now maps to
INPUT_NOT_FOUND(was the
catch-allINPUT_MALFORMED); malformed JSON surfaces the canonical "malformed JSON in …"
message rather than a rawSyntaxError. - Argument validation.
only_clauses/ignore_clausesare validated as arrays and
throwINVALID_ARGSinstead of crashing toINTERNAL_ERRORon a bare value. - Temp-dir cleanup of
content_jsonis always performed viatry/finally. - Reported tier consistency.
negotiation_resolutionis derived by replaying
readNegotiation's exact tier selection, so the reported tier cannot disagree with the
one actually used. MCP_VERSIONcorrected (had drifted to0.1.0while the package was0.1.1).
v0.4.1
Fixed
--catalog jsonmislabeled--strictsemantics. The agent-facing
discovery catalog described--strictas upgrading "cosmetic/typographic
drift to substantive", but--strictonly upgrades typographic drift;
cosmetic drift requires the separate--strict-cosmetic. The catalog help
string now reads "Upgrade typographic drift to substantive (exit 2)." to
matchHELP_TEXT,computeExitClass, andCOMPARE_SCHEMA.md§7.1. Since
the catalog is the machine-readable contract agents read, this corrects a
contract-level inaccuracy. (--strict-cosmetic's catalog entry was already
correct.)
v0.4.0
Added
compare --catalog json— the suite-wide discovery contract
({name, bin, version, description, flags, exitCodes}), so an agent learns
every flag and the exit-code spectrum at startup instead of hardcoding them.- Friendly first-run hint on a bare
compareinvocation (was a terse error);
AGENTS.md aligned to the suite's section headings; README/docs cross-links.
v0.3.0
Minor: surface WordprocessingML track-changes metadata from .docx inputs.
Informational only — TC presence does NOT change the exit-code
classification (text-diff remains the source of truth in v0.3.x). A
future version may use TC as ground truth where both sides have it.
Added
extractDocxTrackChanges(buf)— new exported function that parses
<w:ins>and<w:del>elements fromword/document.xml. Returns a
flat list of{ op: "ins" | "del", text, author, date }in document
order. Robust to malformed input (non-zip / missing document.xml → empty
array, no throw).readInputon.docxpopulatestrack_changeson the returned
side object. Non-docx inputs do not have this field (consumers should
treat missing as[]).--jsonoutput includesbase.track_changesand
candidate.track_changesas stable arrays. Always present on the
base/candidate side object — empty[]when the input isn't.docxor
has no TC. Each entry has shape{ op, text, author, date }.- Human report surfaces TC when either side has it: counts of
insertions / deletions and unique authors, as an addendum after the
per-clause differences block. Skipped when neither side has TC. --whysurfaces TC counts aswhy: track_changes.base=N track_changes.candidate=Mwhen at least one side has TC. Omitted when
both are zero, same posture as the clause-filter line.- SARIF
runs[].invocations[].propertiesincludestrack_changes_base
andtrack_changes_candidatecounts. CI dashboards can flag the
presence of pre-existing TC on either side without re-parsing.
Tests
191 → 206 (added 15). New file tests/test_track_changes.mjs covers the
unit parser, readInput integration, --json surface, human report,
--why line, and SARIF properties. tests/_helpers.mjs's makeDocx
now supports inline TC ops in run arrays ({type: "ins"|"del", text, author, date}).
Out of scope for 0.3.0
- TC as ground truth. If a substantive text-diff result conflicts
with what TC says, the current behavior reports the text-diff result.
A future version (v0.4.0?) may invert this: if<w:ins>/<w:del>
metadata exists, treat the per-op author/date as the authoritative
record of the change and use TC content to populate the diff payload
instead of re-deriving. - Clause attribution. TC ops are returned as a flat list; the agent
/ human can correlate to clauses by matching the surrounding text. A
future version may addclause_indexto each op. - TC outside body paragraphs (header / footer / footnotes / tables).
v0.3.0 only readsword/document.xml; the other parts are silently
skipped.
compare-cli-mcp v0.1.1
Patch: widen compare-cli peer-dependency range from ^0.2.0 to
>=0.2.0 <1.0.0. Silences the EPEERINVALID warning that npm prints
when installing alongside compare-cli@0.3.0+.
Changed
peerDependencies.compare-cli— was^0.2.0, now>=0.2.0 <1.0.0.
The structured--jsonshape compare-cli emits is locked across v1.x
per its AGENTS.md, so any 0.x ≥ 0.2.0 satisfies what this server
consumes. The<1.0.0upper bound reserves the right to require a
re-validation when compare-cli ships a 1.0 (which may include
intentional shape changes).
No code change. No protocol change. Existing tools/list golden
snapshot is unchanged.
v0.2.1
Patch: small polish on the v0.2.0 features (--why now surfaces filter
state; SARIF emits valid Windows-path URIs) plus a CI/infra workflow for
GitHub Releases auto-generation. No behavior change to existing inputs;
two narrow follow-ups + one new workflow.
Added
- GitHub Releases workflow. New
.github/workflows/release.ymlfires on
everyv*tag push and creates a GitHub Release object whose body is
the matching## <version>section verbatim fromCHANGELOG.md. Runs
in parallel withpublish.yml— they're independent (a release-yml
failure doesn't block npm publish, and vice versa). Future tags get
GitHub Releases automatically; the existing v0.1.0 / v0.1.1 / v0.2.0
tags are backfilled manually viagh release createafter this lands. - README badges: npm version, CI status, license, Node engine
range. Cheap, increases discoverability.
Changed
--whyblock surfaces clause-filter state when--only-clausesor
--ignore-clausesis set, or when something was actually suppressed:
why: filter.only_clauses=term|payment filter.ignore_clauses=- filter.suppressed=3.
Omitted when no filters set and nothing suppressed, so it doesn't add
noise to runs that don't use the feature.- SARIF
pathToFileUrihandles Windows absolute paths. Was missing
this case in v0.2.0 —C:\Users\alice\foo.docxnow becomes
file:///C:/Users/alice/foo.docxper the file-URI scheme. Relative
paths still pass through unchanged (SARIF v2.1.0 allows). The function
is now exported for direct testing.
Repo infrastructure (one-time, not in the PR diff)
- Repo description set to the one-paragraph elevator pitch from
README.md + suite link. Set viagh api -X PATCH(a settings change,
not a PR change). - Branch protection enabled on
main— required status checks are
the six existing CI jobs (test (ubuntu × node 20/22),
test (macos × node 20/22),coverage,smoke). PRs cannot merge
until all six pass. Admin override remains available
(enforce_admins=false) for emergency hotfixes. Force-pushes and
branch deletion both blocked.
Tests
186 → 191 (added 5: three --why filter-info cases, two SARIF
Windows-path cases).
v0.2.0
Minor: six new flags / output behaviors, no breaking changes. Drives
compare-cli toward two new workflows: unattended CI gating (via
--sarif, --check, and clause filters) and safer negotiation-driven
comparison (via --require-signoffs).
Added
- Intra-clause word-level diff in human output. Substantive changes
inside a clause body now render inline as[-removed-]{+added+}(or
red/green color in a TTY) instead of two separate- base / + candidate
lines. Falls back to the original two-line format when (a) the combined
base+candidate exceeds 600 chars or (b) more than ~70% of the body
changed (intra-diff becomes unreadable).--no-intra-diffopts out
globally. JSON / SARIF output unchanged — they carry structuredbase
andcandidatestrings already, so consumers can render their own diff. --require-signoffs(use with--from-negotiation). Requires
bothsignoffs.aandsignoffs.bto be non-empty strings in the
negotiation.jsonstate file (per
nda-review-cli's state-file schema).
Errors with exit 2 if either is missing, listing which party is
outstanding. Closes a safety gap: previously compare-cli would read
agreed text even from an unsigned-off file. Default behavior unchanged
(opt-in flag).--only-clauses PATTERNSand--ignore-clauses PATTERNS.
Comma-separated case-insensitive substring patterns matched against
numbering-stripped clause titles (normalizeTitle). Filters apply
before exit-code classification — if you--ignore-clauses Notices
and the only substantive change was in Notices, the run exits 0.
Suppressed-difference count surfaces in the human report and as
summary.suppressed_by_filterin JSON/SARIF so the filtering is
auditable. The two flags compose (--ignoreruns after--only).--sarifemits SARIF v2.1.0 to stdout. Each difference is a
result with class-mapped severity:substantive→errorcosmetic/typographic→warningadded/removed/moved→note
Designed forgithub/codeql-action/upload-sarif@v3— substantive
drift surfaces as inline annotations on the candidate file in the PR
review UI. Mutually exclusive with--json.
--check— suppresses both stdout and stderr; exit code is the
only output. Implies--silent.--outputis skipped under--check.
Convention match:prettier --check,tsc --noEmit.
Changed
readNegotiation(path)now accepts an optional{ requireSignoffs }
flag. Default behavior unchanged. Existing callers / synthetic
schemas keep working.- The
--whyblock and warnings are now suppressed under--sarif
the same way they are under--json(structured output should be
the only thing on stdout / stderr for a structured-format run).
Tests
154 → 186 (added 32 new tests). One new file tests/test_additions_v020.mjs
covers all five new flags + the four new exported helpers (wordDiff,
wordDiffChangeDensity, parseClausePatterns, clauseTitleMatches,
applyClauseFilters, buildReportSarif).
Out of scope for 0.2.0
- MCP server for compare-cli was proposed alongside these additions
but deferred to its own design pass (docs/mcp.md). Adds a runtime
dep (@modelcontextprotocol/sdk); packaging trade-off (separate
compare-cli-mcppackage vs. bundle) needs explicit decision before
implementation.