Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
name: Bug report
about: A reproducible defect in the CLI or its output
title: "bug: "
labels: bug
---

## What happened

<!-- One sentence. What did the tool do that was wrong? -->

## What you expected

<!-- One sentence. What should it have done instead? -->

## Reproduction

<!-- Smallest possible inputs that surface the bug. Include actual files
where possible (paste content or attach). For binary inputs, base64 a
small sample. -->

```sh
compare path/to/base.docx path/to/cand.pdf --json --why
```

```text
<paste the output, both stdout and stderr>
```

## Environment

- compare-cli version: <!-- compare --version -->
- Node version: <!-- node --version -->
- OS: <!-- macOS / Ubuntu / etc. -->
- Install method: <!-- npm install -g | npx | other -->

## Exit code

<!-- What exit code did you get? What did you expect? -->

## Additional context

<!-- Anything else relevant. If you have a `--why` block, paste it. -->
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/DrBaher/compare-cli/security/advisories/new
about: Report security issues privately via GitHub's vulnerability reporting (see SECURITY.md).
- name: Suite-level discussion
url: https://cli.drbaher.com
about: The contract-operations CLI suite that compare-cli is part of.
43 changes: 43 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
name: Feature request
about: A new flag, output mode, or behavior change
title: "feat: "
labels: enhancement
---

## The use case

<!-- One paragraph. What workflow does this enable? Who needs it? -->

## Proposed shape

<!-- How would you invoke it? What's the flag name, the input, the
output? Example commands or JSON payloads are gold. -->

```sh
compare base.docx cand.docx --new-flag ARGS
```

## Why compare-cli specifically

<!-- This tool's contract is *deterministic, clause-aware drift between
two contract versions*. Features that drift from that contract (LLM tier,
batch mode, image comparison, hash-chain validation) are deliberately
out of scope. If your idea is in tension with the contract, say why it
should still land. See CHANGELOG.md "Deferred candidates" for items
already considered. -->

## Trade-offs

<!-- Anything this would break, slow down, or complicate? Any new
runtime dependencies needed? (The CLI ships with exactly two: jszip and
pdfjs-dist. Adding a third is a real decision.) -->

## Related

<!-- Other tools in the suite that might already cover this:
- draft-cli (template filling, parties.json)
- nda-review-cli (negotiation state, redlines, hash chains)
- sign-cli (PAdES signatures, RFC 3161)
- template-vault-CLI (clause vaulting, swap/upgrade)
- docx2pdf-cli (DOCX → PDF) -->
57 changes: 57 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
version: 2
updates:
# Root compare-cli package — two runtime deps (jszip, pdfjs-dist), no devDeps.
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
timezone: "UTC"
commit-message:
prefix: deps
labels:
- dependencies
# Group patch + minor bumps so we get one PR per week instead of one per dep.
# Majors stay separate — pdfjs-dist majors in particular need a CI matrix
# check (the Node-engine pin is downstream).
groups:
runtime:
patterns:
- "*"
update-types:
- patch
- minor

# MCP workspace — runtime dep @modelcontextprotocol/sdk + peer dep compare-cli.
# Peer deps are not auto-bumped by dependabot; the runtime dep is.
- package-ecosystem: npm
directory: /mcp
schedule:
interval: weekly
day: monday
time: "06:00"
timezone: "UTC"
commit-message:
prefix: "deps(mcp)"
labels:
- dependencies
- mcp
groups:
mcp-runtime:
patterns:
- "*"
update-types:
- patch
- minor

# GitHub Actions versions (uses: actions/...@vX).
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
commit-message:
prefix: "ci(actions)"
labels:
- dependencies
- ci
56 changes: 56 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<!--
Thanks for opening a PR. Keep this template's headings; agents and
reviewers both rely on the consistent shape. Delete the comment blocks
when you fill in your content.
-->

## Summary

<!-- 1–3 sentences. What does this PR do? Why? -->

## What changes

<!-- Bulleted list of user-visible / behavior-visible changes. Reference
files where useful (`compare-cli.mjs:123`, `COMPARE_SCHEMA.md §9.2`). -->

-

## Why this design

<!-- For non-trivial changes: what alternatives were considered? Why
not the obvious-other-option? Especially important when the change
touches the locked contract surfaces (exit codes, --json shape,
clause-detection rule). -->

## Test plan

- [ ] `npm test` passes locally
- [ ] `cd mcp && npm test` passes locally (if `mcp/` touched)
- [ ] Manual smoke: <!-- describe -->
- [ ] CI matrix (Ubuntu × macOS × Node 20/22) green

## Out of scope

<!-- Anything you noticed but deliberately didn't change. Useful for
reviewers so they don't ask "why didn't you also fix X?" -->

## Schema impact

<!-- If this changes the --json shape, AGENTS.md / COMPARE_SCHEMA.md
updates are required. Mark which ones. -->

- [ ] No `--json` shape change
- [ ] AGENTS.md updated
- [ ] COMPARE_SCHEMA.md updated
- [ ] CHANGELOG.md entry added

## Version impact

