svn-agent-mcp 1.2.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/README.md +160 -29
  3. package/SECURITY.md +36 -2
  4. package/THIRD_PARTY_CHECKSUMS.txt +2 -2
  5. package/THIRD_PARTY_NOTICES.md +4 -0
  6. package/bin/svn.exe +0 -0
  7. package/dist/commitScope.d.ts +21 -0
  8. package/dist/commitScope.d.ts.map +1 -0
  9. package/dist/commitScope.js +79 -0
  10. package/dist/commitScope.js.map +1 -0
  11. package/dist/eol.d.ts +29 -0
  12. package/dist/eol.d.ts.map +1 -1
  13. package/dist/eol.js +254 -7
  14. package/dist/eol.js.map +1 -1
  15. package/dist/evidenceStore.d.ts +32 -0
  16. package/dist/evidenceStore.d.ts.map +1 -0
  17. package/dist/evidenceStore.js +131 -0
  18. package/dist/evidenceStore.js.map +1 -0
  19. package/dist/fileHash.d.ts +13 -0
  20. package/dist/fileHash.d.ts.map +1 -0
  21. package/dist/fileHash.js +67 -0
  22. package/dist/fileHash.js.map +1 -0
  23. package/dist/guards.d.ts +18 -0
  24. package/dist/guards.d.ts.map +1 -1
  25. package/dist/guards.js +80 -8
  26. package/dist/guards.js.map +1 -1
  27. package/dist/index.d.ts +26 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +432 -46
  30. package/dist/index.js.map +1 -1
  31. package/dist/operationStore.d.ts +74 -0
  32. package/dist/operationStore.d.ts.map +1 -0
  33. package/dist/operationStore.js +705 -0
  34. package/dist/operationStore.js.map +1 -0
  35. package/dist/parse/diffText.d.ts +4 -0
  36. package/dist/parse/diffText.d.ts.map +1 -1
  37. package/dist/parse/diffText.js +78 -8
  38. package/dist/parse/diffText.js.map +1 -1
  39. package/dist/parse/infoXml.d.ts.map +1 -1
  40. package/dist/parse/infoXml.js +1 -0
  41. package/dist/parse/infoXml.js.map +1 -1
  42. package/dist/parse/updateText.d.ts.map +1 -1
  43. package/dist/parse/updateText.js +3 -8
  44. package/dist/parse/updateText.js.map +1 -1
  45. package/dist/response.d.ts +1 -1
  46. package/dist/response.d.ts.map +1 -1
  47. package/dist/response.js +980 -124
  48. package/dist/response.js.map +1 -1
  49. package/dist/runner.d.ts +5 -0
  50. package/dist/runner.d.ts.map +1 -1
  51. package/dist/runner.js +187 -50
  52. package/dist/runner.js.map +1 -1
  53. package/dist/snapshotToken.d.ts +17 -0
  54. package/dist/snapshotToken.d.ts.map +1 -0
  55. package/dist/snapshotToken.js +96 -0
  56. package/dist/snapshotToken.js.map +1 -0
  57. package/dist/tools/composite.d.ts +41 -1
  58. package/dist/tools/composite.d.ts.map +1 -1
  59. package/dist/tools/composite.js +963 -67
  60. package/dist/tools/composite.js.map +1 -1
  61. package/dist/tools/mutating.d.ts +28 -0
  62. package/dist/tools/mutating.d.ts.map +1 -1
  63. package/dist/tools/mutating.js +652 -37
  64. package/dist/tools/mutating.js.map +1 -1
  65. package/dist/tools/readonly.d.ts +32 -0
  66. package/dist/tools/readonly.d.ts.map +1 -1
  67. package/dist/tools/readonly.js +346 -22
  68. package/dist/tools/readonly.js.map +1 -1
  69. package/dist/tools/selfcheck.d.ts +14 -1
  70. package/dist/tools/selfcheck.d.ts.map +1 -1
  71. package/dist/tools/selfcheck.js +42 -4
  72. package/dist/tools/selfcheck.js.map +1 -1
  73. package/dist/types.d.ts +16 -0
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/workflowEvidence.d.ts +29 -0
  76. package/dist/workflowEvidence.d.ts.map +1 -0
  77. package/dist/workflowEvidence.js +47 -0
  78. package/dist/workflowEvidence.js.map +1 -0
  79. package/dist/workflowState.d.ts +31 -0
  80. package/dist/workflowState.d.ts.map +1 -0
  81. package/dist/workflowState.js +209 -0
  82. package/dist/workflowState.js.map +1 -0
  83. package/docs/MCP_API.json +420 -180
  84. package/docs/SPEC.md +377 -82
  85. package/package.json +3 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,163 @@ All notable changes to the SVN MCP are recorded here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.4.0] - 2026-08-02
