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.
- package/CHANGELOG.md +157 -0
- package/README.md +160 -29
- package/SECURITY.md +36 -2
- package/THIRD_PARTY_CHECKSUMS.txt +2 -2
- package/THIRD_PARTY_NOTICES.md +4 -0
- package/bin/svn.exe +0 -0
- package/dist/commitScope.d.ts +21 -0
- package/dist/commitScope.d.ts.map +1 -0
- package/dist/commitScope.js +79 -0
- package/dist/commitScope.js.map +1 -0
- package/dist/eol.d.ts +29 -0
- package/dist/eol.d.ts.map +1 -1
- package/dist/eol.js +254 -7
- package/dist/eol.js.map +1 -1
- package/dist/evidenceStore.d.ts +32 -0
- package/dist/evidenceStore.d.ts.map +1 -0
- package/dist/evidenceStore.js +131 -0
- package/dist/evidenceStore.js.map +1 -0
- package/dist/fileHash.d.ts +13 -0
- package/dist/fileHash.d.ts.map +1 -0
- package/dist/fileHash.js +67 -0
- package/dist/fileHash.js.map +1 -0
- package/dist/guards.d.ts +18 -0
- package/dist/guards.d.ts.map +1 -1
- package/dist/guards.js +80 -8
- package/dist/guards.js.map +1 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +432 -46
- package/dist/index.js.map +1 -1
- package/dist/operationStore.d.ts +74 -0
- package/dist/operationStore.d.ts.map +1 -0
- package/dist/operationStore.js +705 -0
- package/dist/operationStore.js.map +1 -0
- package/dist/parse/diffText.d.ts +4 -0
- package/dist/parse/diffText.d.ts.map +1 -1
- package/dist/parse/diffText.js +78 -8
- package/dist/parse/diffText.js.map +1 -1
- package/dist/parse/infoXml.d.ts.map +1 -1
- package/dist/parse/infoXml.js +1 -0
- package/dist/parse/infoXml.js.map +1 -1
- package/dist/parse/updateText.d.ts.map +1 -1
- package/dist/parse/updateText.js +3 -8
- package/dist/parse/updateText.js.map +1 -1
- package/dist/response.d.ts +1 -1
- package/dist/response.d.ts.map +1 -1
- package/dist/response.js +980 -124
- package/dist/response.js.map +1 -1
- package/dist/runner.d.ts +5 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +187 -50
- package/dist/runner.js.map +1 -1
- package/dist/snapshotToken.d.ts +17 -0
- package/dist/snapshotToken.d.ts.map +1 -0
- package/dist/snapshotToken.js +96 -0
- package/dist/snapshotToken.js.map +1 -0
- package/dist/tools/composite.d.ts +41 -1
- package/dist/tools/composite.d.ts.map +1 -1
- package/dist/tools/composite.js +963 -67
- package/dist/tools/composite.js.map +1 -1
- package/dist/tools/mutating.d.ts +28 -0
- package/dist/tools/mutating.d.ts.map +1 -1
- package/dist/tools/mutating.js +652 -37
- package/dist/tools/mutating.js.map +1 -1
- package/dist/tools/readonly.d.ts +32 -0
- package/dist/tools/readonly.d.ts.map +1 -1
- package/dist/tools/readonly.js +346 -22
- package/dist/tools/readonly.js.map +1 -1
- package/dist/tools/selfcheck.d.ts +14 -1
- package/dist/tools/selfcheck.d.ts.map +1 -1
- package/dist/tools/selfcheck.js +42 -4
- package/dist/tools/selfcheck.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workflowEvidence.d.ts +29 -0
- package/dist/workflowEvidence.d.ts.map +1 -0
- package/dist/workflowEvidence.js +47 -0
- package/dist/workflowEvidence.js.map +1 -0
- package/dist/workflowState.d.ts +31 -0
- package/dist/workflowState.d.ts.map +1 -0
- package/dist/workflowState.js +209 -0
- package/dist/workflowState.js.map +1 -0
- package/docs/MCP_API.json +420 -180
- package/docs/SPEC.md +377 -82
- 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.
|
|
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
|
-
##
|
|
11
|
+
## Install From npm
|
|
12
12
|
|
|
13
13
|
```shell
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
50
|
+
## Source Setup From GitHub
|
|
38
51
|
|
|
39
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
###
|
|
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
|
-
###
|
|
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
|
-
`
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`
|
|
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
|
|
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 `
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
readiness verdict matches
|
|
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
|
|
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.
|
|
34
|
-
|
|
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
|
|
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
|
-
|
|
67
|
+
626bbab5b6b823944ac07996e6ab6c79166a9b3cc59a554bc980300707856a38 bin/svn.exe
|
|
68
68
|
553f415884b3868b0054d9050bd47892762e25f2b78a4570d61ae7f139b05308 bin/svnadmin.exe
|
|
69
69
|
7b35859f7e653a02c3e11a0ee126d7c27c4380ad4467301554f00677a0d85587 bin/svnbench.exe
|
|
70
70
|
59791853f1151233ad774ef1814bffaefbe5b72fe0dfb52360869bd28daac541 bin/svndumpfilter.exe
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -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
|