sooth 0.2.2__tar.gz → 0.2.3__tar.gz
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.
- {sooth-0.2.2 → sooth-0.2.3}/.github/workflows/ci.yml +1 -0
- {sooth-0.2.2 → sooth-0.2.3}/PKG-INFO +23 -8
- {sooth-0.2.2 → sooth-0.2.3}/README.md +22 -7
- sooth-0.2.3/action.sh +29 -0
- sooth-0.2.3/action.yml +35 -0
- {sooth-0.2.2 → sooth-0.2.3}/pyproject.toml +1 -1
- sooth-0.2.3/tests/test_action.sh +86 -0
- {sooth-0.2.2 → sooth-0.2.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/.gitignore +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/LICENSE +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/docs/DESIGN.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/docs/DOGFOOD.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/docs/PRD.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/docs/TESTING.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/calibration.json +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/calibration.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/draft.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/news-1-evil.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/news-1-output.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/news-1-summ.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/news-1.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/policy.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/pricing.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/examples/source.md +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/src/sooth/__init__.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/src/sooth/claims.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/src/sooth/cli.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/src/sooth/demo.json +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/src/sooth/report.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/src/sooth/verify.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/tests/calibrate.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/tests/conftest.py +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/tests/smoke.sh +0 -0
- {sooth-0.2.2 → sooth-0.2.3}/tests/test_core.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sooth
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Verify AI-generated text against source material. Claim-by-claim trust reports powered by Jev (TypeSafe System One).
|
|
5
5
|
Project-URL: Homepage, https://github.com/naufalhilmiaji/sooth
|
|
6
6
|
Project-URL: Documentation, https://github.com/naufalhilmiaji/sooth/tree/main/docs
|
|
@@ -48,10 +48,18 @@ Real output — seven claims in an AI-written news summary, three numbers quietl
|
|
|
48
48
|
|
|
49
49
|
| # | Claim | Verdict | P | Why (P distribution) | Evidence |
|
|
50
50
|
|---|-------|---------|---|----------------------|----------|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
51
|
+
| 1 | Aturan baru BEI menurunkan batas bawah harga saham menjadi Rp 1 per saham mulai 28 September 2026. | ✅ PASS | ████████ 1.00 | supports 1.00 / not_found 0.00 / contradicts 0.00 · details 0.98 | `examples/news-1.md:3` "Saham-saham Grup Bakrie kembali menjadi sorotan menjelang…" |
|
|
52
|
+
| 2 | Menurut analis Bumiputera Sekuritas, aturan ini berlaku untuk seluruh emiten di BEI. | ✅ PASS | ████████ 1.00 | supports 1.00 / not_found 0.00 / contradicts 0.00 · details 0.82 | `examples/news-1.md:7` "Ia menyebut aturan ini berlaku untuk seluruh saham di BEI…" |
|
|
53
|
+
| 3 | BNBR baru menuntaskan rights issue bernilai besar di harga Rp 33. | ❌ FAIL | ████████ 1.00 | supports 0.00 / not_found 0.00 / contradicts 1.00 · details 0.01 · missing #s: 33 | `examples/news-1.md:25` "Saham ini juga baru menyelesaikan rights issue dalam juml…" |
|
|
54
|
+
| 4 | Saham VIVA disuspensi di harga Rp 50. | ❌ FAIL | ████████ 1.00 | supports 0.00 / not_found 0.00 / contradicts 1.00 · details 0.02 | |
|
|
55
|
+
| 5 | BUMI hanya perlu turun sekitar 10% untuk menyentuh level Rp 50. | ❌ FAIL | ████████ 1.00 | supports 0.00 / not_found 0.00 / contradicts 1.00 · details 0.01 · missing #s: 10 | `examples/news-1.md:23` "Adapun PT Bumi Resources Tbk (BUMI) di sekitar Rp192 haru…" |
|
|
56
|
+
| 6 | BEI juga menetapkan batas atas harga saham Rp 5.000 per saham di pasar reguler. | ⚠️ REVIEW | ████████ 1.00 | supports 0.00 / not_found 1.00 / contradicts 0.00 · details 0.02 · missing #s: 5.000 | |
|
|
57
|
+
| 7 | Para investor ritel sangat senang dengan aturan baru ini. | ➖ UNCHECKABLE | ██░░░░░░ 0.25 | P(checkable)=0.25 | |
|
|
58
|
+
|
|
59
|
+
## Needs review
|
|
60
|
+
|
|
61
|
+
- line 13: BEI juga menetapkan batas atas harga saham Rp 5.000 per saham di pasar reguler.
|
|
62
|
+
- line 15: Para investor ritel sangat senang dengan aturan baru ini.
|
|
55
63
|
```
|
|
56
64
|
|
|
57
65
|
Every verdict carries its probability distribution and the source span it was judged against. When Sooth is unsure, it says `REVIEW` instead of guessing.
|
|
@@ -85,15 +93,22 @@ sooth --source policy.md --text draft.md --format plain
|
|
|
85
93
|
# --log FILE append full judgment trace (one JSONL line per run)
|
|
86
94
|
```
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
Use it in CI as a quality gate for generated content:
|
|
89
97
|
|
|
90
98
|
```yaml
|
|
91
99
|
- name: Verify AI output
|
|
92
|
-
|
|
100
|
+
uses: naufalhilmiaji/sooth@v0.2.3
|
|
101
|
+
with:
|
|
102
|
+
source: docs/policy.md
|
|
103
|
+
text: generated-reply.md
|
|
93
104
|
env:
|
|
94
105
|
TYPESAFE_API_KEY: ${{ secrets.TYPESAFE_API_KEY }}
|
|
95
106
|
```
|
|
96
107
|
|
|
108
|
+
`source` takes newline-separated paths when you have several documents. The step fails the build on any `FAIL` — and on any `REVIEW`, so add `continue-on-error: true` if you only want to block on hard contradictions. The full report is appended to the job summary.
|
|
109
|
+
|
|
110
|
+
Prefer plain shell? `sooth --source policy.md --text draft.md` gives the same exit codes.
|
|
111
|
+
|
|
97
112
|
## How it works
|
|
98
113
|
|
|
99
114
|
1. Draft is split into claims (one sentence each).
|
|
@@ -149,9 +164,9 @@ Docs: [PRD](https://github.com/naufalhilmiaji/sooth/blob/main/docs/PRD.md) · [D
|
|
|
149
164
|
|
|
150
165
|
## Roadmap
|
|
151
166
|
|
|
167
|
+
- v0.2.3 shipped: GitHub Action — CI quality gate in one `uses:` line
|
|
152
168
|
- v0.2.2 shipped: `sooth demo` (offline, no API key)
|
|
153
169
|
- v0.2.1 shipped: source-span evidence, published on PyPI
|
|
154
|
-
- GitHub Action
|
|
155
170
|
- later: hosted web app — paste UI, history, team review queues
|
|
156
171
|
|
|
157
172
|
## License
|
|
@@ -25,10 +25,18 @@ Real output — seven claims in an AI-written news summary, three numbers quietl
|
|
|
25
25
|
|
|
26
26
|
| # | Claim | Verdict | P | Why (P distribution) | Evidence |
|
|
27
27
|
|---|-------|---------|---|----------------------|----------|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
28
|
+
| 1 | Aturan baru BEI menurunkan batas bawah harga saham menjadi Rp 1 per saham mulai 28 September 2026. | ✅ PASS | ████████ 1.00 | supports 1.00 / not_found 0.00 / contradicts 0.00 · details 0.98 | `examples/news-1.md:3` "Saham-saham Grup Bakrie kembali menjadi sorotan menjelang…" |
|
|
29
|
+
| 2 | Menurut analis Bumiputera Sekuritas, aturan ini berlaku untuk seluruh emiten di BEI. | ✅ PASS | ████████ 1.00 | supports 1.00 / not_found 0.00 / contradicts 0.00 · details 0.82 | `examples/news-1.md:7` "Ia menyebut aturan ini berlaku untuk seluruh saham di BEI…" |
|
|
30
|
+
| 3 | BNBR baru menuntaskan rights issue bernilai besar di harga Rp 33. | ❌ FAIL | ████████ 1.00 | supports 0.00 / not_found 0.00 / contradicts 1.00 · details 0.01 · missing #s: 33 | `examples/news-1.md:25` "Saham ini juga baru menyelesaikan rights issue dalam juml…" |
|
|
31
|
+
| 4 | Saham VIVA disuspensi di harga Rp 50. | ❌ FAIL | ████████ 1.00 | supports 0.00 / not_found 0.00 / contradicts 1.00 · details 0.02 | |
|
|
32
|
+
| 5 | BUMI hanya perlu turun sekitar 10% untuk menyentuh level Rp 50. | ❌ FAIL | ████████ 1.00 | supports 0.00 / not_found 0.00 / contradicts 1.00 · details 0.01 · missing #s: 10 | `examples/news-1.md:23` "Adapun PT Bumi Resources Tbk (BUMI) di sekitar Rp192 haru…" |
|
|
33
|
+
| 6 | BEI juga menetapkan batas atas harga saham Rp 5.000 per saham di pasar reguler. | ⚠️ REVIEW | ████████ 1.00 | supports 0.00 / not_found 1.00 / contradicts 0.00 · details 0.02 · missing #s: 5.000 | |
|
|
34
|
+
| 7 | Para investor ritel sangat senang dengan aturan baru ini. | ➖ UNCHECKABLE | ██░░░░░░ 0.25 | P(checkable)=0.25 | |
|
|
35
|
+
|
|
36
|
+
## Needs review
|
|
37
|
+
|
|
38
|
+
- line 13: BEI juga menetapkan batas atas harga saham Rp 5.000 per saham di pasar reguler.
|
|
39
|
+
- line 15: Para investor ritel sangat senang dengan aturan baru ini.
|
|
32
40
|
```
|
|
33
41
|
|
|
34
42
|
Every verdict carries its probability distribution and the source span it was judged against. When Sooth is unsure, it says `REVIEW` instead of guessing.
|
|
@@ -62,15 +70,22 @@ sooth --source policy.md --text draft.md --format plain
|
|
|
62
70
|
# --log FILE append full judgment trace (one JSONL line per run)
|
|
63
71
|
```
|
|
64
72
|
|
|
65
|
-
|
|
73
|
+
Use it in CI as a quality gate for generated content:
|
|
66
74
|
|
|
67
75
|
```yaml
|
|
68
76
|
- name: Verify AI output
|
|
69
|
-
|
|
77
|
+
uses: naufalhilmiaji/sooth@v0.2.3
|
|
78
|
+
with:
|
|
79
|
+
source: docs/policy.md
|
|
80
|
+
text: generated-reply.md
|
|
70
81
|
env:
|
|
71
82
|
TYPESAFE_API_KEY: ${{ secrets.TYPESAFE_API_KEY }}
|
|
72
83
|
```
|
|
73
84
|
|
|
85
|
+
`source` takes newline-separated paths when you have several documents. The step fails the build on any `FAIL` — and on any `REVIEW`, so add `continue-on-error: true` if you only want to block on hard contradictions. The full report is appended to the job summary.
|
|
86
|
+
|
|
87
|
+
Prefer plain shell? `sooth --source policy.md --text draft.md` gives the same exit codes.
|
|
88
|
+
|
|
74
89
|
## How it works
|
|
75
90
|
|
|
76
91
|
1. Draft is split into claims (one sentence each).
|
|
@@ -126,9 +141,9 @@ Docs: [PRD](https://github.com/naufalhilmiaji/sooth/blob/main/docs/PRD.md) · [D
|
|
|
126
141
|
|
|
127
142
|
## Roadmap
|
|
128
143
|
|
|
144
|
+
- v0.2.3 shipped: GitHub Action — CI quality gate in one `uses:` line
|
|
129
145
|
- v0.2.2 shipped: `sooth demo` (offline, no API key)
|
|
130
146
|
- v0.2.1 shipped: source-span evidence, published on PyPI
|
|
131
|
-
- GitHub Action
|
|
132
147
|
- later: hosted web app — paste UI, history, team review queues
|
|
133
148
|
|
|
134
149
|
## License
|
sooth-0.2.3/action.sh
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wire SOOTH_* inputs into the sooth CLI, surface the report, propagate the exit code.
|
|
3
|
+
# Inputs arrive via env (never interpolated into this script) so untrusted input
|
|
4
|
+
# cannot be executed as shell.
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
args=(--format md)
|
|
8
|
+
while IFS= read -r path; do
|
|
9
|
+
[ -z "$path" ] && continue
|
|
10
|
+
args+=(--source "$path")
|
|
11
|
+
done <<< "$SOOTH_SOURCE"
|
|
12
|
+
|
|
13
|
+
args+=(--text "$SOOTH_TEXT")
|
|
14
|
+
if [ -n "${SOOTH_CONFIDENCE:-}" ]; then
|
|
15
|
+
args+=(--confidence "$SOOTH_CONFIDENCE")
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
report="${RUNNER_TEMP:-/tmp}/sooth-report.md"
|
|
19
|
+
sooth "${args[@]}" -o "$report"
|
|
20
|
+
status=$?
|
|
21
|
+
|
|
22
|
+
if [ -f "$report" ]; then
|
|
23
|
+
cat "$report"
|
|
24
|
+
if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
|
|
25
|
+
cat "$report" >> "$GITHUB_STEP_SUMMARY"
|
|
26
|
+
fi
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
exit "$status"
|
sooth-0.2.3/action.yml
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: "Sooth"
|
|
2
|
+
description: "Claim-by-claim verification of AI-generated text against source material. Fails CI on hallucinations."
|
|
3
|
+
author: "Naufal Hilmiaji"
|
|
4
|
+
branding:
|
|
5
|
+
icon: "check-circle"
|
|
6
|
+
color: "green"
|
|
7
|
+
|
|
8
|
+
inputs:
|
|
9
|
+
source:
|
|
10
|
+
description: "Ground-truth source file(s). Repeat by separating paths with newlines."
|
|
11
|
+
required: true
|
|
12
|
+
text:
|
|
13
|
+
description: "AI-generated draft to check."
|
|
14
|
+
required: true
|
|
15
|
+
confidence:
|
|
16
|
+
description: "REVIEW below this confidence."
|
|
17
|
+
required: false
|
|
18
|
+
default: "0.7"
|
|
19
|
+
|
|
20
|
+
runs:
|
|
21
|
+
using: "composite"
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
- name: Install sooth
|
|
27
|
+
shell: bash
|
|
28
|
+
run: python -m pip install --quiet sooth
|
|
29
|
+
- name: Verify draft
|
|
30
|
+
shell: bash
|
|
31
|
+
env:
|
|
32
|
+
SOOTH_SOURCE: ${{ inputs.source }}
|
|
33
|
+
SOOTH_TEXT: ${{ inputs.text }}
|
|
34
|
+
SOOTH_CONFIDENCE: ${{ inputs.confidence }}
|
|
35
|
+
run: bash "$GITHUB_ACTION_PATH/action.sh"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sooth"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Verify AI-generated text against source material. Claim-by-claim trust reports powered by Jev (TypeSafe System One)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Arg-wiring checks for action.sh. No network — a fake `sooth` records its argv.
|
|
3
|
+
# Run: bash tests/test_action.sh
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
|
|
6
|
+
here="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
+
tmp="$(mktemp -d)"
|
|
8
|
+
trap 'rm -rf "$tmp"' EXIT
|
|
9
|
+
|
|
10
|
+
write_fake() {
|
|
11
|
+
cat > "$tmp/sooth" <<'EOF'
|
|
12
|
+
#!/usr/bin/env bash
|
|
13
|
+
printf '%s\n' "$@" > "$ARGV_FILE"
|
|
14
|
+
prev=""
|
|
15
|
+
for a in "$@"; do
|
|
16
|
+
if [ "$prev" = "-o" ]; then echo "# report" > "$a"; fi
|
|
17
|
+
prev="$a"
|
|
18
|
+
done
|
|
19
|
+
exit "${FAKE_STATUS:-0}"
|
|
20
|
+
EOF
|
|
21
|
+
chmod +x "$tmp/sooth"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# argv as one line, plus the same with the dynamic "-o <report>" tail dropped
|
|
25
|
+
argv_full() { tr '\n' ' ' < "$ARGV_FILE"; }
|
|
26
|
+
args_only() { argv_full | sed 's/ -o [^ ]*//'; }
|
|
27
|
+
|
|
28
|
+
export PATH="$tmp:$PATH"
|
|
29
|
+
export ARGV_FILE="$tmp/argv"
|
|
30
|
+
export RUNNER_TEMP="$tmp"
|
|
31
|
+
export SOOTH_TEXT="draft.md"
|
|
32
|
+
export SOOTH_CONFIDENCE="0.75"
|
|
33
|
+
unset GITHUB_STEP_SUMMARY 2>/dev/null || true
|
|
34
|
+
|
|
35
|
+
fail() { echo "FAIL: $*" >&2; exit 1; }
|
|
36
|
+
|
|
37
|
+
write_fake
|
|
38
|
+
|
|
39
|
+
# single source
|
|
40
|
+
export SOOTH_SOURCE="policy.md"
|
|
41
|
+
bash "$here/../action.sh" >/dev/null || fail "single source: exit $?"
|
|
42
|
+
got="$(args_only)"
|
|
43
|
+
want="--format md --source policy.md --text draft.md --confidence 0.75 "
|
|
44
|
+
[ "$got" = "$want" ] || fail "single source argv: got [$got] want [$want]"
|
|
45
|
+
|
|
46
|
+
# multiple sources, newline-separated, blanks ignored
|
|
47
|
+
export SOOTH_SOURCE="a.md
|
|
48
|
+
b.md
|
|
49
|
+
|
|
50
|
+
c.md"
|
|
51
|
+
bash "$here/../action.sh" >/dev/null || fail "multi source: exit $?"
|
|
52
|
+
got="$(args_only)"
|
|
53
|
+
want="--format md --source a.md --source b.md --source c.md --text draft.md --confidence 0.75 "
|
|
54
|
+
[ "$got" = "$want" ] || fail "multi source argv: got [$got] want [$want]"
|
|
55
|
+
|
|
56
|
+
# confidence is optional
|
|
57
|
+
unset SOOTH_CONFIDENCE
|
|
58
|
+
export SOOTH_SOURCE="policy.md"
|
|
59
|
+
bash "$here/../action.sh" >/dev/null || fail "no confidence: exit $?"
|
|
60
|
+
got="$(args_only)"
|
|
61
|
+
want="--format md --source policy.md --text draft.md "
|
|
62
|
+
[ "$got" = "$want" ] || fail "no confidence argv: got [$got] want [$want]"
|
|
63
|
+
|
|
64
|
+
# a FAIL from sooth must fail the step (CI gate), and the report still prints
|
|
65
|
+
export SOOTH_CONFIDENCE="0.7"
|
|
66
|
+
export SOOTH_SOURCE="policy.md"
|
|
67
|
+
export FAKE_STATUS=1
|
|
68
|
+
out="$(bash "$here/../action.sh")"
|
|
69
|
+
status=$?
|
|
70
|
+
[ "$status" -eq 1 ] || fail "exit code not propagated: got $status"
|
|
71
|
+
[ -n "$out" ] || fail "report not printed on failure"
|
|
72
|
+
|
|
73
|
+
# hostile input must arrive as a literal argument and never execute
|
|
74
|
+
export FAKE_STATUS=0
|
|
75
|
+
export SOOTH_TEXT='draft.md; echo PWNED'
|
|
76
|
+
out="$(bash "$here/../action.sh")" || fail "injection: exit $?"
|
|
77
|
+
case "$out" in
|
|
78
|
+
*PWNED*) fail "input was executed as shell" ;;
|
|
79
|
+
esac
|
|
80
|
+
full="$(argv_full)"
|
|
81
|
+
case "$full" in
|
|
82
|
+
*"--text draft.md; echo PWNED "*) : ;;
|
|
83
|
+
*) fail "injection argv: got [$full]" ;;
|
|
84
|
+
esac
|
|
85
|
+
|
|
86
|
+
echo "ok — action.sh arg wiring (5 checks)"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|