8
+
9
+ ### Added
10
+
11
+ - Added GitHub bug-report and feature-request templates with SVN MCP-specific environment,
12
+ reproduction, safety, and sanitization fields.
13
+ - Added `receipt` and `structured-only` response modes. Receipt mode defines bounded minimal
14
+ contracts for status, snapshot, precommit, update, and commit.
15
+ - Added validated field projection for high-use tools. Allowed fields are published once in the
16
+ generated API contract rather than repeated in every live tool schema.
17
+ - Added explicit `humanText:true` opt-in for clients that need a short text content block.
18
+ - Added server-level `full`, `docs`, and `review` tool profiles through
19
+ `SVN_MCP_TOOL_PROFILE`; the focused profiles advertise only 8 or 11 tools and return a typed
20
+ refusal when a client calls a hidden tool.
21
+ - Added canonical `svn_path_change` with an explicit `move`, `rename`, or `copy` action.
22
+ - Added repository-driven `normalizeEol` handling to `svn_add`; configured text files are
23
+ transactionally normalized and verified before scheduling, while binary and policy-excluded
24
+ byte-exact files are reported as skipped.
25
+ - Added bounded multi-file `eol_fix_verified` input with aggregate counts, per-file failures, and
26
+ normalized-content SHA256 proof.
27
+ - Added actionable numeric-limit validation and a CI response/schema budget gate.
28
+ - Added process-local snapshot tokens for status/snapshot `NO_CHANGE` polling, with bounded TTL,
29
+ query and working-copy binding, tamper rejection, and replacement tokens after a change.
30
+ - Added bounded process-local diff evidence. Continuation calls reuse an opaque operation ID so
31
+ later pages are stable even when the working copy changes between requests.
32
+ - Added bounded log message filtering, per-revision changed-path summaries, update overlap/top-folder
33
+ summaries, and diff `counts`/`hunk-headings` modes with complete total and omitted-hunk metadata.
34
+ - Added `eolCheckComplete` and an EOL-policy identity to compact precommit receipts.
35
+ - Added independent 100-item conflict pages for status, snapshot, and update so complete conflict
36
+ evidence remains reachable without allowing one receipt to grow without bound.
37
+ - Added `expandDescendants:true` to precommit and commit. Explicit directories can now expand to a
38
+ fully guarded, visible changed-descendant scope while node-only behavior remains opt-in.
39
+ - Added `svn_commit operation:"prepare"`, which performs a pinned explicit-path update with conflict
40
+ postponement, optional remote-HEAD guarding, unexpected-path refusal, and a final precommit
41
+ receipt without committing. A hidden `svn_prepare_commit` route preserves explicit compatibility
42
+ without adding an advertised schema.
43
+ - Added durable UUID operation receipts for update, commit/prepare, EOL repair, and conflict
44
+ resolution. Identical retries replay compact results across MCP restarts; concurrent, mismatched,
45
+ corrupt, and ambiguous stale operations fail closed instead of repeating a mutation. Abandoned
46
+ receipt locks are reclaimed after a bounded interval while active lock contention returns a typed
47
+ failure.
48
+ - Added explicit-file pre-edit baselines through `svn_snapshot captureBaseline:true`. A later
49
+ `svn_update baselineToken` reports local edits, remote touches, postponed conflicts, and
50
+ same-path collisions without requiring a full update transcript.
51
+ - Added READY precommit tokens bound to exact status, base revisions, content and SVN property hashes, repository
52
+ policy, diff identity, scope, and remote revision. `svn_commit precommitToken` refuses if any
53
+ bound evidence changed after verification.
54
+ - Added `svn_commit operation:"safe"` as one durable guarded workflow: pinned scoped update,
55
+ collision refusal, verified EOL repair when needed, precommit binding, commit, pinned final
56
+ update, and a clean scoped snapshot. Bounded stage detail is paged later through
57
+ `operation:"detail"` instead of inflating the normal receipt.
58
+ - Safe mode omits only scheduled-added operands from its pinned update while still checking the
59
+ expected repository HEAD and retaining those files in the exact precommit and commit scope.
60
+
61
+ ### Changed
62
+
63
+ - GitHub Issues is now the canonical public tracker. The 31 completed historical SVNMCP tasks were
64
+ migrated as closed issues with 33 distinct notes, condensed completion evidence, and four
65
+ relations, without private tracker metadata.
66
+ - Reworked setup documentation around the globally installed npm command and added generic,
67
+ platform-neutral install and source-development prompts.
68
+ - Prepared releases now carry their own package manifest, and API-contract generation always uses
69
+ the full canonical tool profile regardless of the caller's environment.
70
+ - Buffered and streamed child processes now share bounded UTF-8 byte accounting, sticky
71
+ truncation, cancellation, timeout escalation, and process-tree termination.
72
+ - Compact diff shaping bounds per-file previews before redaction and serialization. Streamed diff
73
+ callbacks have independent line/byte work budgets and report when aggregate totals are lower
74
+ bounds.
75
+ - Workflow and commit hashes now use cancellable asynchronous streams, and test runs use isolated
76
+ operation-receipt stores instead of the live user store.
77
+ - Workflow hashing now uses a bounded worker pool plus a configurable aggregate-byte ceiling;
78
+ receipt-lock retries yield to the MCP event loop instead of blocking every request.
79
+ - Large verified EOL repairs now use streaming sniff/hash verification and disk-backed backups.
80
+ Rollback refuses to overwrite a file changed by another writer after normalization.
81
+ - Structured content is now authoritative by default; successful and failed calls omit duplicate
82
+ `content.text` unless explicitly requested.
83
+ - Compact, receipt, and standard responses use working-copy-relative paths; absolute paths and
84
+ raw commands remain full-diagnostic output only.
85
+ - Compact guard refusals now return a typed guard code, one actionable detail, and an affected-path
86
+ count without echoing the complete submitted path list.
87
+ - High-volume advanced inputs are validated centrally and published once in `MCP_API.json` instead
88
+ of being repeated across live tool schemas. This preserves schema-token budgets while keeping
89
+ snapshot, evidence, log-filter, and update-overlap controls available to known callers.
90
+ - Diff aggregate file, hunk, addition, removal, binary, and property counts remain complete after
91
+ detailed per-file summaries reach their 20,000-entry cap; terminal evidence truncation is explicit.
92
+ - Runner line/output truncation now propagates into stored diff evidence, and nonzero/past-end update
93
+ pages retain total, offset, and bounded top-folder context.
94
+ - Check-style responses report pass counts and failures by default; passing details require
95
+ `includePassing:true` and remain paginated.
96
+ - The full profile now advertises 25 canonical tools. Legacy `svn_move`, `svn_rename`,
97
+ `svn_copy`, and `svn_resolved` routes remain callable for existing clients but are omitted from
98
+ tool discovery to reduce schema context.
99
+ - `svn_blame` now ignores EOL-only churn by default, matching the existing `svn_diff` default;
100
+ both tools expose `showEolChanges:true` for diagnostics, and pure EOL diffs return `eolOnly:true`.
101
+ - Commit-message format validation now blocks before `svn commit` and returns a typed failed rule
102
+ plus a bounded suggested message.
103
+ - Successful commit receipts now separate exact committed paths from post-commit residue and add
104
+ bounded revision, remote-head, mixed-state, EOL-availability, and content-hash evidence.
105
+ - Baseline, precommit, collision, and safe-commit controls are published once as advanced inputs;
106
+ the full profile remains at 25 advertised tools and compact safe-commit receipts stay
107
+ structured-only by default.
108
+
109
+ ### Fixed
110
+
111
+ - Fixed prepared `current/dist/index.js` launches that could fail module/package resolution while
112
+ self-check still reported the layout healthy.
113
+ - Fixed delete commit and safe-commit receipts so removed targets no longer cause false residue or
114
+ final-verification failures.
115
+ - Fixed multi-path repository logs, exact numeric/whitespace property values, revision diffs for
116
+ literal `@` paths, observed update-HEAD receipts, added-parent guard rechecks, and lock-status
117
+ parsing.
118
+ - Bounded evidence metadata, operation-receipt reads, workflow hashing, and diff evidence summaries;
119
+ snapshot tokens now use one canonical state across compact and receipt modes.
120
+ - Durable stale commit outcomes now fail closed instead of inferring success from matching message
121
+ text, and operation-lock cleanup refuses to break locks owned by live processes.
122
+ - Fixed receipt-store contention and abandoned breaker recovery, prepared-pointer validation by
123
+ physical path, cross-mode status snapshot tokens, independent stdout/stderr overflow handling,
124
+ and explicit buffered-output truncation receipts.
125
+ - Enforced absolute `cwd` values and refused credential-bearing repository URLs at both schema and
126
+ runtime boundaries.
127
+ - Bounded compact log serialization to 24 KiB, rejected unsafe numeric cursors, removed anonymous
128
+ tree-conflict placeholders, and required `riskAck:true` for destructive revert execution.
129
+ - Applied never-commit guards to verified EOL repair and commit-message validation to `svn_import`.
130
+ - Fixed receipt continuation so a supplied cursor advances to the next changed-path page instead of
131
+ repeating page one.
132
+ - Removed remaining absolute working-copy paths from non-full warnings, detailed self-check output,
133
+ standard diagnostics, and batch EOL failure receipts.
134
+ - Embedded a Windows UTF-8 active-code-page manifest in the bundled VisualSVN `svn.exe`, preserving
135
+ Greek, accented, CJK, and spaced path arguments without a shell or machine-wide locale change.
136
+ - Added a post-large-diff client call to prove oversized SVN output cannot corrupt the next MCP
137
+ JSON-RPC frame.
138
+ - Prepare mode now checks root, directory, never-commit, and expansion scope before updating;
139
+ node-only directory preparation uses `--depth empty`, and expanded precommit risk signals are
140
+ calculated from the expanded files.
141
+ - Compact and receipt prepare failures retain up to 25 unexpected paths plus explicit total and
142
+ truncation metadata; ordinary non-expanded calls no longer emit empty expansion fields.
143
+
144
+ ## [1.3.0] - 2026-07-31
145
+
146
+ ### Added
147
+
148
+ - Added exact revision pinning and an optional `expectedRemoteHead` guard to `svn_update`, with
149
+ resulting revision/range metadata, bounded changed-path receipts, and the existing explicit-scope
150
+ and conflict-postpone safety.
151
+ - Added opt-in `requireUniformRevision:true` release gating to `svn_precommit`; ordinary precommit
152
+ calls remain backward compatible and continue to report mixed revisions without blocking.
153
+
154
+ ### Fixed
155
+
156
+ - Preserved successful SVN warnings and recovered exact existing paths beneath ignored directories
157
+ as ignored entries with their covering ancestor instead of returning an empty status for
158
+ VisualSVN/Subversion `W155010`.
159
+ - Made multi-entry `svn_log` envelopes unambiguous with `revision:null`, `revision_range`, and
160
+ `entry_count`, while retaining per-entry changed paths and single-revision behavior.
161
+ - Marked the prepared-release `current` pointer as inapplicable for direct npm-package layouts;
162
+ healthy npm self-checks now return `current_matches_package:null` without reducing health.
163
+
7
164
  ## [1.2.2] - 2026-07-28
