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.
Files changed (36) hide show
  1. {sooth-0.2.2 → sooth-0.2.3}/.github/workflows/ci.yml +1 -0
  2. {sooth-0.2.2 → sooth-0.2.3}/PKG-INFO +23 -8
  3. {sooth-0.2.2 → sooth-0.2.3}/README.md +22 -7
  4. sooth-0.2.3/action.sh +29 -0
  5. sooth-0.2.3/action.yml +35 -0
  6. {sooth-0.2.2 → sooth-0.2.3}/pyproject.toml +1 -1
  7. sooth-0.2.3/tests/test_action.sh +86 -0
  8. {sooth-0.2.2 → sooth-0.2.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  9. {sooth-0.2.2 → sooth-0.2.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  10. {sooth-0.2.2 → sooth-0.2.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  11. {sooth-0.2.2 → sooth-0.2.3}/.gitignore +0 -0
  12. {sooth-0.2.2 → sooth-0.2.3}/LICENSE +0 -0
  13. {sooth-0.2.2 → sooth-0.2.3}/docs/DESIGN.md +0 -0
  14. {sooth-0.2.2 → sooth-0.2.3}/docs/DOGFOOD.md +0 -0
  15. {sooth-0.2.2 → sooth-0.2.3}/docs/PRD.md +0 -0
  16. {sooth-0.2.2 → sooth-0.2.3}/docs/TESTING.md +0 -0
  17. {sooth-0.2.2 → sooth-0.2.3}/examples/calibration.json +0 -0
  18. {sooth-0.2.2 → sooth-0.2.3}/examples/calibration.md +0 -0
  19. {sooth-0.2.2 → sooth-0.2.3}/examples/draft.md +0 -0
  20. {sooth-0.2.2 → sooth-0.2.3}/examples/news-1-evil.md +0 -0
  21. {sooth-0.2.2 → sooth-0.2.3}/examples/news-1-output.md +0 -0
  22. {sooth-0.2.2 → sooth-0.2.3}/examples/news-1-summ.md +0 -0
  23. {sooth-0.2.2 → sooth-0.2.3}/examples/news-1.md +0 -0
  24. {sooth-0.2.2 → sooth-0.2.3}/examples/policy.md +0 -0
  25. {sooth-0.2.2 → sooth-0.2.3}/examples/pricing.md +0 -0
  26. {sooth-0.2.2 → sooth-0.2.3}/examples/source.md +0 -0
  27. {sooth-0.2.2 → sooth-0.2.3}/src/sooth/__init__.py +0 -0
  28. {sooth-0.2.2 → sooth-0.2.3}/src/sooth/claims.py +0 -0
  29. {sooth-0.2.2 → sooth-0.2.3}/src/sooth/cli.py +0 -0
  30. {sooth-0.2.2 → sooth-0.2.3}/src/sooth/demo.json +0 -0
  31. {sooth-0.2.2 → sooth-0.2.3}/src/sooth/report.py +0 -0
  32. {sooth-0.2.2 → sooth-0.2.3}/src/sooth/verify.py +0 -0
  33. {sooth-0.2.2 → sooth-0.2.3}/tests/calibrate.py +0 -0
  34. {sooth-0.2.2 → sooth-0.2.3}/tests/conftest.py +0 -0
  35. {sooth-0.2.2 → sooth-0.2.3}/tests/smoke.sh +0 -0
  36. {sooth-0.2.2 → sooth-0.2.3}/tests/test_core.py +0 -0
@@ -19,3 +19,4 @@ jobs:
19
19
  - run: pip install -e ".[dev]"
20
20
  - run: ruff check src tests
21
21
  - run: pytest
22
+ - run: bash tests/test_action.sh
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sooth
3
- Version: 0.2.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
- | 3 | BNBR baru menuntaskan rights issue bernilai besar di harga Rp 33. | ❌ FAIL | ████████ 1.00 | contradicts 1.00 / not_found 0.00 / supports 0.00 · details 0.01 · missing #s: 33 | `examples/news-1.md:25` "Saham ini juga baru menyelesaikan rights issue dalam juml…" |
52
- | 5 | BUMI hanya perlu turun sekitar 10% untuk menyentuh level Rp 50. | ❌ FAIL | ████████ 1.00 | contradicts 1.00 / not_found 0.00 / supports 0.00 · details 0.01 · missing #s: 10 | `examples/news-1.md:23` "Adapun PT Bumi Resources Tbk (BUMI) di sekitar Rp192 haru…" |
53
- | 6 | BEI juga menetapkan batas atas harga saham Rp 5.000 per saham. | ⚠️ REVIEW | ████████ 1.00 | contradicts 0.00 / not_found 1.00 / supports 0.00 · details 0.02 · missing #s: 5.000 | |
54
- | 7 | Para investor ritel sangat senang dengan aturan baru ini. | ➖ UNCHECKABLE | ██░░░░░░ 0.24 | P(checkable)=0.24 | |
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
- Wire it into CI as a quality gate for generated content:
96
+ Use it in CI as a quality gate for generated content:
89
97
 
90
98
  ```yaml
91
99
  - name: Verify AI output
92
- run: sooth --source docs/policy.md --text generated-reply.md
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
- | 3 | BNBR baru menuntaskan rights issue bernilai besar di harga Rp 33. | ❌ FAIL | ████████ 1.00 | contradicts 1.00 / not_found 0.00 / supports 0.00 · details 0.01 · missing #s: 33 | `examples/news-1.md:25` "Saham ini juga baru menyelesaikan rights issue dalam juml…" |
29
- | 5 | BUMI hanya perlu turun sekitar 10% untuk menyentuh level Rp 50. | ❌ FAIL | ████████ 1.00 | contradicts 1.00 / not_found 0.00 / supports 0.00 · details 0.01 · missing #s: 10 | `examples/news-1.md:23` "Adapun PT Bumi Resources Tbk (BUMI) di sekitar Rp192 haru…" |
30
- | 6 | BEI juga menetapkan batas atas harga saham Rp 5.000 per saham. | ⚠️ REVIEW | ████████ 1.00 | contradicts 0.00 / not_found 1.00 / supports 0.00 · details 0.02 · missing #s: 5.000 | |
31
- | 7 | Para investor ritel sangat senang dengan aturan baru ini. | ➖ UNCHECKABLE | ██░░░░░░ 0.24 | P(checkable)=0.24 | |
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
- Wire it into CI as a quality gate for generated content:
73
+ Use it in CI as a quality gate for generated content:
66
74
 
67
75
  ```yaml
68
76
  - name: Verify AI output
69
- run: sooth --source docs/policy.md --text generated-reply.md
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.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