{"id":50746986,"url":"https://github.com/woladi/sententim","last_synced_at":"2026-06-10T22:01:41.619Z","repository":{"id":362051724,"uuid":"1256988752","full_name":"woladi/sententim","owner":"woladi","description":"Deterministyczny weryfikator sygnatur polskich wyroków · MCP · lokalnie · offline · zero LLM w runtime. FOUND / NOT_FOUND / AMBIGUOUS — z twardymi faktami ze źródła publicznego (SAOS). Sub-10ms lookup.","archived":false,"fork":false,"pushed_at":"2026-06-02T10:45:56.000Z","size":458,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-02T12:15:48.370Z","etag":null,"topics":["ai","claude","deterministic","legaltech","llm","local-first","mcp","model-context-protocol","no-llm-runtime","orzecznictwo","polish-law","sad-najwyzszy","saos","sqlite","sygnatura","typescript"],"latest_commit_sha":null,"homepage":"https://github.com/woladi/sententim","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/woladi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-02T09:03:52.000Z","updated_at":"2026-06-02T10:46:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/woladi/sententim","commit_stats":null,"previous_names":["woladi/sententim"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/woladi/sententim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woladi%2Fsententim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woladi%2Fsententim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woladi%2Fsententim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woladi%2Fsententim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/woladi","download_url":"https://codeload.github.com/woladi/sententim/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/woladi%2Fsententim/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34172196,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","claude","deterministic","legaltech","llm","local-first","mcp","model-context-protocol","no-llm-runtime","orzecznictwo","polish-law","sad-najwyzszy","saos","sqlite","sygnatura","typescript"],"created_at":"2026-06-10T22:01:40.409Z","updated_at":"2026-06-10T22:01:41.610Z","avatar_url":"https://github.com/woladi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sententim\n\n**Deterministyczny weryfikator sygnatur polskich wyroków. Zero LLM w runtime. Zero halucynacji.**\n\nSprawdzasz: czy ten wyrok istnieje?\nOtrzymujesz: `FOUND` / `NOT_FOUND` / `AMBIGUOUS` — z twardymi faktami ze źródła.\n\n[![npm version](https://img.shields.io/npm/v/sententim?style=flat-square\u0026color=cb3837\u0026label=npm)](https://www.npmjs.com/package/sententim)\n[![npm types](https://img.shields.io/npm/types/sententim?style=flat-square\u0026color=3178c6)](https://www.npmjs.com/package/sententim)\n[![license](https://img.shields.io/npm/l/sententim?style=flat-square)](LICENSE)\n[![node](https://img.shields.io/node/v/sententim?style=flat-square\u0026color=339933)](package.json)\n[![ci](https://img.shields.io/github/actions/workflow/status/woladi/sententim/ci.yml?branch=main\u0026style=flat-square\u0026label=ci)](https://github.com/woladi/sententim/actions/workflows/ci.yml)\n[![provenance](https://img.shields.io/badge/Sigstore-provenance%20attested-2A6F50?style=flat-square)](https://www.npmjs.com/package/sententim)\n[![MCP](https://img.shields.io/badge/Model_Context_Protocol-1.x-black?style=flat-square)](https://modelcontextprotocol.io)\n\n---\n\n## Po co to istnieje\n\nLLM-y, które piszą o polskim prawie, **konfabulują sygnatury**. *„Sąd Najwyższy, II CSK 999/22 — orzekł, że…\"* — sygnatura nie istnieje, sąd nigdy się nie wypowiedział, model brzmi pewnie.\n\nSententim rozwiązuje **dokładnie ten jeden problem**:\n\n\u003e Zanim zacytujesz sygnaturę — sprawdź, czy ona naprawdę istnieje. Lokalnie. W mikrosekundach. Bez wysyłania niczego do chmury.\n\nReguła naczelna: **jeśli czegoś nie ma w bazie → `NOT_FOUND`. Nigdy nie zgaduj.**\n\n## Czym to NIE jest\n\n- ❌ Nie generuje streszczeń, omówień ani interpretacji\n- ❌ Nie jest alternatywą dla Lex / Legalis — to jedno małe, precyzyjne narzędzie do jednej rzeczy\n- ❌ Nie korzysta z LLM w runtime — w paczce nie ma ani jednego API-call do chmury\n- ❌ Nie indeksuje pełnego tekstu wyroku — FTS5 chodzi tylko po sygnaturach, sądach i podstawie prawnej\n\n## Co jest w paczce\n\n| Pole | Wartość |\n|---|---|\n| **Wersja** | sententim@0.5.x · [pełen CHANGELOG](CHANGELOG.md) |\n| **Domena prawna** | Kredyt konsumencki + frankowy (sankcja KD, klauzule abuzywne, art. 45 ukk + 75c pr.bank) |\n| **Źródła** | SAOS (SR/SO/SA/SN) · CELLAR / EUR-Lex (TSUE polskie wersje wyroków) |\n| **Korpus** | **1348 wyroków** · ~2011 → 2026 |\n| **Rozkład instancji** | SO 721 · SR 459 · SA 96 · SN 57 · TSUE 15 |\n| **DB size** | 1.23 MB · pełen lookup `0.05 – 0.4 ms` |\n| **Toole MCP** | `verify_signature` · `search_judgments` |\n| **Audyt** | Każdy rekord: `zrodlo_url` + `data_pobrania` + `sha256` + (gdy dostępne) `ecli` |\n| **Provenance** | Sigstore SLSA v1 attestation na każdej publikacji npm |\n\n## Quick start\n\n### Claude Code (CLI)\n\n```bash\nclaude mcp add sententim -- npx -y sententim\n```\n\n### Claude Desktop\n\nW `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"sententim\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"sententim\"]\n    }\n  }\n}\n```\n\n### Cursor / Continue / inny klient MCP\n\nTransport: stdio, komenda: `npx -y sententim`.\n\n\u003e **Dlaczego `npx -y sententim` (nie `sententim-mcp`)?** `npx \u003cX\u003e` szuka **pakietu** o nazwie `\u003cX\u003e` w npm registry, nie binarki. Pakiet nazywa się `sententim`. Binarka `sententim` wykrywa kontekst — jeśli stdin to pipe (czyli odpala MCP klient), startuje server stdio. Jeśli stdin to TTY (interaktywny shell), drukuje help. Stary alias `sententim-mcp` dalej działa po `npm install -g`, ale przez `npx` musisz dać pakiet jawnie: `npx -y -p sententim sententim-mcp`.\n\n### Global install (alternatywa, jednorazowa)\n\n```bash\nnpm install -g sententim\nclaude mcp add sententim -- sententim    # binarka na PATH\nsententim verify \"II CSK 750/15\"          # CLI verify\nsententim info                            # manifest bazy\n```\n\n### Z poziomu kodu\n\n```ts\nimport { JudgmentsDb, runVerifySignature, runSearchJudgments } from \"sententim\";\n\nconst db = new JudgmentsDb();              // baza wbudowana w paczkę\n\n// (1) weryfikacja\nrunVerifySignature(db, { sygnatura: \"II CSK 750/15\" });\n//   → { status: \"FOUND\" | \"NOT_FOUND\" | \"AMBIGUOUS\",\n//       matches: JudgmentMatch[], disclaimer }\n\n// (2) wyszukiwanie\nrunSearchJudgments(db, { query: \"apelacyjny Warszawa\", limit: 5 });\n//   → { query, instancja: \"ALL\", total_returned, matches, disclaimer }\n\ndb.close();\n```\n\n### Weryfikacja Sigstore provenance\n\nKażda publikacja na npm jest atestowana przez Sigstore — supply-chain proof, że konkretny tarball powstał z konkretnego commita w `woladi/sententim` przez OIDC-driven GitHub Actions:\n\n```bash\nnpm audit signatures sententim\n# pokaże: signatures: 1 (provenance), ✓ verified\n```\n\n---\n\n## Kontrakty narzędzi MCP\n\n### Tool: `verify_signature`\n\n```ts\ninput: {\n  sygnatura: string;           // np. \"II CSK 750/15\"\n  sad?:      string;           // zawęża po substringu nazwy sądu\n  data?:     string;           // zawęża po dokładnej dacie ISO YYYY-MM-DD\n}\n\noutput: {\n  status:  \"FOUND\" | \"NOT_FOUND\" | \"AMBIGUOUS\",\n  matches: JudgmentMatch[],\n  disclaimer: \"Dane deterministyczne ze źródła publicznego. Zweryfikuj treść w źródle. Nie stanowi porady prawnej.\"\n}\n```\n\n| status | znaczenie | matches |\n|---|---|---|\n| `FOUND` | dokładnie jedno trafienie | `[{...}]` |\n| `NOT_FOUND` | zero trafień — **nie cytuj tej sygnatury** | `[]` |\n| `AMBIGUOUS` | ta sama sygnatura w ≥2 sądach — zwracamy wszystkich kandydatów, **bez wybierania** | `[{...}, {...}, …]` |\n\n### Tool: `search_judgments`\n\nFTS5 po sygnaturze, nazwie sądu i podstawie prawnej. Akcento-niewrażliwa (`unicode61 remove_diacritics=2`), naiwna na polską morfologię (`Warszawa` znajduje `Warszawie` przez stem trimming).\n\n```ts\ninput: {\n  query:     string;           // multi-token AND, np. \"apelacyjny Warszawa\"\n  instancja?: \"SR\"|\"SO\"|\"SA\"|\"SN\"|\"NSA\"|\"WSA\"|\"TK\"|\"TSUE\";\n  limit?:    number;           // 1-50, default 10\n}\n\noutput: {\n  query: string,\n  instancja: \"SR\"|\"SO\"|\"SA\"|\"SN\"|\"NSA\"|\"WSA\"|\"TK\"|\"TSUE\"|\"ALL\",\n  total_returned: number,\n  matches: JudgmentMatch[],\n  disclaimer: string\n}\n```\n\n**Ważne**: w search wciąż obowiązuje reguła naczelna. `total_returned: 0` ≠ \"wyrok nie istnieje\" — to \"nie ma w tej bazie\". Nie cytuj na podstawie braku trafień.\n\n## Schemat danych\n\n```ts\ntype Judgment = {\n  sygnatura:       string;                    // \"II CSK 750/15\"\n  sygnatura_norm:  string;                    // matchowanie: upper-case, bez kropek, ASCII\n  sad:             string;                    // \"Sąd Rejonowy w Olsztynie\"\n  instancja:       \"SR\"|\"SO\"|\"SA\"|\"SN\"|\"NSA\"|\"WSA\"|\"TK\"|\"TSUE\";\n  data_orzeczenia: string;                    // ISO YYYY-MM-DD\n  sentencja_typ:   \"oddala\"|\"uwzglednia\"|\"uchyla_przekazuje\"|\"zmienia\"|\"umarza\"|\"inne\"|null;\n  prawomocny:      0|1|null;                  // SA/SN/NSA/TK/TSUE → 1 by construction; SR/SO via cross-ref\n  uchylony_przez:  string|null;               // backfilled przez cross-ref pass (rzadko na narrow corpus)\n  podstawa_prawna: string[];                  // [\"art. 45 ukk\", \"art. 75c pr.bank\"]\n  zrodlo_url:      string;\n  data_pobrania:   string;                    // ISO timestamp\n  sha256:          string;                    // hash surowego textContent (audyt)\n};\n```\n\n`JudgmentMatch` (zwracany przez oba toole MCP) to projekcja `Judgment` bez `sygnatura_norm` i `sha256` — pola audytowe nie wyciekają przez MCP.\n\nKażde pole pochodzi z deterministycznej ekstrakcji — pełna lista parserów: `scripts/etl/parsers/`.\n\n## Architektura\n\n```\n                                         (one-shot, ~15-20 min, lokalnie u devy)\n    SAOS REST API ──── seed.ts ─────┐\n                                    │\n                                    ▼\n                            data/judgments.db                ← committed do repo,\n                            (~1300 wierszy, FTS5)              shipped w paczce npm\n                                    │\n                                    │ better-sqlite3 (sync, PRAGMA query_only=1)\n                                    ▼\n                            sententim-mcp · stdio            ← runtime: 0 LLM, 0 sieci\n                                    │\n                            ┌───────┴────────┐\n                            ▼                ▼\n                    verify_signature   search_judgments\n                            │                │\n                            ▼                ▼\n    FOUND/NOT_FOUND/AMBIGUOUS/OUT_OF_SCOPE  ranked matches\n```\n\n| Komponent | Stack |\n|---|---|\n| Schema | SQLite + FTS5 (`tokenize=\"unicode61 remove_diacritics 2\"`) |\n| Runtime | better-sqlite3 (sync), prepared statements, PRAGMA query_only=1 |\n| MCP | @modelcontextprotocol/sdk 1.x, stdio transport |\n| ETL | TypeScript pure-fn — zero LLM, zero zewnętrznych API poza SAOS |\n| CI/CD | GitHub Actions · npm Trusted Publishing (OIDC) · Sigstore provenance |\n\n## Limity i znane luki\n\n- **SAOS-owy SN** zamrożony na **2016-06-22** (CeON przestał ingestować z sn.pl). W korpusie mamy 57 wyroków SN do tej daty z domeny kredytu konsumenckiego / klauzul abuzywnych. Roadmap v0.6: scraper sn.pl dla post-2016 SN.\n- **TSUE** — pokryte hand-curated listą 15 najważniejszych orzeczeń dla domeny (consumer credit Directive 2008/48 + klauzule abuzywne D.93/13). Roadmap v0.6: rozszerzyć przez CELLAR SPARQL + EUROVOC concept code, gdy zweryfikujemy go dla \"kredyt konsumencki\".\n- **`prawomocny`**: SA/SN/NSA/TK/TSUE → `1` z definicji; SR/SO → `1` tylko gdy w korpusie istnieje appellate ze `sentencja_typ=oddala` referujące tę sygnaturę; inaczej `NULL`. Na korpusie v0.5 (1348 rekordów) → 169 by-instance + 19 by-cross-ref = **188 prawomocnych**, 1160 NULL.\n- **`uchylony_przez`** — backfilluje cross-ref pass na podstawie wzorca \"sygn. akt X\" w textContent appellate'ów `uchyla_przekazuje`. Na korpusie v0.5 = **4 trafienia** (z 0 w v0.4 dzięki rozszerzeniu o SN-owe powołania).\n- **`sentencja_typ` `NULL` ~31%** — świadomie zamiast zgadywać `'inne'`. Najczęściej compound rulings (\"uchyla w części, w pozostałej oddala\") które wymagają mocniejszej heurystyki.\n- **`search_judgments`** — stem-aware ale nie pełna morfologia. `Warszawa→Warszaw*` łapie \"Warszawie/Warszawy\", ale rzadkie odmiany mogą umknąć.\n- **`search_judgments` nie szuka po pełnym tekście** wyroku — FTS5 indeksuje tylko `(sygnatura, sygnatura_norm, podstawa_prawna, sad)`. Pełen tekst nie ląduje w bazie (sha256 jako audyt). Pytanie typu \"RODO\" znajdzie tylko gdy \"RODO\" jest w `podstawa_prawna`.\n- **TSUE `data_orzeczenia` to rok-styczeń-1** — CELLAR HTML nie udostępnia daty w machine-readable miejscu, więc stamping na `YYYY-01-01` (gdzie `YYYY` to rok z CELEX-u). Realna data wymaga parsowania HTML body — roadmap v0.6.\n- **Daty filtrowane** do zakresu `1990-01-01 ... dzisiaj+1d` (literówki w źródle typu „3013-…\" są odrzucane).\n\n## Roadmap\n\n- **v0.1** — `verify_signature`, sankcja kredytu darmowego, SAOS COMMON.\n- **v0.2** — `search_judgments` (FTS5), prawomocny heurystyka + cross-ref pass dla SR/SO, OIDC Trusted Publishing.\n- **v0.3** — `npx -y sententim` smart-entry (binarka detect MCP/CLI).\n- **v0.4** — Nowy status `OUT_OF_SCOPE` + heurystyka klasyfikacji wzorca SN/TSUE/NSA/TK, sanitiser FTS5 / rok 4-cyfrowy / stem-aware filtr `sad`.\n- **v0.5** — **SN (SAOS-owy, do 2016-06-22) + TSUE (curated 15 spraw)**. Schema: opcjonalne `ecli`. Korpus 1348 wyroków · [\"SR\",\"SO\",\"SA\",\"SN\",\"TSUE\"]. *Tu jesteś.*\n- **v0.6** — Scraper sn.pl dla post-2016 SN + CELLAR SPARQL+EUROVOC do automatycznego rozszerzania TSUE + real `data_orzeczenia` z TSUE HTML.\n\nStreszczenia LLM — **tylko z human-in-the-loop i flagą provenance**, **nigdy** w default-path.\n\n## Development\n\n```bash\npnpm install              # patrz: native build niżej\npnpm typecheck\npnpm lint\npnpm test                 # 66 testów, wszystko in-memory (bez sieci)\n\npnpm etl:seed             # ~15-20 min, lokalnie, produkuje data/judgments.db\npnpm etl:seed --max=50    # smoke (~30s, nie produkuje ship-grade DB)\npnpm etl:seed --skip-fetch # rebuild DB z istniejących raw JSONL\npnpm etl:verify           # pre-publish gate (PRAGMA query_only + latencja)\npnpm build                # → dist/ (ESM + .d.ts + maps)\n```\n\n### Native build (better-sqlite3)\n\n`pnpm 11` blokuje domyślnie buildy natywne. Przy pierwszym `pnpm install` może pojawić się ostrzeżenie `ERR_PNPM_IGNORED_BUILDS`. Jednorazowy fix:\n\n```bash\npnpm install --config.dangerouslyAllowAllBuilds=true\n# albo\npnpm approve-builds        # interaktywnie zaakceptuj: better-sqlite3, esbuild, @biomejs/biome\n```\n\nPo skompilowaniu `.node` binary (~25s na Apple Silicon), kolejne `pnpm install` już nie wymagają flagi. To samo dotyczy CI — workflow'y używają `--config.dangerouslyAllowAllBuilds=true`.\n\n### Audyt determinizmu\n\nKażdy wiersz w bazie ma `zrodlo_url` + `data_pobrania` + `sha256(textContent)`. Weryfikacja, że nasze pola pochodzą z tych bajtów:\n\n```bash\n# Bierzemy losowy rekord:\nnode -e \"const D=require('better-sqlite3'); const db=new D('data/judgments.db',{readonly:true}); console.log(db.prepare('SELECT zrodlo_url, sha256 FROM judgments ORDER BY RANDOM() LIMIT 1').get())\"\n# Pobieramy źródło, hashujemy textContent, porównujemy:\ncurl -s \"\u003czrodlo_url\u003e\" | jq -r .textContent | shasum -a 256\n```\n\n### Release (OIDC Trusted Publishing)\n\nPublikacja na npm leci automatycznie z GitHub Actions, **bez `NPM_TOKEN`**.\n\n1. Dodaj `.changeset/\u003copis\u003e.md` (lub `pnpm changeset`):\n   ```md\n   ---\n   \"sententim\": patch | minor | major\n   ---\n   Krótki opis zmiany.\n   ```\n2. `git push origin main` → `release.yml` otwiera (lub aktualizuje) PR **\"Version Packages\"** który bumpuje `package.json` + dopisuje wpis do `CHANGELOG.md`.\n3. Merge PR → `release.yml` ponownie się odpala. Tym razem nie ma pending changesets, więc `changesets/action` woła `pnpm release` (`= changeset publish` `= npm publish`). npm CLI wykrywa OIDC w runnerze (`id-token: write` + `actions/setup-node` z `registry-url`), wymienia token GitHub na krótkotrwały token publikacji npm i wysyła tarball z **Sigstore provenance** (włączone przez `publishConfig.provenance: true`).\n4. Bez sekretów `NPM_TOKEN`. Bez ręcznego `npm login`. Atestacja widoczna na stronie pakietu w npm.\n\nPre-req jednorazowy (web UI): konfiguracja Trusted Publishera na npmjs.com pod `Owner=woladi · Repo=sententim · Workflow=release.yml`.\n\n### Layout\n\n```\nsententim/\n├── src/\n│   ├── index.ts                · stdio MCP entry + public API exports\n│   ├── server.ts               · MCP server (verify_signature + search_judgments)\n│   ├── db.ts                   · JudgmentsDb (PRAGMA query_only=1, FTS5)\n│   ├── normalize.ts            · displaySignature + normaliseSignature\n│   ├── types.ts                · Judgment, VerifyResult, Manifest, JudgmentMatch\n│   ├── cli.ts                  · `sententim info` / `sententim verify`\n│   └── tools/\n│       ├── verify-signature.ts · FOUND / NOT_FOUND / AMBIGUOUS\n│       └── search-judgments.ts · FTS5-backed search\n├── scripts/etl/\n│   ├── parsers/\n│   │   ├── sentencja-typ.ts    · regex outcome classifier\n│   │   ├── podstawa-prawna.ts  · regex legal-basis extractor\n│   │   ├── sad-instancja.ts    · court → SR/SO/SA/SN/...\n│   │   └── cross-ref.ts        · sygn. akt X regex (prawomocny + uchylony_przez)\n│   ├── sources/\n│   │   ├── saos.ts             · SAOS REST API client\n│   │   └── cjeu.ts             · gated SENTENTIM_ENABLE_CJEU (deferred)\n│   ├── normalize.ts            · raw SAOS → canonical + cross-ref pass\n│   ├── build-db.ts             · staged JSONL → SQLite + manifest\n│   ├── seed.ts                 · unia 2 queries SAOS\n│   └── verify.ts               · prepublish gate\n├── data/\n│   ├── schema.sql              · DDL (committed)\n│   ├── judgments.db            · published artefact\n│   └── manifest.json           · published artefact\n├── tests/                      · 66 vitest tests\n│   ├── normalize.test.ts\n│   ├── parsers.test.ts\n│   ├── cross-ref.test.ts\n│   ├── db.test.ts\n│   ├── verify-contract.test.ts\n│   └── search-judgments.test.ts\n└── .github/workflows/\n    ├── ci.yml                  · typecheck · lint · test · build\n    └── release.yml             · changesets → OIDC → npm + Sigstore\n```\n\n## License\n\n[MIT](LICENSE) © Adrian Wołczuk. Data-source attribution: [NOTICE](NOTICE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwoladi%2Fsententim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwoladi%2Fsententim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwoladi%2Fsententim/lists"}