8
165
 
9
166
  ### Fixed
package/README.md CHANGED
@@ -2,30 +2,43 @@
2
2
 
3
3
  Strict SVN Model Context Protocol server for agent-safe status, diff, EOL diagnosis, precommit checks, and guarded SVN mutations.
4
4
 
5
- The implementation contract lives in `docs/SPEC.md`. The current source release is `1.2.2`; each source clone can prepare a local runtime under `releases/v1.2.2`, while npm installations run directly from package-root `dist/`.
5
+ The implementation contract lives in `docs/SPEC.md`. The current source release is `1.4.0`; each source clone can prepare a local runtime under `releases/v1.4.0`, while npm installations run directly from package-root `dist/`.
6
6
 
7
7
  Requirements: Node.js 24.18.0 or newer within the Node 24 LTS line, npm 11.16.0 or newer, Git, and access to the public npm registry. Windows uses the
8
8
  bundled VisualSVN Apache Subversion command-line package and dos2unix payload. On macOS and Linux, `svn`, `svnversion`, `svnadmin`,
9
9
  `dos2unix`, and `unix2dos` must be available on `PATH`.
10
10
 
11
- ## Quick Start
11
+ ## Install From npm
12
12
 
13
13
  ```shell
14
- git clone https://github.com/shrishailrana-maker/svn-agent-mcp-v1.git
15
- cd svn-agent-mcp-v1
16
- npm install
17
- npm run prepare:local
18
- npm test
14
+ npm install -g svn-agent-mcp@latest
15
+ npm list -g svn-agent-mcp --depth=0
19
16
  ```
20
17
 
21
- ## Agent-Managed Global Install
18
+ Register one MCP server named `svn` and let the client resolve the globally installed command from
19
+ `PATH`:
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "svn": {
25
+ "command": "svn-agent-mcp"
26
+ }
27
+ }
28
+ }
29
+ ```
22
30
 
23
- Give this prompt to Codex, Claude, or another local coding agent:
31
+ Restart the MCP client after changing its configuration, then run `svn_self_check` once to verify
32
+ the installed version and runtime health.
33
+
34
+ ## Generic Agent Install Prompt
35
+
36
+ Give this prompt to any local coding agent:
24
37
 
25
38
  ```text
26
39
  Install or update the SVN MCP globally with: npm install -g svn-agent-mcp@latest
