Skip to content

Releases: DrBaher/compare-cli

compare-cli-mcp v0.1.4

07 Jun 08:49

Choose a tag to compare

Fixed

  • Shorten server.json description to ≤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

07 Jun 08:45

Choose a tag to compare

Added

  • Listed on the official MCP Registry. Added server.json + the mcpName
    field (io.github.DrBaher/compare-cli-mcp) and a registry-publish step (GitHub
    OIDC) to the mcp-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

03 Jun 16:15

Choose a tag to compare

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/--completion fast-paths now resolve even with --require-signoffs set
    (they no longer trip the negotiation guard).
  • Structured error envelopes preserved. The --json input-error envelope is
    pretty-printed and carries exit_class:"error"; an --output write failure in
    --json/--sarif mode emits a structured error envelope instead of plain text.

compare-cli-mcp v0.1.2

03 Jun 16:15

Choose a tag to compare

Robustness fixes from a follow-up source audit.

Fixed

  • Error mapping. A missing negotiation file now maps to INPUT_NOT_FOUND (was the
    catch-all INPUT_MALFORMED); malformed JSON surfaces the canonical "malformed JSON in …"
    message rather than a raw SyntaxError.
  • Argument validation. only_clauses/ignore_clauses are validated as arrays and
    throw INVALID_ARGS instead of crashing to INTERNAL_ERROR on a bare value.
  • Temp-dir cleanup of content_json is always performed via try/finally.
  • Reported tier consistency. negotiation_resolution is derived by replaying
    readNegotiation's exact tier selection, so the reported tier cannot disagree with the
    one actually used.
  • MCP_VERSION corrected (had drifted to 0.1.0 while the package was 0.1.1).

v0.4.1

31 May 17:13

Choose a tag to compare

Fixed

  • --catalog json mislabeled --strict semantics. The agent-facing
    discovery catalog described --strict as upgrading "cosmetic/typographic
    drift to substantive", but --strict only upgrades typographic drift;
    cosmetic drift requires the separate --strict-cosmetic. The catalog help
    string now reads "Upgrade typographic drift to substantive (exit 2)." to
    match HELP_TEXT, computeExitClass, and COMPARE_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

23 May 08:04

Choose a tag to compare

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 compare invocation (was a terse error);
    AGENTS.md aligned to the suite's section headings; README/docs cross-links.

v0.3.0

18 May 16:32
fbee8aa

Choose a tag to compare

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 from word/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).
  • readInput on .docx populates track_changes on the returned
    side object. Non-docx inputs do not have this field (consumers should
    treat missing as []).
  • --json output includes base.track_changes and
    candidate.track_changes
    as stable arrays. Always present on the
    base/candidate side object — empty [] when the input isn't .docx or
    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.
  • --why surfaces TC counts as why: track_changes.base=N track_changes.candidate=M when at least one side has TC. Omitted when
    both are zero, same posture as the clause-filter line.
  • SARIF runs[].invocations[].properties includes track_changes_base
    and track_changes_candidate
    counts. 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 add clause_index to each op.
  • TC outside body paragraphs (header / footer / footnotes / tables).
    v0.3.0 only reads word/document.xml; the other parts are silently
    skipped.

compare-cli-mcp v0.1.1

18 May 16:32
fbee8aa

Choose a tag to compare

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 --json shape 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.0 upper 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

17 May 18:17
a3f8212

Choose a tag to compare

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.yml fires on
    every v* tag push and creates a GitHub Release object whose body is
    the matching ## <version> section verbatim from CHANGELOG.md. Runs
    in parallel with publish.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 via gh release create after this lands.
  • README badges: npm version, CI status, license, Node engine
    range. Cheap, increases discoverability.

Changed

  • --why block surfaces clause-filter state when --only-clauses or
    --ignore-clauses is 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 pathToFileUri handles Windows absolute paths. Was missing
    this case in v0.2.0 — C:\Users\alice\foo.docx now becomes
    file:///C:/Users/alice/foo.docx per 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 via gh 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

17 May 18:15
a358486

Choose a tag to compare

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-diff opts out
    globally. JSON / SARIF output unchanged — they carry structured base
    and candidate strings already, so consumers can render their own diff.
  • --require-signoffs (use with --from-negotiation). Requires
    both signoffs.a and signoffs.b to be non-empty strings in the
    negotiation.json state 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 PATTERNS and --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_filter in JSON/SARIF so the filtering is
    auditable. The two flags compose (--ignore runs after --only).
  • --sarif emits SARIF v2.1.0 to stdout. Each difference is a
    result with class-mapped severity:
    • substantiveerror
    • cosmetic / typographicwarning
    • added / removed / movednote
      Designed for github/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. --output is 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 --why block 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-mcp package vs. bundle) needs explicit decision before
    implementation.