mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-12 03:03:23 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b847406dc | ||
|
|
613a196501 | ||
|
|
ef0c55c40f |
@@ -1,4 +1,4 @@
|
|||||||
**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md)
|
**Language:** English | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md) | [Deutsch](docs/de-DE/README.md)
|
||||||
|
|
||||||
# ECC
|
# ECC
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md)
|
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md)
|
||||||
| [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md)
|
| [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md) | [Deutsch](docs/de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md)
|
[**English**](README.md) | [Português (Brasil)](docs/pt-BR/README.md) | [简体中文](README.zh-CN.md) | [繁體中文](docs/zh-TW/README.md) | [日本語](docs/ja-JP/README.md) | [한국어](docs/ko-KR/README.md) | [Türkçe](docs/tr/README.md) | [Русский](docs/ru/README.md) | [Tiếng Việt](docs/vi-VN/README.md) | [ไทย](docs/th/README.md) | [Deutsch](docs/de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
67
docs/de-DE/GLOSSARY.md
Normal file
67
docs/de-DE/GLOSSARY.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Glossar / Glossary
|
||||||
|
|
||||||
|
Einheitliches Terminologie-Glossar für die deutsche (de-DE) Übersetzung von ECC.
|
||||||
|
|
||||||
|
Leitlinie: Etablierte englische Fachbegriffe und ECC-Oberflächennamen (`agents/`, `skills/`,
|
||||||
|
`commands/`, `hooks/`, `rules/`) bleiben **englisch** — sie sind im deutschsprachigen
|
||||||
|
Entwickleralltag Standard und entsprechen Verzeichnis-/Befehlsnamen im Repo. Begriffe mit
|
||||||
|
einer klaren, gebräuchlichen deutschen Entsprechung werden **übersetzt**.
|
||||||
|
|
||||||
|
| English | Deutsch | Notiz |
|
||||||
|
|---------|---------|-------|
|
||||||
|
| Agent | Agent | bleibt englisch — ECC-Oberfläche (`agents/`) |
|
||||||
|
| Skill | Skill | bleibt englisch — ECC-Oberfläche (`skills/`) |
|
||||||
|
| Hook | Hook | bleibt englisch — ECC-Oberfläche (`hooks/`) |
|
||||||
|
| Command | Command | bleibt englisch als ECC-Oberfläche (`commands/`); generisch sonst „Befehl“ |
|
||||||
|
| Rule | Rule | bleibt englisch als ECC-Oberfläche (`rules/`); generisch sonst „Regel“ |
|
||||||
|
| Harness | Harness | bleibt englisch — keine etablierte deutsche Entsprechung |
|
||||||
|
| Instinct | Instinct | bleibt englisch — ECC-Begriff aus Continuous Learning |
|
||||||
|
| Plugin | Plugin | bleibt englisch |
|
||||||
|
| Marketplace | Marketplace | bleibt englisch — Anthropic-Produktbegriff |
|
||||||
|
| Worktree | Worktree | bleibt englisch — Git-Fachbegriff |
|
||||||
|
| Subagent | Subagent | bleibt englisch |
|
||||||
|
| Frontmatter | Frontmatter | bleibt englisch; YAML-Feldnamen bleiben englisch |
|
||||||
|
| Continuous Learning | Continuous Learning | ECC-Feature-Name bleibt englisch; beschreibend „kontinuierliches Lernen“ |
|
||||||
|
| Memory | Memory | als ECC-Konzept englisch; generisch „Speicher“ |
|
||||||
|
| Context window | Kontextfenster | |
|
||||||
|
| Token | Token | |
|
||||||
|
| Coverage | Coverage | „Testabdeckung“, wo beschreibend |
|
||||||
|
| Test-Driven Development | testgetriebene Entwicklung | Kürzel TDD beibehalten |
|
||||||
|
| Code review | Code-Review | |
|
||||||
|
| Refactoring | Refactoring | |
|
||||||
|
| Pull request | Pull Request | |
|
||||||
|
| Commit | Commit | |
|
||||||
|
| Branch | Branch | |
|
||||||
|
| Merge | Merge / zusammenführen | je nach Kontext |
|
||||||
|
| Build | Build | |
|
||||||
|
| Deploy | Deployment / deployen | |
|
||||||
|
| Pipeline | Pipeline | |
|
||||||
|
| Orchestration | Orchestrierung | |
|
||||||
|
| Repository | Repository | kurz „Repo“ zulässig |
|
||||||
|
| Dependency | Abhängigkeit | |
|
||||||
|
| Edge case | Grenzfall | |
|
||||||
|
| Best practice | Best Practice | |
|
||||||
|
| Anti-pattern | Anti-Pattern | |
|
||||||
|
| Middleware | Middleware | |
|
||||||
|
| Endpoint | Endpoint | |
|
||||||
|
| Schema | Schema | |
|
||||||
|
| Payload | Payload | |
|
||||||
|
| Callback | Callback | |
|
||||||
|
| Checkpoint | Checkpoint | |
|
||||||
|
| Linter | Linter | |
|
||||||
|
| Formatter | Formatter | |
|
||||||
|
| Staging | Staging | |
|
||||||
|
| Production | Produktion / Produktivumgebung | je nach Kontext |
|
||||||
|
| Debugging | Debugging | |
|
||||||
|
| Logging | Logging | |
|
||||||
|
| Monitoring | Monitoring | |
|
||||||
|
| Rate limit | Rate-Limit | |
|
||||||
|
| Retry | Retry / Wiederholung | |
|
||||||
|
| Fallback | Fallback | |
|
||||||
|
| Graceful degradation | Graceful Degradation | |
|
||||||
|
| Sandboxing | Sandboxing | |
|
||||||
|
| Sanitization | Sanitisierung | |
|
||||||
|
| Selective install | selektive Installation | |
|
||||||
|
| Profile | Profil | Installationsprofil |
|
||||||
|
| Component | Komponente | Installationskomponente |
|
||||||
|
| Module | Modul | Installationsmodul |
|
||||||
1762
docs/de-DE/README.md
Normal file
1762
docs/de-DE/README.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
**言語:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
**言語:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
# Everything Claude Code
|
# Everything Claude Code
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
**言語 / Language / 語言 / Dil / Язык / Ngôn ngữ**
|
**言語 / Language / 語言 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
**언어:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | 한국어 | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
**언어:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | 한국어 | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
# Everything Claude Code
|
# Everything Claude Code
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
**Language / 语言 / 語言 / 언어 / Dil / Язык / Ngôn ngữ**
|
**Language / 语言 / 語言 / 언어 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
**Idioma:** [English](../../README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | Português (Brasil) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
**Idioma:** [English](../../README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | Português (Brasil) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
# Everything Claude Code
|
# Everything Claude Code
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
**Idioma / Language / 语言 / Dil / Язык / Ngôn ngữ**
|
**Idioma / Language / 语言 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](../../README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Português (Brasil)](README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
[**English**](../../README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Português (Brasil)](README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
**Язык:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | **Русский** | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
**Язык:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | **Русский** | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
# Everything Claude Code
|
# Everything Claude Code
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
**Язык / 语言 / 語言 / Dil / Ngôn ngữ**
|
**Язык / 语言 / 語言 / Dil / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | **Русский** | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | **Русский** | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
**ภาษา:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | **ไทย**
|
**ภาษา:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | **ไทย** | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
# Everything Claude Code
|
# Everything Claude Code
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
**ภาษา / Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
**ภาษา / Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | **ไทย**
|
[English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | **ไทย** | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
**Dil / Language / 语言 / 語言 / Язык / Ngôn ngữ**
|
**Dil / Language / 语言 / 語言 / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [**Türkçe**](README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [**Türkçe**](README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
**Ngôn ngữ:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | **Tiếng Việt** | [ไทย](../th/README.md)
|
**Ngôn ngữ:** [English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | **Tiếng Việt** | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
# Everything Claude Code
|
# Everything Claude Code
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
**Ngôn ngữ / Language / 语言 / 語言 / Dil / Язык**
|
**Ngôn ngữ / Language / 语言 / 語言 / Dil / Язык**
|
||||||
|
|
||||||
[English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | **Tiếng Việt** | [ไทย](../th/README.md)
|
[English](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | [繁體中文](../zh-TW/README.md) | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | **Tiếng Việt** | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
**Language / 语言 / 語言 / Dil / Язык / Ngôn ngữ**
|
||||||
|
|
||||||
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | **繁體中文** | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md)
|
[**English**](../../README.md) | [Português (Brasil)](../pt-BR/README.md) | [简体中文](../../README.zh-CN.md) | **繁體中文** | [日本語](../ja-JP/README.md) | [한국어](../ko-KR/README.md) | [Türkçe](../tr/README.md) | [Русский](../ru/README.md) | [Tiếng Việt](../vi-VN/README.md) | [ไทย](../th/README.md) | [Deutsch](../de-DE/README.md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,126 +0,0 @@
|
|||||||
# AURA trust-check adapter
|
|
||||||
|
|
||||||
Opt-in, **read-only** counterparty reputation for agent hosts. One HTTP GET
|
|
||||||
answers *"can I trust this agent before I delegate work or settle a payment?"*
|
|
||||||
|
|
||||||
- **Zero dependencies** — pure Python stdlib. Vendor the `aura/` folder, no `pip install`.
|
|
||||||
- **Read-only** — the only network call is `GET /check?did=...`. No auth, no API key.
|
|
||||||
- **No coupling** — does not sign, hold keys, move funds, or touch your wallet.
|
|
||||||
- **Off by default** — nothing runs until you call it. Disabled = delete the import.
|
|
||||||
|
|
||||||
## Enable (opt-in)
|
|
||||||
|
|
||||||
It's a gate you call explicitly at a trust boundary — there is no global hook,
|
|
||||||
no monkey-patching, no background calls. Wrap the action you want to protect:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from aura import before_settle, AuraUntrusted
|
|
||||||
|
|
||||||
def settle(counterparty_did: str, amount: float) -> None:
|
|
||||||
try:
|
|
||||||
before_settle(counterparty_did) # rejects high_risk + unknown
|
|
||||||
except AuraUntrusted as e:
|
|
||||||
log.warning("blocked: %s", e)
|
|
||||||
return # your policy decides what to do
|
|
||||||
pay(counterparty_did, amount) # your existing logic, untouched
|
|
||||||
```
|
|
||||||
|
|
||||||
Prefer to read the verdict yourself instead of raising?
|
|
||||||
|
|
||||||
```python
|
|
||||||
from aura import aura_verdict
|
|
||||||
|
|
||||||
v = aura_verdict(counterparty_did)
|
|
||||||
print(v.verdict) # trusted | caution | high_risk | new | unknown
|
|
||||||
print(v.reason) # human-readable explanation
|
|
||||||
print(v.score) # composite 0..1, or None when there's no history
|
|
||||||
print(v.ok) # True for trusted/caution
|
|
||||||
|
|
||||||
# v.dimensions tells you *which* axis is weak, not just the aggregate:
|
|
||||||
if v.dimensions and v.dimensions.get("financial_integrity", 1) < 0.4:
|
|
||||||
require_manual_review() # placeholder for your own policy
|
|
||||||
```
|
|
||||||
|
|
||||||
> `v.ok` reflects the *verdict class* (True for `trusted`/`caution`), not the
|
|
||||||
> outcome of `require_trust()` — the gate's default `allow` also lets `new`
|
|
||||||
> through. Use the gate's return/raise for the decision, `v.ok` for display.
|
|
||||||
|
|
||||||
## Verdicts
|
|
||||||
|
|
||||||
| verdict | meaning | `ok` |
|
|
||||||
|---|---|---|
|
|
||||||
| `trusted` | strong on-chain track record (composite ≥ 0.70) | ✅ |
|
|
||||||
| `caution` | mixed history (0.40–0.70) | ✅ |
|
|
||||||
| `high_risk` | poor track record (< 0.40) | ❌ |
|
|
||||||
| `new` | registered identity, no interactions yet | ❌ |
|
|
||||||
| `unknown` | no track record — or AURA was unreachable | ❌ |
|
|
||||||
|
|
||||||
## Policy knobs
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Reject brand-new agents too (strict):
|
|
||||||
before_settle(did, allow=("trusted", "caution"))
|
|
||||||
|
|
||||||
# Treat an *unreachable* AURA as a pass (fail-open). Off by default —
|
|
||||||
# absence of evidence is not evidence of trust.
|
|
||||||
before_settle(did, fail_open=True)
|
|
||||||
|
|
||||||
# Point at a self-hosted / staging gateway:
|
|
||||||
before_settle(did, base_url="https://my-aura-mirror.example", timeout=5)
|
|
||||||
```
|
|
||||||
|
|
||||||
`require_trust` is an alias of `before_settle` for non-payment call sites.
|
|
||||||
|
|
||||||
## Failure behavior
|
|
||||||
|
|
||||||
`aura_verdict()` **never raises on a network or parse error** — it returns an
|
|
||||||
`unknown` verdict with the reason set. The gate then decides:
|
|
||||||
|
|
||||||
- **default (`fail_open=False`)** — `unknown` is rejected → an unreachable AURA
|
|
||||||
blocks the action. *Fail-closed.*
|
|
||||||
- **`fail_open=True`** — `unknown` from an unreachable endpoint is allowed
|
|
||||||
through, so AURA can never take your flow down. *Fail-open.*
|
|
||||||
|
|
||||||
This keeps the trust signal **purely additive**: if you remove the adapter or
|
|
||||||
AURA is down, your existing allow/deny logic runs exactly as before.
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
Offline — every call replays a recorded `/check` body, no network:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python -m pytest aura/tests -q
|
|
||||||
```
|
|
||||||
|
|
||||||
Covers all five verdict classes, the gate's allow-list + `fail_open`, the
|
|
||||||
unreachable path, and input validation. See `tests/fixtures.py` for the
|
|
||||||
recorded response shapes.
|
|
||||||
|
|
||||||
## Boundary & threats
|
|
||||||
|
|
||||||
See [THREAT_MODEL.md](./THREAT_MODEL.md) — what the verdict does and does not
|
|
||||||
prove, and the failure modes a verifier should account for.
|
|
||||||
|
|
||||||
## Carry the AURA badge
|
|
||||||
|
|
||||||
Show your live trust verdict in your own README — it updates automatically and
|
|
||||||
links back to your AURA profile:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
[](https://agent.auraopenprotocol.org/check?did=YOUR_DID)
|
|
||||||
```
|
|
||||||
|
|
||||||
A shields-style badge colored by verdict (`trusted` green, `caution` amber,
|
|
||||||
`high_risk` red, `new` blue, `unknown` grey). Add `&score=1` to show the
|
|
||||||
composite score. No DID yet? The bare badge is a generic mark:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
[](https://auraopenprotocol.org)
|
|
||||||
```
|
|
||||||
|
|
||||||
## What's behind the verdict
|
|
||||||
|
|
||||||
[AURA Open Protocol](https://auraopenprotocol.org) — W3C DID identity plus 8
|
|
||||||
on-chain reputation dimensions on Base L2 (`task_completion`, `delivery_speed`,
|
|
||||||
`output_quality`, `honesty`, `financial_integrity`, `security_compliance`,
|
|
||||||
`collaboration`, `dispute_history`). Docs: https://dev.auraopenprotocol.org
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# Threat model — AURA trust-check adapter
|
|
||||||
|
|
||||||
A short, honest boundary statement. The verdict is **one backward-looking
|
|
||||||
signal**, not a security guarantee. Read this before treating `trusted` as a
|
|
||||||
green light for anything irreversible.
|
|
||||||
|
|
||||||
## What the verdict proves
|
|
||||||
|
|
||||||
- The DID has (or lacks) an on-chain interaction history on AURA, summarized
|
|
||||||
into a composite score and per-dimension breakdown.
|
|
||||||
- It is **backward-looking**: a statement about past recorded behavior, not a
|
|
||||||
prediction or an authorization for the *current* proposed action.
|
|
||||||
|
|
||||||
## What it explicitly does NOT prove
|
|
||||||
|
|
||||||
- **Not action-safety.** A `trusted` agent can still propose a malicious or
|
|
||||||
buggy transaction. Pair this with a forward-looking action-risk check
|
|
||||||
(contract simulation, policy engine) and keep the two signals separate so
|
|
||||||
the policy decision stays auditable.
|
|
||||||
- **Not execution quality.** It says nothing about whether *this* call will
|
|
||||||
succeed.
|
|
||||||
- **Not identity proof of the live caller.** It checks a DID's reputation, not
|
|
||||||
that the entity you're talking to controls that DID (see "Spoofed DID").
|
|
||||||
|
|
||||||
## Failure modes a caller must account for
|
|
||||||
|
|
||||||
| # | Threat | Mitigation in this adapter | Residual risk owned by caller |
|
|
||||||
|---|---|---|---|
|
|
||||||
| 1 | **Endpoint unreachable / timeout** | Returns `unknown` (never raises). Gate is fail-closed by default. | Choose `fail_open` deliberately; pick a sane `timeout`. |
|
|
||||||
| 2 | **Spoofed DID** — caller claims a DID it doesn't control | Out of scope: adapter checks reputation, not control of the key. | Verify DID control (signature challenge / auth) **before** trusting the verdict. |
|
|
||||||
| 3 | **Stale verdict** — score lags very recent bad behavior | Each call is live (no caching here). | If you cache the result, bound the TTL; don't reuse a verdict across sessions. |
|
|
||||||
| 4 | **Endpoint MITM / response tampering** | HTTPS to a pinned host (`agent.auraopenprotocol.org`). Verdict strings are validated against a fixed allow-list; unknown values collapse to `unknown`. | Don't point `base_url` at an untrusted mirror. Consider TLS pinning if your runtime supports it. |
|
|
||||||
| 5 | **Score gaming / Sybil** — cheap DIDs farming a `trusted` score | Inherited from AURA's on-chain cost + dispute dimension; not solvable in the adapter. | Weight `dimensions` (e.g. require non-trivial `interactions` / `dispute_history`) for high-value actions rather than trusting the aggregate alone. |
|
|
||||||
| 6 | **Over-trust** — using the verdict as sole gate for irreversible value | `new`/`unknown` rejected by default; `dimensions` exposed. | For high-value settlement, combine with action-risk + escrow + manual review. |
|
|
||||||
|
|
||||||
## Data handled
|
|
||||||
|
|
||||||
- **Sent:** only the counterparty DID, as a query parameter to `/check`. No
|
|
||||||
PII, no payloads, no secrets, no keys.
|
|
||||||
- **Stored:** nothing. The adapter is stateless; it holds the DID only for the
|
|
||||||
duration of the call.
|
|
||||||
- **Received:** the public `/check` JSON body. Surfaced verbatim on `.raw`.
|
|
||||||
|
|
||||||
## Trust boundary summary
|
|
||||||
|
|
||||||
```
|
|
||||||
your host --(DID only, HTTPS GET)--> AURA /check --> verdict
|
|
||||||
| |
|
|
||||||
| forward-looking action-risk check (separate, yours) |
|
|
||||||
v v
|
|
||||||
policy decision (auditable, your code)
|
|
||||||
```
|
|
||||||
|
|
||||||
The adapter sits on the read-only reputation edge. Signing, fund movement,
|
|
||||||
and the final allow/deny decision stay in your code, where they can be audited.
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
"""
|
|
||||||
AURA trust-check adapter — opt-in, read-only counterparty reputation.
|
|
||||||
|
|
||||||
from aura import before_settle, AuraUntrusted
|
|
||||||
|
|
||||||
try:
|
|
||||||
before_settle(counterparty_did)
|
|
||||||
settle_payment(counterparty_did, amount)
|
|
||||||
except AuraUntrusted as e:
|
|
||||||
abort(str(e))
|
|
||||||
|
|
||||||
Zero dependencies (pure stdlib). Does not sign, hold keys, or move funds.
|
|
||||||
See README.md for the enable section and THREAT_MODEL.md for the boundary.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .adapter import (
|
|
||||||
DEFAULT_ALLOW,
|
|
||||||
DEFAULT_BASE_URL,
|
|
||||||
AuraUntrusted,
|
|
||||||
AuraVerdict,
|
|
||||||
aura_verdict,
|
|
||||||
before_settle,
|
|
||||||
require_trust,
|
|
||||||
)
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"aura_verdict",
|
|
||||||
"before_settle",
|
|
||||||
"require_trust",
|
|
||||||
"AuraVerdict",
|
|
||||||
"AuraUntrusted",
|
|
||||||
"DEFAULT_BASE_URL",
|
|
||||||
"DEFAULT_ALLOW",
|
|
||||||
]
|
|
||||||
|
|
||||||
__version__ = "0.1.0"
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
"""
|
|
||||||
AURA trust-check adapter — a zero-dependency, read-only reputation lookup.
|
|
||||||
|
|
||||||
Drop this module into any agent/host project to gate a sensitive action
|
|
||||||
(settlement, delegation, tool execution) behind a backward-looking trust
|
|
||||||
verdict for the *counterparty* agent. It does NOT sign, hold keys, move
|
|
||||||
funds, or touch your wallet. It makes one HTTP GET and returns a verdict.
|
|
||||||
|
|
||||||
Design boundary (intentional):
|
|
||||||
- read-only: the only network call is GET /check?did=...
|
|
||||||
- no auth: /check is a public endpoint; no API key, no secret
|
|
||||||
- no coupling: pure stdlib (urllib). No third-party imports, no SDK.
|
|
||||||
- fail-closed: on network failure the verdict is `unknown`, and the
|
|
||||||
default gate (before_settle) rejects `unknown` — so an
|
|
||||||
unreachable AURA never silently waves a counterparty
|
|
||||||
through. Flip `fail_open=True` to invert that.
|
|
||||||
|
|
||||||
Public API:
|
|
||||||
aura_verdict(did) -> AuraVerdict (never raises on network)
|
|
||||||
before_settle(did, allow=...) -> AuraVerdict (raises AuraUntrusted)
|
|
||||||
require_trust = before_settle (alias)
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import json
|
|
||||||
import urllib.error
|
|
||||||
import urllib.parse
|
|
||||||
import urllib.request
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import Any, Callable, Optional
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"aura_verdict",
|
|
||||||
"before_settle",
|
|
||||||
"require_trust",
|
|
||||||
"AuraVerdict",
|
|
||||||
"AuraUntrusted",
|
|
||||||
"DEFAULT_BASE_URL",
|
|
||||||
"DEFAULT_ALLOW",
|
|
||||||
]
|
|
||||||
|
|
||||||
DEFAULT_BASE_URL = "https://agent.auraopenprotocol.org"
|
|
||||||
DEFAULT_TIMEOUT = 8 # seconds
|
|
||||||
|
|
||||||
# Verdicts safe to proceed with by default. Rejects `high_risk` (poor track
|
|
||||||
# record) and `unknown` (no verifiable history / endpoint unreachable).
|
|
||||||
DEFAULT_ALLOW = ("trusted", "caution", "new")
|
|
||||||
|
|
||||||
# All verdict classes the /check endpoint can return.
|
|
||||||
VERDICTS = ("trusted", "caution", "high_risk", "new", "unknown")
|
|
||||||
|
|
||||||
|
|
||||||
class AuraUntrusted(Exception):
|
|
||||||
"""Raised by before_settle() when a counterparty fails the trust gate."""
|
|
||||||
|
|
||||||
def __init__(self, verdict: "AuraVerdict") -> None:
|
|
||||||
self.verdict = verdict
|
|
||||||
super().__init__(
|
|
||||||
f"trust gate rejected {verdict.did}: {verdict.verdict} — {verdict.reason}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
|
||||||
class AuraVerdict:
|
|
||||||
"""
|
|
||||||
Result of a zero-auth trust check on a counterparty DID.
|
|
||||||
|
|
||||||
Fields:
|
|
||||||
did the DID that was checked
|
|
||||||
verdict one of trusted | caution | high_risk | new | unknown
|
|
||||||
reason human-readable explanation
|
|
||||||
score composite 0..1, or None when there is no history
|
|
||||||
has_history True once the agent has on-chain interactions
|
|
||||||
dimensions per-dimension breakdown (which axis is weak), or None
|
|
||||||
raw the untouched JSON body, for callers that want more
|
|
||||||
"""
|
|
||||||
|
|
||||||
did: str
|
|
||||||
verdict: str
|
|
||||||
reason: str = ""
|
|
||||||
score: Optional[float] = None
|
|
||||||
has_history: bool = False
|
|
||||||
dimensions: Optional[dict[str, float]] = None
|
|
||||||
# False only when AURA could not be reached (network/parse failure) and the
|
|
||||||
# verdict is a synthetic `unknown`. A reachable AURA that genuinely returns
|
|
||||||
# `unknown` has reachable=True. before_settle's fail_open keys on this, not
|
|
||||||
# on the verdict alone, so it can't wave through unverified counterparties.
|
|
||||||
reachable: bool = True
|
|
||||||
raw: dict[str, Any] = field(default_factory=dict, repr=False)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def ok(self) -> bool:
|
|
||||||
"""True for verdicts safe to proceed with (trusted / caution)."""
|
|
||||||
return self.verdict in ("trusted", "caution")
|
|
||||||
|
|
||||||
def as_dict(self) -> dict[str, Any]:
|
|
||||||
"""The minimal {verdict, reason, score} contract, plus did/ok."""
|
|
||||||
return {
|
|
||||||
"did": self.did,
|
|
||||||
"verdict": self.verdict,
|
|
||||||
"reason": self.reason,
|
|
||||||
"score": self.score,
|
|
||||||
"ok": self.ok,
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_payload(cls, did: str, body: dict[str, Any]) -> "AuraVerdict":
|
|
||||||
verdict = str(body.get("verdict", "unknown"))
|
|
||||||
if verdict not in VERDICTS:
|
|
||||||
verdict = "unknown"
|
|
||||||
return cls(
|
|
||||||
did=body.get("did", did),
|
|
||||||
verdict=verdict,
|
|
||||||
reason=str(body.get("reason", "")),
|
|
||||||
score=body.get("score"),
|
|
||||||
has_history=bool(body.get("has_history", False)),
|
|
||||||
dimensions=body.get("dimensions"),
|
|
||||||
raw=body,
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def unreachable(cls, did: str, reason: str) -> "AuraVerdict":
|
|
||||||
"""A synthetic `unknown` verdict for network/parse failures."""
|
|
||||||
return cls(did=did, verdict="unknown", reason=reason, reachable=False)
|
|
||||||
|
|
||||||
|
|
||||||
# Indirection point so tests can inject canned responses without a network.
|
|
||||||
# Signature: (url: str, timeout: float) -> dict (raises on transport error)
|
|
||||||
def _http_get_json(url: str, timeout: float) -> dict[str, Any]:
|
|
||||||
req = urllib.request.Request(url, headers={"User-Agent": "aura-adapter/1.0"})
|
|
||||||
with urllib.request.urlopen(req, timeout=timeout) as resp: # noqa: S310 (https only)
|
|
||||||
return json.loads(resp.read().decode("utf-8"))
|
|
||||||
|
|
||||||
|
|
||||||
def aura_verdict(
|
|
||||||
did: str,
|
|
||||||
*,
|
|
||||||
base_url: str = DEFAULT_BASE_URL,
|
|
||||||
timeout: float = DEFAULT_TIMEOUT,
|
|
||||||
_fetch: Callable[[str, float], dict[str, Any]] = _http_get_json,
|
|
||||||
) -> AuraVerdict:
|
|
||||||
"""
|
|
||||||
Look up the trust verdict for a counterparty DID. Never raises on a
|
|
||||||
network/parse failure — returns an `unknown` verdict instead, leaving the
|
|
||||||
proceed/abort decision to the caller's policy (see before_settle).
|
|
||||||
|
|
||||||
v = aura_verdict("did:aura:z6Mk...")
|
|
||||||
print(v.verdict, v.reason, v.score)
|
|
||||||
|
|
||||||
`_fetch` is an injection seam for tests; production callers ignore it.
|
|
||||||
"""
|
|
||||||
if not did or not str(did).startswith("did:"):
|
|
||||||
raise ValueError(f"invalid DID: {did!r} (must start with 'did:')")
|
|
||||||
|
|
||||||
url = f"{base_url.rstrip('/')}/check?" + urllib.parse.urlencode({"did": did})
|
|
||||||
try:
|
|
||||||
body = _fetch(url, timeout)
|
|
||||||
except (urllib.error.URLError, TimeoutError, OSError) as e:
|
|
||||||
return AuraVerdict.unreachable(did, f"AURA unreachable: {e}")
|
|
||||||
except (json.JSONDecodeError, ValueError) as e:
|
|
||||||
return AuraVerdict.unreachable(did, f"AURA returned non-JSON: {e}")
|
|
||||||
|
|
||||||
if not isinstance(body, dict):
|
|
||||||
return AuraVerdict.unreachable(did, "AURA returned an unexpected shape")
|
|
||||||
return AuraVerdict.from_payload(did, body)
|
|
||||||
|
|
||||||
|
|
||||||
def before_settle(
|
|
||||||
did: str,
|
|
||||||
*,
|
|
||||||
allow: tuple[str, ...] = DEFAULT_ALLOW,
|
|
||||||
fail_open: bool = False,
|
|
||||||
base_url: str = DEFAULT_BASE_URL,
|
|
||||||
timeout: float = DEFAULT_TIMEOUT,
|
|
||||||
_fetch: Callable[[str, float], dict[str, Any]] = _http_get_json,
|
|
||||||
) -> AuraVerdict:
|
|
||||||
"""
|
|
||||||
Gate a sensitive action behind a trust check. Returns the verdict on pass,
|
|
||||||
raises AuraUntrusted on fail.
|
|
||||||
|
|
||||||
try:
|
|
||||||
before_settle(counterparty_did) # rejects high_risk + unknown
|
|
||||||
settle_payment(counterparty_did, amount)
|
|
||||||
except AuraUntrusted as e:
|
|
||||||
abort(str(e))
|
|
||||||
|
|
||||||
Tighten to reject brand-new agents too:
|
|
||||||
before_settle(did, allow=("trusted", "caution"))
|
|
||||||
|
|
||||||
fail_open=True makes an *unreachable* AURA pass through (transport failure
|
|
||||||
only — a reachable AURA that returns `unknown` is still rejected). Off by
|
|
||||||
default — absence of evidence is not evidence of trust.
|
|
||||||
"""
|
|
||||||
v = aura_verdict(did, base_url=base_url, timeout=timeout, _fetch=_fetch)
|
|
||||||
|
|
||||||
if v.verdict in allow:
|
|
||||||
return v
|
|
||||||
# fail_open only excuses a transport failure, never a reachable `unknown`.
|
|
||||||
if fail_open and not v.reachable:
|
|
||||||
return v
|
|
||||||
raise AuraUntrusted(v)
|
|
||||||
|
|
||||||
|
|
||||||
# Alias — same gate, name that reads better at non-payment call sites.
|
|
||||||
require_trust = before_settle
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
"""
|
|
||||||
Canned /check responses — one per verdict class.
|
|
||||||
|
|
||||||
These are recorded shapes of real GET /check?did=... responses, used so the
|
|
||||||
test suite runs offline with no network. Pass `make_fetch(...)` as the
|
|
||||||
`_fetch` argument to aura_verdict / before_settle to replay them.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Any, Callable
|
|
||||||
|
|
||||||
# did -> recorded /check JSON body
|
|
||||||
RECORDED: dict[str, dict[str, Any]] = {
|
|
||||||
"did:aura:trusted-bot": {
|
|
||||||
"did": "did:aura:trusted-bot",
|
|
||||||
"verdict": "trusted",
|
|
||||||
"reason": "strong on-chain track record (composite 0.86)",
|
|
||||||
"has_history": True,
|
|
||||||
"score": 0.86,
|
|
||||||
"interactions": 142,
|
|
||||||
"dimensions": {
|
|
||||||
"task_completion": 0.92,
|
|
||||||
"delivery_speed": 0.81,
|
|
||||||
"output_quality": 0.88,
|
|
||||||
"honesty": 0.90,
|
|
||||||
"financial_integrity": 0.95,
|
|
||||||
"security_compliance": 0.79,
|
|
||||||
"collaboration": 0.84,
|
|
||||||
"dispute_history": 0.83,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"did:aura:caution-bot": {
|
|
||||||
"did": "did:aura:caution-bot",
|
|
||||||
"verdict": "caution",
|
|
||||||
"reason": "mixed history (composite 0.55)",
|
|
||||||
"has_history": True,
|
|
||||||
"score": 0.55,
|
|
||||||
"interactions": 31,
|
|
||||||
"dimensions": {"financial_integrity": 0.41, "task_completion": 0.62},
|
|
||||||
},
|
|
||||||
"did:aura:risky-bot": {
|
|
||||||
"did": "did:aura:risky-bot",
|
|
||||||
"verdict": "high_risk",
|
|
||||||
"reason": "poor track record (composite 0.22)",
|
|
||||||
"has_history": True,
|
|
||||||
"score": 0.22,
|
|
||||||
"interactions": 18,
|
|
||||||
"dimensions": {"financial_integrity": 0.12, "dispute_history": 0.20},
|
|
||||||
},
|
|
||||||
"did:aura:fresh-bot": {
|
|
||||||
"did": "did:aura:fresh-bot",
|
|
||||||
"verdict": "new",
|
|
||||||
"reason": "registered identity, no interactions yet",
|
|
||||||
"has_history": False,
|
|
||||||
"score": None,
|
|
||||||
"interactions": 0,
|
|
||||||
},
|
|
||||||
"did:aura:ghost-bot": {
|
|
||||||
"did": "did:aura:ghost-bot",
|
|
||||||
"verdict": "unknown",
|
|
||||||
"reason": "no track record — unverified counterparty",
|
|
||||||
"has_history": False,
|
|
||||||
"score": None,
|
|
||||||
"interactions": 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def make_fetch(
|
|
||||||
table: dict[str, dict[str, Any]] | None = None,
|
|
||||||
) -> Callable[[str, float], dict[str, Any]]:
|
|
||||||
"""
|
|
||||||
Build a `_fetch` stand-in that replays RECORDED bodies by DID parsed from
|
|
||||||
the query string. Unknown DIDs replay the `unknown` body.
|
|
||||||
"""
|
|
||||||
table = RECORDED if table is None else table
|
|
||||||
|
|
||||||
def _fetch(url: str, timeout: float) -> dict[str, Any]:
|
|
||||||
from urllib.parse import parse_qs, urlparse
|
|
||||||
|
|
||||||
did = parse_qs(urlparse(url).query).get("did", [""])[0]
|
|
||||||
return table.get(did, RECORDED["did:aura:ghost-bot"])
|
|
||||||
|
|
||||||
return _fetch
|
|
||||||
|
|
||||||
|
|
||||||
def raising_fetch(exc: Exception) -> Callable[[str, float], dict[str, Any]]:
|
|
||||||
"""Build a `_fetch` that always raises — simulates an unreachable AURA."""
|
|
||||||
|
|
||||||
def _fetch(url: str, timeout: float) -> dict[str, Any]:
|
|
||||||
raise exc
|
|
||||||
|
|
||||||
return _fetch
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
"""
|
|
||||||
Offline tests for the AURA trust-check adapter.
|
|
||||||
|
|
||||||
Runs with plain `pytest` (or `python -m pytest`). No network: every call
|
|
||||||
replays a recorded /check body via the `_fetch` injection seam.
|
|
||||||
|
|
||||||
Coverage:
|
|
||||||
- one assertion per verdict class (trusted / caution / high_risk / new / unknown)
|
|
||||||
- the before_settle gate: allow-list pass/reject, custom allow, fail_open
|
|
||||||
- the network-failure path (fail-closed by default, pass with fail_open)
|
|
||||||
- input validation
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import urllib.error
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from aura.adapter import AuraUntrusted, aura_verdict, before_settle
|
|
||||||
from aura.tests.fixtures import make_fetch, raising_fetch
|
|
||||||
|
|
||||||
FETCH = make_fetch()
|
|
||||||
|
|
||||||
|
|
||||||
# ── verdict classes ─────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"did,expected,ok",
|
|
||||||
[
|
|
||||||
("did:aura:trusted-bot", "trusted", True),
|
|
||||||
("did:aura:caution-bot", "caution", True),
|
|
||||||
("did:aura:risky-bot", "high_risk", False),
|
|
||||||
("did:aura:fresh-bot", "new", False),
|
|
||||||
("did:aura:ghost-bot", "unknown", False),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_verdict_classes(did, expected, ok):
|
|
||||||
v = aura_verdict(did, _fetch=FETCH)
|
|
||||||
assert v.verdict == expected
|
|
||||||
assert v.ok is ok
|
|
||||||
assert v.did == did
|
|
||||||
assert isinstance(v.reason, str) and v.reason
|
|
||||||
|
|
||||||
|
|
||||||
def test_minimal_dict_contract():
|
|
||||||
v = aura_verdict("did:aura:trusted-bot", _fetch=FETCH)
|
|
||||||
d = v.as_dict()
|
|
||||||
assert set(d) >= {"verdict", "reason", "score"}
|
|
||||||
assert d["verdict"] == "trusted"
|
|
||||||
assert d["score"] == 0.86
|
|
||||||
|
|
||||||
|
|
||||||
def test_dimensions_exposed_for_history():
|
|
||||||
v = aura_verdict("did:aura:risky-bot", _fetch=FETCH)
|
|
||||||
assert v.has_history is True
|
|
||||||
assert v.dimensions["financial_integrity"] == 0.12
|
|
||||||
|
|
||||||
|
|
||||||
def test_new_agent_has_no_score():
|
|
||||||
v = aura_verdict("did:aura:fresh-bot", _fetch=FETCH)
|
|
||||||
assert v.score is None
|
|
||||||
assert v.has_history is False
|
|
||||||
|
|
||||||
|
|
||||||
# ── the before_settle gate ───────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def test_gate_allows_trusted():
|
|
||||||
v = before_settle("did:aura:trusted-bot", _fetch=FETCH)
|
|
||||||
assert v.verdict == "trusted"
|
|
||||||
|
|
||||||
|
|
||||||
def test_gate_allows_caution_and_new_by_default():
|
|
||||||
assert before_settle("did:aura:caution-bot", _fetch=FETCH).verdict == "caution"
|
|
||||||
assert before_settle("did:aura:fresh-bot", _fetch=FETCH).verdict == "new"
|
|
||||||
|
|
||||||
|
|
||||||
def test_gate_rejects_high_risk():
|
|
||||||
with pytest.raises(AuraUntrusted) as ei:
|
|
||||||
before_settle("did:aura:risky-bot", _fetch=FETCH)
|
|
||||||
assert ei.value.verdict.verdict == "high_risk"
|
|
||||||
|
|
||||||
|
|
||||||
def test_gate_rejects_unknown_by_default():
|
|
||||||
with pytest.raises(AuraUntrusted):
|
|
||||||
before_settle("did:aura:ghost-bot", _fetch=FETCH)
|
|
||||||
|
|
||||||
|
|
||||||
def test_strict_allow_rejects_new():
|
|
||||||
with pytest.raises(AuraUntrusted):
|
|
||||||
before_settle("did:aura:fresh-bot", allow=("trusted", "caution"), _fetch=FETCH)
|
|
||||||
|
|
||||||
|
|
||||||
# ── network-failure path ──────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def test_unreachable_returns_unknown_not_raise():
|
|
||||||
fetch = raising_fetch(urllib.error.URLError("connection refused"))
|
|
||||||
v = aura_verdict("did:aura:trusted-bot", _fetch=fetch)
|
|
||||||
assert v.verdict == "unknown"
|
|
||||||
assert "unreachable" in v.reason.lower()
|
|
||||||
|
|
||||||
|
|
||||||
def test_gate_fail_closed_on_unreachable():
|
|
||||||
fetch = raising_fetch(urllib.error.URLError("connection refused"))
|
|
||||||
with pytest.raises(AuraUntrusted):
|
|
||||||
before_settle("did:aura:trusted-bot", _fetch=fetch)
|
|
||||||
|
|
||||||
|
|
||||||
def test_gate_fail_open_passes_on_unreachable():
|
|
||||||
fetch = raising_fetch(urllib.error.URLError("connection refused"))
|
|
||||||
v = before_settle("did:aura:trusted-bot", fail_open=True, _fetch=fetch)
|
|
||||||
assert v.verdict == "unknown"
|
|
||||||
assert v.reachable is False
|
|
||||||
|
|
||||||
|
|
||||||
def test_fail_open_does_not_pass_reachable_unknown():
|
|
||||||
# A reachable AURA that returns `unknown` (ghost DID) is still rejected even
|
|
||||||
# with fail_open — fail_open only excuses transport failures.
|
|
||||||
with pytest.raises(AuraUntrusted):
|
|
||||||
before_settle("did:aura:ghost-bot", fail_open=True, _fetch=FETCH)
|
|
||||||
|
|
||||||
|
|
||||||
def test_reachable_verdict_marked_reachable():
|
|
||||||
v = aura_verdict("did:aura:ghost-bot", _fetch=FETCH)
|
|
||||||
assert v.reachable is True
|
|
||||||
|
|
||||||
|
|
||||||
# ── input validation ──────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("bad", ["", "not-a-did", "z6Mk-no-prefix", None])
|
|
||||||
def test_rejects_bad_did(bad):
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
aura_verdict(bad, _fetch=FETCH)
|
|
||||||
@@ -589,6 +589,14 @@
|
|||||||
"modules": [
|
"modules": [
|
||||||
"docs-zh-tw"
|
"docs-zh-tw"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "locale:de-de",
|
||||||
|
"family": "locale",
|
||||||
|
"description": "German (de-DE) translated reference docs installed to ~/.claude/docs/de-DE/.",
|
||||||
|
"modules": [
|
||||||
|
"docs-de-de"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -843,6 +843,22 @@
|
|||||||
"defaultInstall": false,
|
"defaultInstall": false,
|
||||||
"cost": "heavy",
|
"cost": "heavy",
|
||||||
"stability": "stable"
|
"stability": "stable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "docs-de-de",
|
||||||
|
"kind": "docs",
|
||||||
|
"description": "German (de-DE) translated reference docs for agents, commands, skills, and rules.",
|
||||||
|
"paths": [
|
||||||
|
"docs/de-DE"
|
||||||
|
],
|
||||||
|
"targets": [
|
||||||
|
"claude",
|
||||||
|
"claude-project"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"defaultInstall": false,
|
||||||
|
"cost": "heavy",
|
||||||
|
"stability": "stable"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
"agent.yaml",
|
"agent.yaml",
|
||||||
"agents/",
|
"agents/",
|
||||||
"commands/",
|
"commands/",
|
||||||
|
"docs/de-DE/",
|
||||||
"docs/ja-JP/",
|
"docs/ja-JP/",
|
||||||
"docs/ko-KR/",
|
"docs/ko-KR/",
|
||||||
"docs/pt-BR/",
|
"docs/pt-BR/",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const COMPONENT_FAMILY_PREFIXES = {
|
|||||||
skill: 'skill:',
|
skill: 'skill:',
|
||||||
locale: 'locale:',
|
locale: 'locale:',
|
||||||
};
|
};
|
||||||
const SUPPORTED_LOCALES = Object.freeze(['ja', 'zh-CN', 'ko-KR', 'pt-BR', 'ru', 'tr', 'vi-VN', 'zh-TW']);
|
const SUPPORTED_LOCALES = Object.freeze(['ja', 'zh-CN', 'ko-KR', 'pt-BR', 'ru', 'tr', 'vi-VN', 'zh-TW', 'de-DE']);
|
||||||
const LOCALE_ALIAS_TO_COMPONENT_ID = Object.freeze({
|
const LOCALE_ALIAS_TO_COMPONENT_ID = Object.freeze({
|
||||||
'ja': 'locale:ja',
|
'ja': 'locale:ja',
|
||||||
'ja-JP': 'locale:ja',
|
'ja-JP': 'locale:ja',
|
||||||
@@ -29,6 +29,8 @@ const LOCALE_ALIAS_TO_COMPONENT_ID = Object.freeze({
|
|||||||
'vi-VN': 'locale:vi-vn',
|
'vi-VN': 'locale:vi-vn',
|
||||||
'vi': 'locale:vi-vn',
|
'vi': 'locale:vi-vn',
|
||||||
'zh-TW': 'locale:zh-tw',
|
'zh-TW': 'locale:zh-tw',
|
||||||
|
'de-DE': 'locale:de-de',
|
||||||
|
'de': 'locale:de-de',
|
||||||
});
|
});
|
||||||
|
|
||||||
function listSupportedLocales() {
|
function listSupportedLocales() {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ function runTests() {
|
|||||||
const components = listInstallComponents({ family: 'locale' });
|
const components = listInstallComponents({ family: 'locale' });
|
||||||
assert.ok(components.some(component => component.id === 'locale:ja'));
|
assert.ok(components.some(component => component.id === 'locale:ja'));
|
||||||
assert.ok(components.some(component => component.id === 'locale:zh-cn'));
|
assert.ok(components.some(component => component.id === 'locale:zh-cn'));
|
||||||
|
assert.ok(components.some(component => component.id === 'locale:de-de'));
|
||||||
assert.ok(components.every(component => component.family === 'locale'));
|
assert.ok(components.every(component => component.family === 'locale'));
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
@@ -75,6 +76,59 @@ function runTests() {
|
|||||||
}
|
}
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('locale:de-de resolves to the German translated docs module', () => {
|
||||||
|
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-plan-de-'));
|
||||||
|
try {
|
||||||
|
const plan = resolveInstallPlan({
|
||||||
|
includeComponentIds: ['locale:de-de'],
|
||||||
|
target: 'claude',
|
||||||
|
homeDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepStrictEqual(plan.selectedModuleIds, ['docs-de-de']);
|
||||||
|
assert.ok(
|
||||||
|
plan.operations.some(operation => (
|
||||||
|
normalizePlanPath(operation.sourceRelativePath) === 'docs/de-DE'
|
||||||
|
&& normalizePlanPath(operation.destinationPath).endsWith('/.claude/docs/de-DE')
|
||||||
|
)),
|
||||||
|
'Should map docs/de-DE to ~/.claude/docs/de-DE'
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('end-to-end: --locale de dry-run includes docs-de-de operations', () => {
|
||||||
|
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-de-'));
|
||||||
|
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-de-project-'));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const output = runInstallApply([
|
||||||
|
'--locale', 'de',
|
||||||
|
'--dry-run',
|
||||||
|
'--json',
|
||||||
|
], {
|
||||||
|
cwd: projectDir,
|
||||||
|
env: { HOME: homeDir },
|
||||||
|
});
|
||||||
|
const json = JSON.parse(output);
|
||||||
|
|
||||||
|
assert.strictEqual(json.plan.mode, 'manifest');
|
||||||
|
assert.deepStrictEqual(json.plan.includedComponentIds, ['locale:de-de']);
|
||||||
|
assert.deepStrictEqual(json.plan.selectedModuleIds, ['docs-de-de']);
|
||||||
|
assert.ok(
|
||||||
|
json.plan.operations.some(operation => (
|
||||||
|
normalizePlanPath(operation.sourceRelativePath) === 'docs/de-DE/README.md'
|
||||||
|
&& normalizePlanPath(operation.destinationPath).endsWith('/.claude/docs/de-DE/README.md')
|
||||||
|
)),
|
||||||
|
'Should copy translated README into ~/.claude/docs/de-DE'
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(homeDir, { recursive: true, force: true });
|
||||||
|
fs.rmSync(projectDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
if (test('end-to-end: --locale ja dry-run includes docs-ja-jp operations', () => {
|
if (test('end-to-end: --locale ja dry-run includes docs-ja-jp operations', () => {
|
||||||
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-'));
|
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-'));
|
||||||
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-project-'));
|
const projectDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locale-dry-run-project-'));
|
||||||
|
|||||||
Reference in New Issue
Block a user