27
40
  Verify the package with: npm list -g svn-agent-mcp --depth=0
28
- Resolve the executable with the platform command lookup: where.exe svn-agent-mcp on Windows, or command -v svn-agent-mcp on macOS/Linux.
41
+ Resolve the executable with the host shell's command lookup: Get-Command svn-agent-mcp in PowerShell, where.exe svn-agent-mcp in Windows Command Prompt, or command -v svn-agent-mcp on POSIX shells. Do not use a lookup command from another platform.
29
42
  On macOS/Linux, verify that svn, svnversion, svnadmin, dos2unix, and unix2dos are available on PATH. If any are missing, install Subversion and dos2unix with the host package manager.
30
43
  Ensure the MCP client entry is named "svn". Use command "svn-agent-mcp" when the client can launch it without a visible window; never use a source checkout, junction, or current pointer. Do not add --readonly.
31
44
  On Windows, enable the client's hidden/no-window process option. If the npm command shim still opens a console, resolve the global module root with `npm root -g`, then use command "node" with args `["<global-module-root>\\svn-agent-mcp\\dist\\index.js"]`; the server cannot choose its parent process creation flags.
@@ -34,12 +47,13 @@ Query the registry version with: npm view svn-agent-mcp version
34
47
  After restarting, run svn_self_check and compare its installed version with the registry version. Report the installed version, executable path, runtime layout, and MCP health instead of relying on a remembered version.
35
48
  ```
36
49
 
37
- ## Agent Setup From GitHub
50
+ ## Source Setup From GitHub
38
51
 
39
- Tell an agent:
52
+ Use a source checkout for development and contribution work, not as the normal global MCP runtime.
53
+ Generic source-setup prompt:
40
54
 
41
55
  ```text
42
- Get the SVN MCP from https://github.com/shrishailrana-maker/svn-agent-mcp-v1, clone it to a stable absolute path, run npm install, run npm run prepare:local, then configure the MCP command as node <absolute-clone-path>/current/dist/index.js. Use the host platform's native path syntax.
56
+ Clone https://github.com/shrishailrana-maker/svn-agent-mcp-v1 into a stable development directory. Run npm ci --strict-allow-scripts, npm run prepare:local, and npm test. Use the globally installed svn-agent-mcp command for normal MCP client registration; use node <absolute-clone-path>/current/dist/index.js only when explicitly testing that checkout.
43
57
  ```
44
58
 
45
59
  The setup commands are:
@@ -47,8 +61,9 @@ The setup commands are:
47
61
  ```shell
48
62
  git clone https://github.com/shrishailrana-maker/svn-agent-mcp-v1.git
49
63
  cd svn-agent-mcp-v1
50
- npm install
64
+ npm ci --strict-allow-scripts
51
65
  npm run prepare:local
66
+ npm test
52
67
  ```
53
68
 
54
69
  Then configure the MCP client to run:
@@ -57,7 +72,7 @@ Then configure the MCP client to run:
57
72
  node <absolute-clone-path>/current/dist/index.js
58
73
  ```
59
74
 
60
- ### Claude Desktop Config Example
75
+ ### JSON Client Config Example
61
76
 
62
77
  Add this under `mcpServers`:
63
78
 
@@ -72,7 +87,7 @@ Add this under `mcpServers`:
72
87
  }
73
88
  ```
74
89
 
75
- ### Codex Config Example
90
+ ### TOML Client Config Example
76
91
 
77
92
  ```toml
78
93
  [mcp_servers.svn]
@@ -121,21 +136,46 @@ Generic client example:
121
136
  }