<!-- Patch / minor / major / no bump. Per the project's posture, the
JSON shape and exit codes are stable across v1.x — changes there force
a major bump (which we won't ship until the suite settles). -->

- [ ] No bump (infra / docs only)
- [ ] Patch
- [ ] Minor
- [ ] Major (locked-surface change)
44 changes: 44 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,50 @@ Useful when the agreement is "byte-perfect after normalization or do
nothing" — e.g. financial term sheets where `$1,000` vs `$1000` is in
fact meaningful.

## Invoking via MCP

For agent pipelines that prefer structured tool-calls over shelling out,
`compare-cli-mcp` (separate npm package, lives in `mcp/`) wraps the CLI
as an MCP (Model Context Protocol) server. Three tools, stdio transport,
JSON-first responses.

```sh
npm install -g compare-cli@^0.3.0 compare-cli-mcp@^0.1.1
compare-mcp # spawns the server on stdio
```

Wire into Claude Desktop / Claude Code:

```json
{
"mcpServers": {
"compare-cli": {
"command": "compare-mcp",
"env": { "COMPARE_MCP_BASE_DIR": "/path/to/contract/documents" }
}
}
}
```

Tool catalog:

| MCP tool | CLI equivalent |
|---------------------------|------------------------------------------------------|
| `compare_files` | `compare BASE CANDIDATE [options]` |
| `compare_with_negotiation`| `compare --from-negotiation NEG.json CANDIDATE [...]`|
| `compare_demo` | `compare --demo` |

`structuredContent` returned by every successful tool call is **byte-
identical** to the `compare --json` shape documented above; agents can
read it without per-transport special-casing. Substantive drift is a
successful tool call (not an MCP error) — same routing logic as the
shell pattern above. Genuine errors (I/O failure, malformed input, no
agreed round) surface as MCP errors with stable codes (`INPUT_NOT_FOUND`,
`PDF_NO_TEXT_LAYER`, `NO_AGREED_ROUND`, etc.).

Full spec: [`docs/mcp.md`](./docs/mcp.md) (design) and
[`mcp/README.md`](./mcp/README.md) (usage / error catalog).

## Failure diagnosis

| Symptom | Likely cause | Recovery |
Expand Down
72 changes: 72 additions & 0 deletions GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,81 @@ sign draft.pdf --signer counsel@acme.com
Each tool reads stdin / writes stdout / exits with a documented code, so
they compose cleanly.

## Troubleshooting

### `npx compare-cli ... --demo` errors with `sh: compare: command not found`

The package is `compare-cli`; the installed bin is `compare`. npm 10.x's
`npx` doesn't auto-resolve a bin when the names differ. Use the explicit
form:

```sh
npx -p compare-cli@latest -- compare --demo
```

Or install globally (`npm install -g compare-cli`) and then `compare` is
on `$PATH` directly. Same behavior, less typing.

### `extracted zero characters from X.pdf`

The PDF has no text layer — it's a scanned image. compare-cli is
deliberately OCR-free (deterministic + zero-network is the contract;
OCR engines are neither). Run an OCR tool first:

```sh
ocrmypdf scanned.pdf scanned-ocr.pdf
compare base.docx scanned-ocr.pdf
```

`ocrmypdf` is a separate project; install it via your package manager.

### Exit code 2 from `--demo`, surprised by `--check` exiting non-zero

`compare --demo` runs against a deliberately-substantive-drift fixture
(the bundled Term clause changed from "two (2) years" to "three (3)
years"). Exit 2 is the contract — the demo demonstrates the gate, not
clean state. Use `compare --version` or `compare --help` if you just
want to confirm the bin runs.

### `compare-cli-mcp` install: `EPEERINVALID compare-cli@…`

`compare-cli-mcp@0.1.0` declared `peerDependencies.compare-cli: ^0.2.0`
which doesn't satisfy `compare-cli@0.3.0+`. The warning is cosmetic —
the server functions correctly because the `--json` shape is stable
across compare-cli's v1.x. Upgrading to `compare-cli-mcp@0.1.1+`
widens the peer-dep range and silences the warning.

### `--from-negotiation: no agreed round found`

The reader walks every round in `negotiation.json` looking for one of
three signals (in order):

1. Top-level `status: "converged" | "signed_off" | "finalized"`.
2. A round with `agreed: true`.
3. A round with `clause_status` whose every value is `"agreed"`.

If none of those is true, the negotiation hasn't converged yet — call
this from compare-cli prematurely and you'll get exit 2 with this
message. Run `nda-review-cli negotiate status` to confirm.

### CI shows a green `compare` step but my `npm publish` blocks

If you're using compare-cli inside a publish workflow as a pre-flight
sanity check, remember the exit codes:

- `0` = safe, publish.
- `2` = substantive drift — usually the right thing to **block** on.
- `3` / `4` = cosmetic / moved — usually safe to publish (the agreement
didn't change), but if you want a strict gate, add `--strict` and
`--strict-cosmetic`.

The default CI pattern from `AGENTS.md` "Pre-signature gate in a
pipeline" routes these correctly.

## Next steps

- **[COMPARE_SCHEMA.md](./COMPARE_SCHEMA.md)** for the locked v1 contract.
- **[AGENTS.md](./AGENTS.md)** for the stable agent-facing surface.
- **[ARCHITECTURE.md](./ARCHITECTURE.md)** for how the CLI is shaped.
- **[FAQ.md](./FAQ.md)** for common questions.
- **[mcp/README.md](./mcp/README.md)** if you're wiring it into an MCP client.
Loading