122
137
  ```
123
138
 
124
- The MCP is not tied to one SVN checkout. If a tool call supplies absolute paths and omits `cwd`, the server finds the nearest SVN working copy for those paths. Relative paths require explicit per-call `cwd`.
139
+ The MCP is not tied to one SVN checkout. If a tool call supplies absolute paths and omits `cwd`, the server finds the nearest SVN working copy for those paths. Relative paths require an explicit, absolute per-call `cwd`. Repository URL inputs must not embed usernames or passwords; use the native SVN credential cache.
125
140
 
126
141
  Client registration is static: configure the MCP once, and working-copy discovery happens per tool call. The server does not rewrite client configuration at runtime.
127
142
 
143
+ ## Issues And Feature Requests
144
+
145
+ Use [GitHub Issues](https://github.com/shrishailrana-maker/svn-agent-mcp-v1/issues) for public bugs,
146
+ feature requests, and planned work. Search existing issues before filing a new one and use the
147
+ provided templates. Include the package version, operating system, Node.js version, installation
148
+ method, and a minimal sanitized reproduction when relevant. Remove credentials, private repository
149
+ URLs, usernames, and local absolute paths from public reports.
150
+
151
+ The completed historical project backlog was migrated as issues
152
+ [#1](https://github.com/shrishailrana-maker/svn-agent-mcp-v1/issues/1) through
153
+ [#31](https://github.com/shrishailrana-maker/svn-agent-mcp-v1/issues/31). Report security
154
+ vulnerabilities through the private process in `SECURITY.md`, not a public issue.
155
+
128
156
  Environment variables are not required when the toolchain is bundled or available on `PATH`.
129
- `SVN_MCP_RESPONSE_MODE` selects `compact`
130
- (default), `standard`, or `full` responses. Compact mode returns bounded structured results and
131
- short text receipts; use `responseMode: "full"` on a call when bounded raw SVN diagnostics are needed.
132
- Errors retain bounded stdout/stderr diagnostics in every mode. Other development/test escape
133
- hatches are `SVN_AGENT_BIN_DIR`, `SVN_AGENT_SVN_PATH`, `SVN_AGENT_DOS2UNIX_DIR`,
134
- `SVN_AGENT_TIMEOUT_MS`, and `SVN_AGENT_MAX_DIFF_LINES`.
157
+ `SVN_MCP_TOOL_PROFILE` controls the advertised schema surface: `full` (default) exposes 25
158
+ canonical tools, `docs` exposes the 8-tool edit/commit workflow, and `review` adds bounded diff,
159
+ cat, and blame for 11 tools total. Focused profiles reduce tool-definition context without changing
160
+ any guard. A call to a hidden tool returns a typed `TOOL_PROFILE` refusal; use `full` when the
161
+ workflow needs another operation.
162
+ `SVN_MCP_RESPONSE_MODE` selects `compact` (default), `receipt`, `structured-only`, `standard`, or
163
+ `full` responses. `structuredContent` is authoritative and `content` is empty by default; pass
164
+ `humanText:true` when a client needs a short text receipt. `structured-only` makes that intent
165
+ explicit. `receipt` is the smallest stable contract for status, snapshot, precommit, update, and
166
+ commit. Use `responseMode:"full"` only when bounded raw SVN diagnostics and machine paths are
167
+ needed.
168
+ Non-guard failures retain bounded path-sanitized stdout/stderr diagnostics outside full mode;
169
+ compact guard refusals return only a typed guard code, one-line reason, and affected-path count.
170
+ Other development/test escape hatches are `SVN_AGENT_BIN_DIR`, `SVN_AGENT_SVN_PATH`, `SVN_AGENT_DOS2UNIX_DIR`,
171
+ `SVN_AGENT_TIMEOUT_MS`, `SVN_AGENT_MAX_DIFF_LINES`, `SVN_MCP_HASH_CONCURRENCY`, and
172
+ `SVN_MCP_MAX_HASH_BYTES`. Hashing defaults to four concurrent files and a 1 GiB aggregate explicit
173
+ scope; narrow the path scope before raising either bound.
135
174
 
136
175
  High-volume reads are bounded by default. Log messages and changed paths are capped and opt-in
137
176
  where appropriate. Diff collection defaults to 200 lines, compact excerpts are capped at 3,000
138
- characters, and compact diff results retain transport headroom below a 32 KiB JSON-RPC record.
177
+ characters, compact logs are capped at 24 KiB, and compact diff results retain transport headroom
178
+ below a 32 KiB JSON-RPC record.
139
179
  `maxChars` and `maxFiles` are upper requests: the response may return less with independent
140
180
  `nextCursor` and `nextFileCursor` values. Large file/property/status/EOL collections expose
141
181
  explicit continuation cursors.
@@ -146,12 +186,102 @@ characters.
146
186
  Compact mode changes response size only; path containment, mutation guards, EOL checks,
147
187
  mixed-revision checks, and commit verification run unchanged.
148
188
 
189
+ Use `svn_diff diffMode:"counts"` for totals only or `"hunk-headings"` for one meaningful line per
190
+ file plus omitted-hunk counts. A returned `operationId` binds later cursor pages to the same bounded
191
+ process-local evidence, so continuation does not rerun SVN against a changing working copy. Evidence
192
+ expires after 10 minutes and is limited to 2 MiB per operation, 32 operations, and 16 MiB total.
193
+ `svn_log messageContains` performs a bounded server-side scan; `changedPathsSummary:true` returns
194
+ per-revision action counts and top-level directories without listing every path. Large updates can
195
+ use `maxItems`, `taskPaths`, and `targetOverlapOnly` to keep unrelated paths out of the receipt while
196
+ making complete conflict evidence available through bounded `conflictCursor` pages.
197
+ Runner-level line/output truncation is carried into the operation evidence, so a final retained page
198
+ cannot be mistaken for the complete source diff.
199
+
200
+ Normal responses use working-copy-relative paths. High-use tools accept a validated `fields`
201
+ array; the allowed names are published once under `globalResponseControls.fieldProjections` in
202
+ `docs/MCP_API.json` so the live MCP does not repeat those lists in every tool schema. Invalid
203
+ fields are rejected before any SVN process starts. Focused `docs` and `review` profiles advertise
204
+ only `compact`, `receipt`, and `structured-only`; known callers may still explicitly request
205
+ standard/full diagnostics, but switching to the full profile is clearer for diagnostic work.
206
+
207
+ High-volume controls are likewise published once under
208
+ `globalResponseControls.advancedInputs` in `docs/MCP_API.json`, rather than repeated in every live
209
+ tool schema. They include `afterCursor` for status/snapshot polling, diff `file`/`operationId`,
210
+ bounded log filtering and summaries, and update paging/overlap controls. Snapshot tokens are opaque,
211
+ working-copy and query bound, process-local, and expire after 15 minutes. Repeating the same status
212
+ or snapshot with `afterCursor` returns a minimal `NO_CHANGE` receipt; changed or safety-relevant
213
+ state returns the current bounded result and a replacement token.
214
+ For multi-client editing, `svn_snapshot captureBaseline:true` on explicit files returns a separate
215
+ pre-edit baseline token. Pass it to `svn_update baselineToken` to receive path-level local-edit,
216
+ remote-touch, conflict, and same-path-collision evidence. Directory baselines are refused because
217
+ directory metadata cannot prove which descendant changed.
218
+ Conflict lists use independent pages of at most 100 paths; `conflictCount`, `conflictsTruncated`, and
219
+ `nextConflictCursor` make omitted pages explicit without inflating every status or update response.
220
+
149
221
  `svn_commit` refuses existing directory targets by default because its deliberate `--depth empty`
150
222
  behavior commits only the directory node and excludes changed descendants. Prefer explicit file
151
- paths. Set `allowDirectoryTargets:true` only when intentionally committing directory properties
152
- or another directory-node-only change; remaining descendants are reported as post-commit residue.
153
- `svn_precommit` accepts the same `allowDirectoryTargets` and `allowRoot` acknowledgements so its
154
- readiness verdict matches those target-scope guards.
223
+ paths. Set `expandDescendants:true` to expand a named directory to its currently changed descendants,
224
+ guard every result, and return the exact expanded scope. Set `allowDirectoryTargets:true` only when
225
+ intentionally committing a directory property or another directory-node-only change.
226
+ `svn_precommit` accepts the same scope controls so its readiness verdict matches the later commit.
227
+ A READY precommit also returns a short-lived `precommitToken` bound to exact path status, base
228
+ revisions, content hashes, repository policy, diff identity, and observed remote revision. Passing
229
+ that token to `svn_commit` makes the commit refuse if the verified state changed in between.
230
+
231
+ Release workflows can pin `svn_update` with an exact `revision`; it still requires explicit paths
232
+ or `updateAll:true` and always postpones conflicts. Add `expectedRemoteHead` with a numeric revision
233
+ to refuse if repository HEAD moved since the caller's probe. Use
234
+ `svn_precommit requireUniformRevision:true` when a release handoff must not proceed from a
235
+ mixed-revision working copy. The default remains backward compatible and reports mixed revisions
236
+ without blocking ordinary precommit work.
237
+
238
+ `svn_commit operation:"prepare"` performs a pinned update of explicit intended paths with conflicts
239
+ postponed, checks an optional expected remote HEAD, refuses any path touched outside that scope, and
240
+ then runs the normal guarded precommit checks. It never commits. Its compact receipt reports the
241
+ resulting revision, conflicts, updated paths, and exact final commit scope. Keeping preparation as
242
+ a mode of the existing commit workflow avoids loading another tool schema.
243
+
244
+ `svn_commit operation:"safe"` performs the guarded sequence in one durable call: pinned scoped
245
+ update, baseline collision refusal, automatic verified EOL repair when precommit requests it,
246
+ precommit binding, commit, pinned update to the committed revision, and a final clean scoped
247
+ snapshot. It requires an explicit numeric `revision`, `expectedRemoteHead`, pre-edit
248
+ `baselineToken` when an earlier edit-session baseline is available, valid commit message, explicit
249
+ paths, and UUID `operationId`. Without a token it captures the current explicit-file state before
250
+ update, keeping the common workflow to one call. Its normal response is a compact receipt. Use
251
+ `operation:"detail"` with the returned `detailOperationId` and cursor to
252
+ page bounded stage evidence only when an audit needs it. This adds no advertised tool schema; the
253
+ full profile remains at 25 tools.
254
+
255
+ Scheduled-added files are not valid `svn update` operands, so safe mode omits only those files from
256
+ the pinned update while still verifying the expected repository HEAD. They remain in the exact
257
+ precommit and commit scope.
258
+
259
+ Mutation retries can include a UUID `operationId` on `svn_update`, `svn_commit` (including prepare
260
+ and safe mode),
261
+ `eol_fix_verified`, and `svn_resolve`. The server binds that ID to normalized inputs and stores a
262
+ bounded receipt outside the working copy. An identical retry replays the prior result after a client
263
+ timeout or MCP restart; a concurrent or changed request with the same ID is refused. The receipt is
264
+ local to one machine, not a distributed lock between machines. `SVN_MCP_OPERATION_DIR` can relocate
265
+ the store when an operator needs a different profile-data location.
266
+ The resolved store path is refused when it sits inside any SVN working copy. Terminal receipts and
267
+ orphan lock/temp files are pruned within fixed count, byte, age, and record-size limits; retained
268
+ unfinished or unreadable records are never deleted to make room, so new operations fail closed when
269
+ those records exhaust capacity.
270
+
271
+ Repositories can make EOL handling automatic for new files:
272
+
273
+ ```json
274
+ {
275
+ "normalizeEol": "crlf",
276
+ "eolExclude": ["**/*.patch", "**/*.diff"]
277
+ }
278
+ ```
279
+
280
+ With this in `.svn-mcp-policy.json`, `svn_add` normalizes and verifies new text files in the same
281
+ call, skips binaries and excluded byte-exact fixtures, and refuses before scheduling if verification
282
+ fails. `eol_fix_verified` also accepts a bounded explicit `paths` batch for tracked-file repairs.
283
+ `svn_diff` and `svn_blame` ignore EOL-only churn by default; use `showEolChanges:true` only for EOL
284
+ diagnostics.
155
285
 
156
286
  ## Commands
157
287
 
@@ -166,6 +296,7 @@ readiness verdict matches those target-scope guards.
166
296
  | `npm test` | Run the Jest test suite |
167
297
  | `npm run test:package` | Pack, install, and self-check the real npm artifact in isolation |
168
298
  | `npm run benchmark:responses` | Compare compact MCP, full MCP, and equivalent raw SVN output sizes |
299
+ | `npm run check:response-budgets` | Fail when representative compact responses or schemas exceed token budgets |
169
300
  | `npm run prepare:local` | Build and prepare the local `current` runtime |
170
301
  | `npm run release:prepare` | Copy `dist/` and `bin/` into `releases/v<version>` and repoint `current` |
171
302
  | `npm run clean` | Remove root `dist/` with the Node clean script |
@@ -174,7 +305,7 @@ readiness verdict matches those target-scope guards.
174
305
 
175
306
  Use `svn_self_check` to verify the MCP package, runtime layout, resolved native or bundled tools, and release scripts. Use `svn_diagnose` on a working-copy path when SVN itself is acting strange; it checks local status, remote status, HEAD info, latest log reachability, and returns actionable notes for authentication, network, lock, and working-copy database failures.
176
307
 
177
- Use `svn_snapshot` for a one-call status and revision summary. `svn_log` and `svn_diff` accept exact or ranged revision selectors, while bounded `svn_cat` and `svn_blame` calls support historical file inspection without raw SVN output. Mutations include dry-run-first `svn_delete` and canonical `svn_resolve`; the older `svn_resolved` name remains as a deprecated compatibility alias.
308
+ Use `svn_snapshot` for a one-call status and revision summary. Exact ignored descendants are reported with their covering ignored ancestor instead of disappearing behind SVN's `W155010` warning. `svn_log` and `svn_diff` accept exact or ranged revision selectors; multi-entry log envelopes report an explicit revision range and entry count. Bounded `svn_cat` and `svn_blame` calls support historical file inspection without raw SVN output. Mutations include dry-run-first `svn_delete`, canonical `svn_resolve`, and `svn_path_change` with an explicit `move`, `rename`, or `copy` action. Legacy direct calls to `svn_resolved`, `svn_move`, `svn_rename`, and `svn_copy` remain callable in the full profile for compatibility but are no longer advertised.
178
309
 
179
310
  For SVN property work, use `svn_propget` and guarded `svn_propset` instead of raw `svn propget`/`svn propset`. `svn_propset_eol_style` remains the safer shortcut for `svn:eol-style` normalization.
180
311
 
package/SECURITY.md CHANGED
@@ -30,8 +30,12 @@ Please do not publish exploit details until a fix or mitigation is available.
30
30
  in read-only mode; import scans its source for never-commit paths and refuses symbolic links or
31
31
  directory junctions before invoking SVN.
32
32
  - Buffered SVN output is limited to 20 MB. Streamed diff lines are limited to 1 MiB, and diff file
33
- summaries are limited to 20,000 entries. Truncation and over-limit failures are reported rather
34
- than silently discarded.
33
+ summaries are limited to 20,000 entries. Streamed parser callbacks and per-file previews have
34
+ separate work/size limits. Truncation, incomplete aggregate totals, and over-limit failures are
35
+ reported rather than silently discarded.
36
+ - Child-process timeouts and MCP cancellation terminate the process tree, escalate when needed, and
37
+ wait for process closure before returning a receipt. Output byte limits count UTF-8 bytes rather
38
+ than JavaScript string units.
35
39
  - Compact diff results enforce a separate serialized-size budget and return continuation cursors
36
40
  for omitted excerpts and file summaries. Stdio clients must still buffer the byte stream through
37
41
  its newline-delimited JSON-RPC record boundary instead of parsing arbitrary read chunks.
@@ -39,6 +43,36 @@ Please do not publish exploit details until a fix or mitigation is available.
39
43
  not a substitute for keeping credentials out of versioned file content and commit messages.
40
44
  - Commit/import messages and generic property values are passed through mode-0600 temporary files
41
45
  outside the working copy and removed in `finally`, rather than embedded in displayed commands.
46
+ - Optional mutation operation receipts are stored outside working copies with atomic replacement,
47
+ restricted file modes, bounded record sizes, and no raw successful stdout/stderr. IDs are bound to
48
+ normalized inputs; unreadable, mismatched, concurrent, or ambiguous stale receipts fail closed.
49
+ The physical store path is refused inside an SVN working copy. Terminal and stale orphan files
50
+ are pruned within fixed limits; retained unfinished or unreadable records cause a capacity refusal
51
+ rather than deletion. Live lock owners are preserved, abandoned breaker files are recoverable,
52
+ and lock acquisition waits asynchronously for a bounded five seconds without blocking unrelated
53
+ MCP requests. The receipt store is local to one host and must not be treated as a cross-machine lock.
54
+ - Working-copy `cwd` inputs must be absolute. Repository URL inputs containing user information are
55
+ refused; authentication remains the responsibility of the native SVN credential cache or trusted
56
+ operator configuration.
57
+ - Baseline, precommit, and safe-operation detail tokens are process-local, expire, and are bound to
58
+ a working copy plus exact explicit paths. Baselines accept files only. Precommit tokens include
59
+ file content hashes, canonical SVN property hashes, status, base revisions, repository policy, diff identity, and observed
60
+ remote revision; commit rechecks them without weakening any ordinary guard. Detailed workflow
61
+ stages stay in bounded memory and are not persisted with durable mutation receipts.
62
+ - Workflow content hashes use cancellable streams, a bounded worker pool, and a default 1 GiB
63
+ aggregate explicit-scope ceiling. `SVN_MCP_HASH_CONCURRENCY` and `SVN_MCP_MAX_HASH_BYTES` may
64
+ tune those limits without weakening path containment.
65
+ - Verified EOL repair applies never-commit guards before mutation. Large opted-in files use
66
+ streaming verification and disk-backed backups; rollback will not overwrite a file whose content
67
+ changed after normalization.
68
+ - Precommit evidence is revalidated immediately before invoking `svn commit`. This narrows the
69
+ local check/use interval but cannot freeze files against an unrelated external editor; use one
70
+ writer per working copy and do not share a writable checkout across processes or machines.
71
+ - `svn_commit operation:"safe"` requires an exact revision, expected remote revision, valid commit
72
+ message, explicit files, and durable operation ID. It accepts a stronger pre-edit baseline or
73
+ captures the current scoped state internally before update. It stops before
74
+ commit on same-path overlap or postponed conflict, and an interrupted ambiguous operation fails
75
+ closed rather than repeating a mutation.
42
76
  - SVN and conversion processes inherit the host environment so native credential caches, proxy
43
77
  settings, home directories, and configured SSH transports continue to work. Treat MCP process
44
78
  environment variables as trusted operator configuration and do not place secrets in debug logs.
@@ -1,6 +1,6 @@
1
1
  # SHA256 checksums for bundled third-party binaries
2
2
  #
3
- # Generated from the files under bin/ for release v1.2.0.
3
+ # Generated from the files under bin/ for the current public distribution.
4
4
 
5
5
  213cdeffc15c734e42565c90512491113652de9e52694ae335131d0e24f91df7 bin/api-ms-win-core-console-l1-1-0.dll
6
6
  45a155e9b60f068fbc3ea8dd73552905afeae49270bea6bbccb4aad0aa696f2d bin/api-ms-win-core-console-l1-2-0.dll
@@ -64,7 +64,7 @@ bcc347a52726e139d3cfec484503dd178859ad3d6d47771dda3dbbc61766ebfc bin/libsvn_fs_
64
64
  1c95f7db69e732b995122b12502387867c8c13dd9574f8b0e5a12d10c2da4930 bin/msvcp140_2.dll
65
65
  f8a381e45f6f3dcab092b5e256c8304906b3c523dc721bcc126dd899167e0ba6 bin/msvcp140_codecvt_ids.dll
66
66
  faaa4870bf745444022f409bd494095b7b3796637cf9994ad9faf7a43f393b88 bin/msvcp140.dll
67
- 514bbd1a03109aba979b9ecb7fad46a43e3f29da6741adb827d36cabf0690b6d bin/svn.exe
67
+ 626bbab5b6b823944ac07996e6ab6c79166a9b3cc59a554bc980300707856a38 bin/svn.exe
68
68
  553f415884b3868b0054d9050bd47892762e25f2b78a4570d61ae7f139b05308 bin/svnadmin.exe
69
69
  7b35859f7e653a02c3e11a0ee126d7c27c4380ad4467301554f00677a0d85587 bin/svnbench.exe
70
70
  59791853f1151233ad774ef1814bffaefbe5b72fe0dfb52360869bd28daac541 bin/svndumpfilter.exe
@@ -21,6 +21,10 @@ APR Util, OpenSSL, Subversion, and Zlib license files are reproduced under
21
21
  `third_party_licenses/apache-subversion-windows/`. The Apache Subversion 1.14.5 `NOTICE` file is
22
22
  included there as well. The package contains no separate OpenSSL runtime DLLs.
23
23
 
24
+ This project modifies the embedded application manifest in `bin/svn.exe` to request the Windows
25
+ UTF-8 active code page. The executable code and all other bundled files remain from the named
26
+ VisualSVN archive. The source manifest and reproducible maintenance script are under `scripts/`.
27
+
24
28
  Microsoft Visual C++ runtime support files in `bin/` are copied unmodified from the VisualSVN
25
29
  archive. Microsoft redistributable runtime license terms apply to those files.
26
30
 
package/bin/svn.exe CHANGED
Binary file
@@ -0,0 +1,21 @@
1
+ import type { ToolEnvelope } from "./types.js";
2
+ export type CommitScopeResult = {
3
+ ok: true;
4
+ paths: string[];
5
+ expanded: boolean;
6
+ expandedPaths: string[];
7
+ } | {
8
+ ok: false;
9
+ note: string;
10
+ envelope?: ToolEnvelope;
11
+ expanded: boolean;
12
+ expandedPaths: string[];
13
+ };
14
+ export declare function resolveCommitScope(input: {
15
+ cwd: string;
16
+ wcRoot: string;
17
+ paths: string[];
18
+ expandDescendants?: boolean;
19
+ allowDirectoryTargets?: boolean;
20
+ }): Promise<CommitScopeResult>;
21
+ //# sourceMappingURL=commitScope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitScope.d.ts","sourceRoot":"","sources":["../src/commitScope.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK/C,MAAM,MAAM,iBAAiB,GACzB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,GACD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAEN,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkE7B"}
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { findExistingDirectoryTarget, isCommittableStatus, isInsideOrEqual, pathIdentityKey, repoRelativePath, resolveTargetsInsideWc } from "./guards.js";
4
+ import { scopedStatusMap } from "./tools/readonly.js";
5
+ const MAX_EXPANDED_COMMIT_PATHS = 500;
6
+ export async function resolveCommitScope(input) {
7
+ const directoryTarget = findExistingDirectoryTarget(input.paths);
8
+ if (!directoryTarget.ok) {
9
+ return { ok: false, note: directoryTarget.note, expanded: false, expandedPaths: [] };
10
+ }
11
+ if (!directoryTarget.target) {
12
+ return { ok: true, paths: input.paths, expanded: false, expandedPaths: [] };
13
+ }
14
+ if (!input.expandDescendants) {
15
+ if (!input.allowDirectoryTargets) {
16
+ return {
17
+ ok: false,
18
+ note: `directory commit target requires allowDirectoryTargets:true because --depth empty excludes descendants: ${repoRelativePath(directoryTarget.target, input.wcRoot)}`,
19
+ expanded: false,
20
+ expandedPaths: []
21
+ };
22
+ }
23
+ return { ok: true, paths: input.paths, expanded: false, expandedPaths: [] };
24
+ }
25
+ const directoryKeys = new Set(input.paths.filter(isExistingDirectory).map((candidate) => pathIdentityKey(candidate)));
26
+ const explicitFileKeys = new Set(input.paths
27
+ .filter((candidate) => !directoryKeys.has(pathIdentityKey(candidate)))
28
+ .map((candidate) => pathIdentityKey(candidate)));
29
+ const status = await scopedStatusMap(input.cwd, input.wcRoot, input.paths);
30
+ if (!status.envelope.ok) {
31
+ return {
32
+ ok: false,
33
+ note: status.envelope.note || "unable to expand directory commit targets",
34
+ envelope: status.envelope,
35
+ expanded: true,
36
+ expandedPaths: []
37
+ };
38
+ }
39
+ const candidates = [];
40
+ for (const changed of status.envelope.changed_paths) {
41
+ if (!isCommittableStatus(changed.status))
42
+ continue;
43
+ const candidate = path.resolve(input.cwd, changed.path);
44
+ const key = pathIdentityKey(candidate);
45
+ if (explicitFileKeys.has(key) || [...directoryKeys].some((directory) => isInsideOrEqual(candidate, directory))) {
46
+ if (!candidates.some((existing) => pathIdentityKey(existing) === key)) {
47
+ candidates.push(candidate);
48
+ }
49
+ }
50
+ }
51
+ candidates.sort((left, right) => repoRelativePath(left, input.wcRoot).localeCompare(repoRelativePath(right, input.wcRoot)));
52
+ if (candidates.length > MAX_EXPANDED_COMMIT_PATHS) {
53
+ return {
54
+ ok: false,
55
+ note: `expanded commit scope contains ${candidates.length} paths; narrow the directory scope to at most ${MAX_EXPANDED_COMMIT_PATHS}`,
56
+ expanded: true,
57
+ expandedPaths: candidates.slice(0, MAX_EXPANDED_COMMIT_PATHS).map((candidate) => repoRelativePath(candidate, input.wcRoot))
58
+ };
59
+ }
60
+ const contained = resolveTargetsInsideWc(input.cwd, input.wcRoot, candidates);
61
+ if (!contained.ok) {
62
+ return { ok: false, note: contained.note, expanded: true, expandedPaths: [] };
63
+ }
64
+ return {
65
+ ok: true,
66
+ paths: contained.paths,
67
+ expanded: true,
68
+ expandedPaths: contained.paths.map((candidate) => repoRelativePath(candidate, input.wcRoot))
69
+ };
70
+ }
71
+ function isExistingDirectory(candidate) {
72
+ try {
73
+ return fs.statSync(candidate).isDirectory();
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ }
79
+ //# sourceMappingURL=commitScope.js.map