diff --git a/README.md b/README.md index 1ef9027..558e637 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ If the agent cannot produce the artifact, the work cannot be promoted. - Architecture generation: Trinity v2 - Runtime release: v0.1.0 -- Public Tool Contract: v1.0 freeze candidate; working spec is `v1.1.0-draft` +- Tool Contract ABI: v1.0.0 stable; validation tooling v1.0.1 - Kernel CLI: verified v0.1.0 runtime included in this repository - Release evidence: [`docs/releases/TRINITY_V0_1_0_RELEASE_EVIDENCE.md`](docs/releases/TRINITY_V0_1_0_RELEASE_EVIDENCE.md) @@ -108,6 +108,27 @@ Clean export without optional sibling tools: 1860 passed, 8 skipped --- +## Tool Ecosystem + +Trinity separates the kernel, public ABI, and tools that implement the ABI. + +| Tool | Role | Status | Contract | Repo | +|---|---|---|---|---| +| Trinity Protocol | Kernel / governance runtime | v0.1.0 stable | consumes Tool Contract | this repo | +| Trinity Tool Contract | Stable ABI for CLI tools | v1.0.0 stable, v1.0.1 validator | v1.0 | [`postmunnet/trinity-tool-contract`](https://github.com/postmunnet/trinity-tool-contract) | +| browser-cli | Browser automation organ | planned clean export | target v1.0 | planned | +| memory-cli | Artifact memory organ | planned | target v1.0 | planned | +| verify-cli | Verification organ | planned | target v1.0 | planned | +| retro-cli | Retrospective / memory handoff organ | planned | target v1.0 | planned | + +Canonical Tool Contract: + +- [`postmunnet/trinity-tool-contract`](https://github.com/postmunnet/trinity-tool-contract) +- pinned ABI: [`v1.0.0`](https://github.com/postmunnet/trinity-tool-contract/tree/v1.0.0) +- validation tooling: [`v1.0.1`](https://github.com/postmunnet/trinity-tool-contract/releases/tag/v1.0.1) + +--- + ## Architecture ```text @@ -206,7 +227,7 @@ Specs: - [`docs/specs/INDEX.md`](docs/specs/INDEX.md) - [`docs/specs/00_BLUEPRINT.md`](docs/specs/00_BLUEPRINT.md) -- [`docs/specs/01_TOOL_CONTRACT.md`](docs/specs/01_TOOL_CONTRACT.md) +- [`docs/specs/01_TOOL_CONTRACT.md`](docs/specs/01_TOOL_CONTRACT.md) redirects to [`postmunnet/trinity-tool-contract`](https://github.com/postmunnet/trinity-tool-contract) --- @@ -242,7 +263,7 @@ Version story: ```text Trinity Protocol v2 = architecture / constitution generation Runtime v0.1.0 = first public executable runtime line -Tool Contract = v1.0 freeze candidate, v1.1 draft working spec +Tool Contract ABI = v1.0.0 stable; validation tooling v1.0.1 ``` See [`docs/VERSION_LINEAGE.md`](docs/VERSION_LINEAGE.md). @@ -279,3 +300,4 @@ Trinity คือ control layer แบบ CLI-first สำหรับงาน - [`docs/ORIGIN_TH.md`](docs/ORIGIN_TH.md) — ที่มาของ Trinity - [`docs/RITUALS_TH.md`](docs/RITUALS_TH.md) — ritual reference - [`docs/operator-guide-th/00_README.md`](docs/operator-guide-th/00_README.md) — คู่มือใช้งาน +- [`postmunnet/trinity-tool-contract`](https://github.com/postmunnet/trinity-tool-contract) — Tool Contract ABI v1.0 diff --git a/docs/VERSION_LINEAGE.md b/docs/VERSION_LINEAGE.md index d86f2d8..1cd607b 100644 --- a/docs/VERSION_LINEAGE.md +++ b/docs/VERSION_LINEAGE.md @@ -8,7 +8,7 @@ contracts. They should not be collapsed into one number. ```text Trinity Protocol v2 = architecture / constitution generation Runtime v0.1.0 = first public executable runtime line -Tool Contract = v1.0 freeze candidate, v1.1 draft working spec +Tool Contract ABI = v1.0.0 stable; validation tooling v1.0.1 ``` ## v0.1.0 diff --git a/docs/VERSION_LINEAGE_TH.md b/docs/VERSION_LINEAGE_TH.md index e1075a1..ee838ae 100644 --- a/docs/VERSION_LINEAGE_TH.md +++ b/docs/VERSION_LINEAGE_TH.md @@ -8,7 +8,7 @@ Trinity แยก version line ของ architecture, runtime และ tool co ```text Trinity Protocol v2 = architecture / constitution generation Runtime v0.1.0 = first public executable runtime line -Tool Contract = v1.0 freeze candidate, v1.1 draft working spec +Tool Contract ABI = v1.0.0 stable; validation tooling v1.0.1 ``` ## v0.1.0 diff --git a/docs/specs/01_TOOL_CONTRACT.md b/docs/specs/01_TOOL_CONTRACT.md index 6a8f48a..ab713b9 100644 --- a/docs/specs/01_TOOL_CONTRACT.md +++ b/docs/specs/01_TOOL_CONTRACT.md @@ -1,1329 +1,19 @@ ---- -title: "Trinity Tool Contract" -subtitle: "Universal CLI tool contract — POSIX of Trinity" -version: 1.1.0-draft -status: revised -last-updated: 2026-04-28 -applies-to: All CLI tools in Trinity OS userland -reference-implementation: browser-cli -revision-notes: "v1.1 — added Action Namespace, Contract Compliance Test, MCP stance clarified as CLI-first default with optional bridge" ---- +# Tool Contract (Moved) -# Trinity Tool Contract v1.1 +Canonical spec: -> **Universal contract for CLI tools in Trinity OS ecosystem** -> -> ถ้า tool ไม่ตามสัญญานี้ — Trinity kernel จะไม่ orchestrate ได้ -> ถ้า tool ตามสัญญานี้ครบ — เสียบกับ Trinity ได้ทันทีโดยไม่ต้องแก้ kernel +- https://github.com/postmunnet/trinity-tool-contract ---- +Pinned stable ABI: -## Public Freeze Status +- https://github.com/postmunnet/trinity-tool-contract/tree/v1.0.0 -Public ecosystem messaging should treat the Tool Contract as: +Latest validation tooling: -```text -Tool Contract v1.0 = freeze candidate -Current working spec = v1.1.0-draft -``` +- https://github.com/postmunnet/trinity-tool-contract/releases/tag/v1.0.1 -ก่อนประกาศ stable interface ต้อง freeze อย่างน้อย 10 เรื่องนี้: +This file is kept as a redirect so older Trinity Protocol links do not break. +Do not edit this file as the source of truth. -1. Input envelope -2. Output envelope -3. Exit code meaning -4. Verdict schema -5. Artifact declaration -6. Error taxonomy -7. Retry semantics -8. Idempotency expectation -9. Audit log requirements -10. Security boundary - -จนกว่า checklist นี้จะปิดครบ ห้ามสื่อสารว่า external tool interface เป็น -stable แล้ว ให้ใช้คำว่า **v1.0 freeze candidate** หรือ **v1.1 draft working -spec** แทน - ---- - -## 0. Status & Compliance Levels - -| Level | Description | -|-------|-------------| -| **MUST** | บังคับ — ขาดไม่ได้, kernel จะปฏิเสธ tool | -| **SHOULD** | ควรทำ — ขาดได้แต่ไม่แนะนำ | -| **MAY** | ทำเพิ่มก็ได้ — ตามความเหมาะสม | - -Tool compliance assessment ทำผ่าน `trinity tool verify ` (Phase 5+) - ---- - -## 1. Scope - -### 1.1 In Scope -- Binary entry point conventions -- Stdin/stdout JSON protocol -- Response envelope schema -- Universal CLI flags (`--config`, `--run-id`, `--log-file`, ...) -- Logging format (NDJSON) -- Policy tiers (safe / normal / aggressive) -- Error code conventions -- Schema versioning rules -- Discovery (`--list-commands`, `--describe`, `--health`) -- Helpers (YAML composition) -- Documentation requirements -- Test harness pattern -- Tool registry format - -### 1.2 Out of Scope -- ❌ Tool internal architecture (each tool decides) -- ❌ Programming language (Node/Python/Rust/Go ทั้งหมดได้) -- ❌ External library choices -- ❌ Database choice (FTS5, ChromaDB, etc.) -- ❌ **MCP protocol as default core path** — Trinity is CLI-first by default. - - Vendor harness's built-in tools (Read/Write/Edit/Bash) = ใช้ตามปกติ (ไม่กระทบ) - - External MCP servers = optional bridge only, not the default control path - - MCP-only capability ต้องถูก wrap ผ่าน Tool Contract envelope ก่อนเข้า audit chain - - Default replacement: capability สำคัญควรมี CLI tool ตาม contract นี้ - -### 1.3 Non-goals -- ไม่ใช่ AI logic specification -- ไม่ใช่ workflow graph definition -- ไม่ใช่ kernel orchestration logic - ---- - -## 2. Terminology - -| Term | Definition | -|------|------------| -| **Tool** | CLI binary ที่ implement contract นี้ | -| **Verb / Command** | คำสั่งใน tool (e.g. `search`, `index`, `goto`) | -| **Run** | 1 invocation ของ tool (single command, REPL session, pipe batch) | -| **Run ID** | Unique identifier ของ run — สำหรับ trace correlation | -| **Envelope** | Response JSON wrapper (`ok`, `data`, `error`, `meta`) | -| **Artifact** | File/data ที่ tool สร้าง — เก็บไว้เป็น truth | -| **Policy** | Tier ที่จำกัดว่า command ไหนรันได้ (safe/normal/aggressive) | -| **Schema version** | Version ของ response format (`v1`, `v2`, ...) | -| **Helper** | YAML composition ของ commands ที่ใช้ซ้ำ | - ---- - -## 3. Binary Interface - -### 3.1 Entry Point (MUST) - -```bash - [universal-flags] [tool-flags] [-- ] -``` - -**Examples:** -```bash -memory-cli --config configs/.json --cmd "search 'auth bug'" -browser-cli --config configs/.json --login backend -wordpress-cli --config configs/site.json --policy=safe -``` - -### 3.2 Execution Modes (MUST support all 4) - -#### Mode A: Single Command (`--cmd`) -```bash -memory-cli --cmd "search 'auth bug'" -``` -- รัน 1 command, exit -- Response เดียวออก stdout - -#### Mode B: REPL (interactive) -```bash -memory-cli -> search auth -> get r123 -> exit -``` -- Read-Eval-Print loop -- Prompt `> ` -- Each command = 1 response line -- `exit` ออก - -#### Mode C: Pipe (stdin) -```bash -echo "search auth -get r123 -exit" | memory-cli -``` -- อ่านบรรทัดจาก stdin -- Run sequentially -- Each command = 1 response line stdout - -#### Mode D: Run File -```bash -memory-cli --run-file batch.txt -``` -- อ่านไฟล์ — ทุกบรรทัด = 1 command -- Run sequentially -- Skip `#` comments - -### 3.3 Exit Codes (MUST) - -| Code | Meaning | -|------|---------| -| `0` | Success (all commands ok) | -| `1` | Generic error (1+ command failed) | -| `2` | Invalid usage (bad flags, missing config) | -| `3` | Policy violation (command blocked by tier) | -| `4` | Configuration error (config file invalid) | -| `5` | Permission denied (filesystem, network) | -| `10` | Timeout | -| `20` | External dependency failure (e.g. SQLite locked) | -| `64-78` | Reserved (sysexits.h compatibility) | -| `100+` | Tool-specific | - -### 3.4 stdin/stdout/stderr Discipline (MUST) - -| Stream | Purpose | Format | -|--------|---------|--------| -| **stdin** | Commands input | Plain text (1 command per line) | -| **stdout** | Responses | JSON (1 envelope per line, NDJSON) | -| **stderr** | Human-readable diagnostics | Free-form | - -**Critical:** stdout ต้องเป็น **machine-parseable JSON เท่านั้น** ห้ามมี log/debug/banner - ---- - -## 4. Response Envelope - -### 4.1 Success Envelope (MUST) - -```json -{ - "ok": true, - "command": "search", - "action": "memory.search", - "data": { "...": "tool-specific" }, - "artifacts": [ - { "type": "file", "path": "./out/result.json", "sha256": "..." } - ], - "error": null, - "meta": { - "tool": "memory-cli", - "schema_version": "1", - "run_id": "run_2026-04-28_xyz", - "duration_ms": 42, - "timestamp": "2026-04-28T12:34:56.789Z" - } -} -``` - -> ⚠️ **`action` field (v1.1+)** — canonical namespaced verb (e.g. `memory.search`, `browser.screenshot`) — ดู §4a Action Namespace - -### 4.2 Error Envelope (MUST) - -```json -{ - "ok": false, - "command": "search", - "data": null, - "artifacts": [], - "error": { - "code": "INDEX_NOT_FOUND", - "message": "Memory index not initialized", - "details": { - "expected_path": "./.memory/index.db", - "hint": "Run 'memory-cli index ./.claude/retrospectives/' first" - }, - "recoverable": true - }, - "meta": { - "tool": "memory-cli", - "schema_version": "1", - "run_id": "run_2026-04-28_xyz", - "duration_ms": 5, - "timestamp": "2026-04-28T12:34:56.789Z" - } -} -``` - -### 4.3 Field Reference - -| Field | Required | Type | Notes | -|-------|----------|------|-------| -| `ok` | MUST | boolean | `true`=success, `false`=error | -| `command` | MUST | string | verb ที่ถูกเรียก (local name) | -| `action` | MUST (v1.1+) | string | canonical namespaced verb (`tool.verb`) | -| `data` | MUST | object\|null | tool-specific payload (null on error) | -| `artifacts` | MUST | array | files/data created (เก็บเป็น truth) | -| `error` | MUST | object\|null | null on success | -| `error.code` | MUST | string | UPPER_SNAKE_CASE | -| `error.message` | MUST | string | human-readable (Thai+English ok) | -| `error.details` | SHOULD | object | structured context | -| `error.recoverable` | SHOULD | boolean | retry หาย vs need human | -| `meta` | MUST | object | run metadata | -| `meta.tool` | MUST | string | tool name + version (`memory-cli@0.1.0`) | -| `meta.schema_version` | MUST | string | response schema version | -| `meta.run_id` | MUST | string | run correlation ID | -| `meta.duration_ms` | MUST | number | exec time | -| `meta.timestamp` | MUST | string | ISO 8601 UTC | - -### 4.4 Artifact Object Schema - -```json -{ - "type": "file" | "url" | "ref", - "path": "./out/screenshot.png", - "sha256": "abc123...", - "size_bytes": 4096, - "mime": "image/png", - "metadata": {} -} -``` - ---- - -## 4a. Action Namespace (v1.1+) - -### 4a.1 Why -- `screenshot` มีทั้งใน browser-cli, future wordpress-cli — **conflict!** -- `search` มีใน memory-cli, future grep-cli — **conflict!** -- Audit log ต้องระบุ canonical action สำหรับ correlation - -### 4a.2 Format (MUST) - -```text -. -``` - -- `` = lowercase, kebab-case (`browser`, `memory`, `wordpress`, `ftp`, `seo`) -- `` = lowercase, snake_case (`search`, `screenshot`, `fill_form`) - -### 4a.3 Reserved Namespaces - -| Namespace | Tool | -|-----------|------| -| `browser` | browser-cli | -| `memory` | memory-cli | -| `retro` | retro-cli | -| `verify` | verify-cli | -| `wordpress` | wordpress-cli | -| `ftp` | ftp-cli | -| `seo` | seo-cli | -| `code` | grep-cli (code search) | -| `deploy` | deploy-cli | -| `god` | god-team-cli | - -### 4a.4 Examples - -| Local verb | Action namespace | -|-----------|------------------| -| `goto` (browser-cli) | `browser.goto` | -| `screenshot` (browser-cli) | `browser.screenshot` | -| `search` (memory-cli) | `memory.search` | -| `learn` (memory-cli) | `memory.learn` | -| `validate` (retro-cli) | `retro.validate` | -| `assert_browser` (verify-cli) | `verify.assert_browser` | -| `put` (ftp-cli) | `ftp.put` | - -### 4a.5 Rules - -- Tool ต้อง emit `action` field ใน envelope ทุก response -- Tool ต้อง register namespace ใน `.ai/tools.yaml` -- Trinity kernel ต้อง dedupe by action — log canonical name -- `--list-commands` MUST return action namespace per verb - ---- - -## 5. Stdin/Stdout Protocol - -### 5.1 Line Discipline (MUST) -- Each input command = 1 line, terminated by `\n` -- Each output envelope = 1 line, terminated by `\n` (NDJSON) -- No multi-line JSON output — everything single-line - -### 5.2 Encoding (MUST) -- UTF-8 -- ASCII subset acceptable -- No BOM - -### 5.3 Buffering (SHOULD) -- Stdout: line-buffered (flush after each envelope) -- Stderr: unbuffered (immediate diagnostic) -- Stdin: line-buffered (read complete commands) - -### 5.4 Backpressure (MAY) -- Tools MAY honor `SIGPIPE` to halt cleanly -- Long-running commands SHOULD send heartbeat to stderr (not stdout) - ---- - -## 6. Universal CLI Flags - -### 6.1 Required Flags (MUST support) - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--config ` | path | `./.config.json` | Config file | -| `--run-id ` | string | auto-generated | Run correlation | -| `--log-file ` | path | none | NDJSON log output | -| `--policy ` | enum | `normal` | `safe` \| `normal` \| `aggressive` | -| `--response-schema ` | string | `1` | Response schema version | -| `--cmd ""` | string | none | Single command mode | -| `--run-file ` | path | none | Batch from file | - -### 6.2 Standard Flags (SHOULD support) - -| Flag | Description | -|------|-------------| -| `--help, -h` | Print help | -| `--version, -v` | Print version | -| `--list-commands` | Print available verbs (JSON) | -| `--describe ` | Print verb spec (JSON) | -| `--health` | Print health check (JSON) | -| `--quiet, -q` | Suppress stderr diagnostics | -| `--verbose` | Extra stderr diagnostics | -| `--dry-run` | Validate without side effects | - -### 6.3 Reserved Flags (MAY use, but conventions apply) - -| Flag | Convention | -|------|-----------| -| `--show` | Visual mode (e.g. headed browser) | -| `--cdp ` | CDP/external connection (browser-cli) | -| `--reuse` | Reuse existing resource | -| `--force` | Bypass safety checks (require aggressive policy) | -| `--watch` | Long-running watch mode | - -### 6.4 Tool-specific Flags (MAY use any unprefixed name not above) - -ห้ามชนกับ universal/standard/reserved - ---- - -## 7. Configuration - -### 7.1 Config File Format (MUST) -- JSON (preferred) -- YAML (acceptable if tool dependencies allow) - -### 7.2 Standard Config Fields - -```json -{ - "$schema": "https://trinity.local/schemas/tool-config-v1.json", - "version": "1.0", - "tool": "memory-cli", - "run": { - "default_policy": "normal", - "default_log_file": "./logs/memory-cli.ndjson", - "max_duration_ms": 60000 - }, - "paths": { - "data_dir": "./.memory", - "artifact_dir": "./out" - }, - "tool_specific": { - "...": "tool-defined" - } -} -``` - -### 7.3 Config Resolution Order (MUST) - -1. CLI flag explicit (`--config foo.json`) -2. ENV `_CONFIG` -3. CWD `./.config.json` -4. CWD `./configs/.json` -5. Built-in default - -### 7.4 Config Schema Validation (SHOULD) - -Tool ต้อง validate config ก่อน execute และ exit code `4` ถ้าไม่ผ่าน - ---- - -## 8. Logging (NDJSON) - -### 8.1 Log Format (MUST when `--log-file` given) - -Each log line = JSON object on one line: - -```json -{"ts":"2026-04-28T12:34:56.789Z","level":"INFO","tool":"memory-cli","run_id":"run_xyz","event":"command_start","command":"search","args":["auth bug"]} -{"ts":"2026-04-28T12:34:56.823Z","level":"DEBUG","tool":"memory-cli","run_id":"run_xyz","event":"db_query","sql":"SELECT ..."} -{"ts":"2026-04-28T12:34:56.831Z","level":"INFO","tool":"memory-cli","run_id":"run_xyz","event":"command_end","command":"search","duration_ms":42,"ok":true} -``` - -### 8.2 Required Fields per Log Line - -| Field | Type | Description | -|-------|------|-------------| -| `ts` | string | ISO 8601 UTC | -| `level` | enum | `DEBUG`, `INFO`, `WARN`, `ERROR` | -| `tool` | string | tool name | -| `run_id` | string | run correlation | -| `event` | string | event type (snake_case) | - -### 8.3 Standard Events (SHOULD use) - -| Event | When | -|-------|------| -| `run_start` | Tool process starts | -| `run_end` | Tool process exits | -| `command_start` | Verb begins execution | -| `command_end` | Verb finishes | -| `policy_violation` | Command blocked by tier | -| `artifact_created` | File written | -| `external_call` | DB/HTTP/exec invoked | -| `error_caught` | Exception handled | - -### 8.4 Append-only (MUST) -- Log file = append-only NDJSON -- ห้ามแก้บรรทัดเก่า -- Rotation = สร้างไฟล์ใหม่ (ไม่ rewrite) - ---- - -## 9. Policy Tiers - -### 9.1 Tier Definitions (MUST honor) - -| Tier | Allows | Use case | -|------|--------|----------| -| **safe** | Read-only verbs | Audit, status, search, get, list, describe | -| **normal** | + Write verbs | Standard work — index, learn, create, update | -| **aggressive** | + Destructive verbs | Migrations — delete, supersede, force, reset | - -### 9.2 Verb Classification (MUST in `--describe`) - -```json -{ - "verb": "delete", - "tier_required": "aggressive", - "destructive": true, - "writes": true -} -``` - -### 9.3 Policy Enforcement (MUST) -- ก่อนรันทุก verb — check tier -- Block ด้วย exit code `3` + error envelope -- Log `policy_violation` event - -```json -{ - "ok": false, - "command": "delete", - "error": { - "code": "POLICY_VIOLATION", - "message": "Verb 'delete' requires tier=aggressive, current=normal", - "recoverable": false - } -} -``` - -### 9.4 Policy Override (MAY) -- `--policy aggressive` flag = explicit ack -- ห้าม default = `aggressive` -- Tool MAY require additional confirmation (e.g. ENV `I_KNOW_WHAT_IM_DOING=1`) - ---- - -## 10. Error Codes - -### 10.1 Standard Codes (MUST use เหล่านี้สำหรับสถานการณ์ตรงกัน) - -| Code | Meaning | Recoverable | -|------|---------|-------------| -| `INVALID_ARGS` | Bad command arguments | true | -| `INVALID_CONFIG` | Config file malformed | false | -| `MISSING_DEPENDENCY` | External tool not found | false | -| `POLICY_VIOLATION` | Tier insufficient | false | -| `PERMISSION_DENIED` | Filesystem/network forbidden | false | -| `RESOURCE_NOT_FOUND` | File/record missing | true | -| `RESOURCE_LOCKED` | Can't acquire lock | true | -| `RESOURCE_EXHAUSTED` | Disk/memory/quota | true | -| `EXTERNAL_FAILURE` | DB/HTTP/exec failed | true | -| `TIMEOUT` | Operation took too long | true | -| `SCHEMA_MISMATCH` | Response schema version wrong | false | -| `INTERNAL_ERROR` | Bug ใน tool | false | - -### 10.2 Tool-specific Codes (MAY add) - -- ใช้ prefix tool name: `MEMORY_INDEX_CORRUPT`, `BROWSER_PAGE_CRASH` -- UPPER_SNAKE_CASE -- Document ใน COMMAND_CONTRACT.md ของ tool - ---- - -## 11. Schema Versioning - -### 11.1 Versioning Rules (MUST) - -- Schema version = string (e.g. `"1"`, `"2"`, `"1.1"`) -- Backward compat: `v2` tool MUST support `--response-schema=v1` -- Tool MUST embed `schema_version` ใน envelope `meta` - -### 11.2 Breaking Changes Trigger (MUST bump major) - -- ลบ field -- เปลี่ยน type ของ field -- เปลี่ยน semantic ของ field -- เพิ่ม required field - -### 11.3 Non-breaking Changes (MAY bump minor) - -- เพิ่ม optional field -- เพิ่ม enum value (clients SHOULD ignore unknown) - -### 11.4 Deprecation (SHOULD) - -- ประกาศ deprecation 1 major version ก่อนลบ -- Log `WARN` เมื่อ client ใช้ field ที่ deprecated - ---- - -## 12. Discovery - -### 12.1 `--list-commands` (MUST) - -```bash -$ memory-cli --list-commands -``` - -```json -{ - "ok": true, - "command": "list-commands", - "data": { - "tool": "memory-cli@0.1.0", - "commands": [ - { "verb": "search", "tier": "safe", "description": "Hybrid search" }, - { "verb": "learn", "tier": "normal", "description": "Add document" }, - { "verb": "supersede", "tier": "aggressive", "description": "Mark obsolete" } - ] - }, - "error": null, - "meta": { "...": "..." } -} -``` - -### 12.2 `--describe ` (MUST) - -```bash -$ memory-cli --describe search -``` - -```json -{ - "ok": true, - "command": "describe", - "data": { - "verb": "search", - "tier_required": "safe", - "destructive": false, - "writes": false, - "args": [ - { "name": "query", "type": "string", "required": true, "description": "Search query" } - ], - "options": [ - { "name": "--limit", "type": "int", "default": 10 } - ], - "returns": { - "type": "object", - "schema": { "$ref": "schemas/search-response-v1.json" } - }, - "examples": [ - "search 'auth bug'", - "search 'login error' --limit=20" - ] - } -} -``` - -### 12.3 `--health` (SHOULD) - -```bash -$ memory-cli --health -``` - -```json -{ - "ok": true, - "command": "health", - "data": { - "tool": "memory-cli@0.1.0", - "status": "ready", - "checks": [ - { "name": "config_loaded", "ok": true }, - { "name": "db_connection", "ok": true, "details": { "path": "./.memory/index.db" } }, - { "name": "external_deps", "ok": true, "deps": ["sqlite3"] } - ] - } -} -``` - ---- - -## 13. Helpers (YAML) - -### 13.1 Helper File Format (SHOULD support) - -```yaml -# memory-helpers.yml -helpers: - fresh-search: - args: [query] - description: "Reindex then search" - steps: - - reindex - - search {query} - - weekly-stats: - description: "Stats + recent learnings" - steps: - - stats - - list --since=7d --tag=lesson -``` - -### 13.2 Invocation - -```bash -memory-cli --cmd "helper fresh-search 'auth bug'" -``` - -### 13.3 Variable Interpolation (MAY) -- `{arg_name}` = positional arg -- `{$ENV_VAR}` = environment variable -- `{ts}` = timestamp -- ห้าม shell injection — escape always - ---- - -## 14. Documentation Requirements - -### 14.1 Required Files (MUST in each tool repo) - -``` -/ -├── README.md ← User-facing intro -├── docs/ -│ ├── ARCHITECTURE.md ← Design overview, state model, phases -│ ├── COMMAND_CONTRACT.md ← All verbs + response schema -│ ├── CONFIG_SCHEMA.md ← Config file schema -│ ├── AI_AGENT_GUIDE.md ← How AI should use this tool -│ ├── USER_GUIDE.md ← Human user guide -│ ├── POLICY_TIERS.md ← Tier mapping per verb -│ └── TROUBLESHOOTING.md ← Common errors + fixes -├── schema/ -│ ├── config.schema.json ← JSON Schema for config -│ └── response-v.schema.json ← JSON Schema for envelope -├── tests/ -│ ├── harness.js (or .py) ← Unit tests (no external deps) -│ └── golden.js (or .py) ← Integration test -├── package.json (or pyproject.toml) -└── CHANGELOG.md -``` - -### 14.2 Recommended Files (SHOULD) - -``` -├── docs/ -│ ├── examples/ ← End-to-end examples -│ ├── SHELL_ALIASES.md ← Quick aliases -│ └── TMUX_INTEGRATION.md ← Pane patterns -└── configs/ - └── .json ← Example config -``` - -### 14.3 Documentation Requirements per File - -#### README.md (MUST contain) -- Tool name + version -- 1-paragraph description -- Setup (install + first run) -- Usage examples (single-cmd, REPL, pipe) -- Link to docs/ - -#### COMMAND_CONTRACT.md (MUST contain) -- Every verb with full schema -- Tier classification -- Argument list -- Return schema -- Examples -- Error codes specific to verb - -#### AI_AGENT_GUIDE.md (MUST contain) -- When to use (decision tree) -- When NOT to use -- Common patterns -- Anti-patterns -- Composition with other Trinity tools - ---- - -## 15. Test Harness Pattern - -### 15.1 Unit Test Harness (MUST have) - -File: `tests/harness.js` (or `.py`) - -```javascript -#!/usr/bin/env node -// Minimal unit test harness — no external deps -const assert = require('assert'); -const parser = require('../lib/parser'); - -let passed = 0, failed = 0; - -function test(name, fn) { - try { fn(); console.log(`✓ ${name}`); passed++; } - catch (e) { console.log(`✗ ${name}: ${e.message}`); failed++; } -} - -// ─── Parser ─── -test('basic verb + arg', () => { - const r = parser.parse('search auth'); - assert.strictEqual(r.verb, 'search'); -}); - -// ... more tests - -console.log(`\n${passed} passed, ${failed} failed`); -process.exit(failed ? 1 : 0); -``` - -**Invocation:** `node tests/harness.js` — no external services - -### 15.2 Golden Test (MUST have) - -File: `tests/golden.js` - -- Integration test against real dependency (DB, browser, etc.) -- Idempotent (cleanup before/after) -- Must run < 60 seconds -- Exit code = 0 on full pass - -### 15.3 Schema Validation Test (SHOULD have) - -- Validate every example response against `schema/response-v.schema.json` -- Fail if envelope doesn't match - ---- - -## 16. Tool Registry - -### 16.1 Registry Format - -File: `.ai/tools.yaml` (in TRINITY kernel root) - -```yaml -version: 1 -tools: - - name: browser-cli - path: ///Downloads/yai_project/browser-cli - bin: node ///Downloads/yai_project/browser-cli/index.js - schema_version: "2" - capabilities: [browser, navigation, dom, screenshot, assertion] - policy_default: normal - health_check: --health - contract_version: "1.0" - - - name: memory-cli - path: ///Downloads/yai_project/memory-cli - bin: node ///Downloads/yai_project/memory-cli/index.js - schema_version: "1" - capabilities: [search, index, recall, learn] - policy_default: normal - health_check: --health - contract_version: "1.0" - - # ... more tools -``` - -### 16.2 Registry Operations (Trinity kernel) - -```bash -trinity tool list # ดู tools ทั้งหมด -trinity tool register # เพิ่ม tool -trinity tool verify # ตรวจ contract compliance -trinity tool health # ตรวจ health -trinity tool capabilities # ค้น tool ที่มี capability -``` - -### 16.3 Capability Naming Convention - -- lowercase -- hyphen-separated -- noun (resource) or verb (action) -- examples: `browser`, `dom-query`, `screenshot`, `search`, `index`, `delete` - ---- - -## 16a. Contract Compliance Test (v1.1+) - -### 16a.1 Why (MUST) -ถ้ามี TOOL_CONTRACT แต่ไม่มี automated test — tool จะ drift จาก contract เสมอ - -### 16a.2 `trinity-contract-test` CLI - -```bash -trinity-contract-test -``` - -ตัวอย่าง output: -``` -Testing: memory-cli@0.1.0 -───────────────────────── -Binary Interface - ✓ stdin/stdout JSON discipline - ✓ Exit codes match spec - ✓ Single-cmd mode works - ✓ REPL mode works - ✓ Pipe mode works - ✓ Run-file mode works - -Universal Flags - ✓ --config supported - ✓ --run-id supported - ✓ --log-file supported - ✓ --policy supported - ✓ --response-schema supported - ✓ --cmd / --run-file supported - -Discovery - ✓ --help works - ✓ --version works - ✓ --list-commands returns valid JSON - ✓ --describe returns valid JSON - ✗ --health endpoint missing ← FAIL - -Response Envelope - ✓ Success envelope schema valid - ✓ Error envelope schema valid - ✓ action field present (v1.1+) - ✓ All required meta fields present - -Logging - ✓ NDJSON format valid - ✓ Required fields per log line - ✓ Standard events used - -Policy - ✓ Verbs classified in --describe - ✓ Tier enforcement blocks correctly - ✓ POLICY_VIOLATION error code used - -Schema - ✓ Backward compat (v1 supported) - ✓ schema_version embedded - -───────────────────────── -RESULT: 22/23 PASSED, 1 FAILED -``` - -### 16a.3 Test Categories (MUST run) - -| Category | Tests | -|----------|-------| -| Binary Interface | exec modes, exit codes, stdio discipline | -| Universal Flags | all required flags accepted | -| Discovery | help/version/list-commands/describe/health | -| Response Envelope | success/error schema validation | -| Logging | NDJSON format + required fields | -| Policy | tier classification + enforcement | -| Schema | versioning + backward compat | -| Action Namespace | format + registry consistency (v1.1+) | - -### 16a.4 Implementation - -`trinity-contract-test` itself = CLI tool that: -- Spawns target tool with various inputs -- Validates outputs against schemas (JSON Schema) -- Reports per-test result + overall verdict -- Exit code: `0` if all pass, `1` if any fail - -### 16a.5 CI Integration (SHOULD) - -ทุก tool ใน registry ต้องรัน `trinity-contract-test` ใน CI: -- Pre-commit hook -- GitHub Actions / GitLab CI -- Block merge if fail - -### 16a.6 Compliance Levels - -| Level | Definition | -|-------|------------| -| **Bronze** | Pass binary interface + envelope tests | -| **Silver** | + Pass discovery + logging tests | -| **Gold** | + Pass policy + schema + namespace tests | -| **Platinum** | + Pass golden integration tests | - -Trinity kernel SHOULD reject tools below Bronze in production registry - ---- - -## 17. Compliance Checklist - -ก่อน register tool ใน Trinity registry — tool ต้องผ่านทุกข้อต่อไปนี้: - -### Binary Interface -- [ ] รับ 4 execution modes (single-cmd, REPL, pipe, run-file) -- [ ] Exit codes ตาม spec -- [ ] stdin/stdout/stderr discipline ถูก -- [ ] UTF-8 encoding - -### Response Envelope -- [ ] ทุก response มี fields ครบ (`ok`, `command`, `data`, `artifacts`, `error`, `meta`) -- [ ] `meta` มี tool, schema_version, run_id, duration_ms, timestamp -- [ ] Error envelope มี `error.code` + `error.message` -- [ ] Single-line NDJSON output - -### CLI Flags -- [ ] รองรับ `--config`, `--run-id`, `--log-file`, `--policy`, `--response-schema`, `--cmd`, `--run-file` -- [ ] รองรับ `--help`, `--version`, `--list-commands`, `--describe`, `--health` - -### Configuration -- [ ] Config file = JSON (or YAML) -- [ ] Config resolution order ถูก -- [ ] Config schema validation -- [ ] Exit `4` on invalid config - -### Logging -- [ ] NDJSON format เมื่อ `--log-file` ระบุ -- [ ] Required fields per log line ครบ -- [ ] Standard events ใช้ตามที่ spec - -### Policy -- [ ] Verbs classified ใน `--describe` -- [ ] Tier enforcement ก่อน execute -- [ ] Exit `3` + envelope on policy violation - -### Error Codes -- [ ] ใช้ standard codes ที่ตรงสถานการณ์ -- [ ] Tool-specific codes มี prefix -- [ ] `error.recoverable` set ถูกต้อง - -### Schema Versioning -- [ ] Schema version embedded in meta -- [ ] Backward compat รองรับ -- [ ] Deprecation warnings - -### Documentation -- [ ] README.md -- [ ] docs/ARCHITECTURE.md -- [ ] docs/COMMAND_CONTRACT.md -- [ ] docs/AI_AGENT_GUIDE.md -- [ ] docs/USER_GUIDE.md -- [ ] schema/config.schema.json -- [ ] schema/response-v1.schema.json -- [ ] CHANGELOG.md - -### Tests -- [ ] tests/harness.js — unit, no deps, < 5s -- [ ] tests/golden.js — integration, < 60s -- [ ] Schema validation tests - -### Registry -- [ ] เพิ่มใน `.ai/tools.yaml` -- [ ] `trinity tool verify ` ผ่าน -- [ ] `trinity tool health ` ผ่าน - ---- - -## 18. Examples - -### 18.1 Minimal Compliant Tool Skeleton (Node.js) - -```javascript -#!/usr/bin/env node -// memory-cli — minimal contract-compliant skeleton - -const fs = require('fs'); -const path = require('path'); -const readline = require('readline'); - -// ─── Constants ─── -const TOOL_NAME = 'memory-cli'; -const TOOL_VERSION = '0.1.0'; -const SCHEMA_VERSION = '1'; - -// ─── Args parsing ─── -const args = parseArgs(process.argv.slice(2)); -const config = loadConfig(args.config); -const runId = args['run-id'] || generateRunId(); -const policy = args.policy || 'normal'; -const logFile = args['log-file'] ? fs.createWriteStream(args['log-file'], { flags: 'a' }) : null; - -// ─── Discovery flags ─── -if (args.help) { printHelp(); process.exit(0); } -if (args.version) { console.log(`${TOOL_NAME}@${TOOL_VERSION}`); process.exit(0); } -if (args['list-commands']) { send(listCommands()); process.exit(0); } -if (args.describe) { send(describeVerb(args.describe)); process.exit(0); } -if (args.health) { send(healthCheck()); process.exit(0); } - -// ─── Execution mode dispatch ─── -if (args.cmd) { - executeOne(args.cmd).then(env => { send(env); process.exit(env.ok ? 0 : 1); }); -} else if (args['run-file']) { - executeBatch(args['run-file']); -} else { - startRepl(); -} - -// ─── Core ─── -async function executeOne(cmdLine) { - const start = Date.now(); - log({ event: 'command_start', command: cmdLine }); - - try { - const { verb, args: verbArgs } = parseVerb(cmdLine); - - // Policy check - const verbSpec = getVerbSpec(verb); - if (!isPolicyAllowed(verbSpec.tier_required, policy)) { - return errorEnvelope(verb, 'POLICY_VIOLATION', - `Verb '${verb}' requires tier=${verbSpec.tier_required}, current=${policy}`); - } - - // Execute - const data = await runVerb(verb, verbArgs); - const env = successEnvelope(verb, data, Date.now() - start); - log({ event: 'command_end', command: verb, duration_ms: env.meta.duration_ms, ok: true }); - return env; - } catch (e) { - const env = errorEnvelope(cmdLine, e.code || 'INTERNAL_ERROR', e.message); - log({ event: 'command_end', command: cmdLine, ok: false, error: e.message }); - return env; - } -} - -function successEnvelope(command, data, duration_ms) { - return { - ok: true, - command, - data: data || {}, - artifacts: [], - error: null, - meta: { - tool: `${TOOL_NAME}@${TOOL_VERSION}`, - schema_version: SCHEMA_VERSION, - run_id: runId, - duration_ms, - timestamp: new Date().toISOString() - } - }; -} - -function errorEnvelope(command, code, message, details = {}) { - return { - ok: false, - command, - data: null, - artifacts: [], - error: { code, message, details, recoverable: !['INVALID_CONFIG', 'POLICY_VIOLATION', 'INTERNAL_ERROR'].includes(code) }, - meta: { - tool: `${TOOL_NAME}@${TOOL_VERSION}`, - schema_version: SCHEMA_VERSION, - run_id: runId, - duration_ms: 0, - timestamp: new Date().toISOString() - } - }; -} - -function send(envelope) { - process.stdout.write(JSON.stringify(envelope) + '\n'); -} - -function log(entry) { - if (!logFile) return; - logFile.write(JSON.stringify({ - ts: new Date().toISOString(), - level: 'INFO', - tool: TOOL_NAME, - run_id: runId, - ...entry - }) + '\n'); -} - -function generateRunId() { - return `run_${new Date().toISOString().replace(/[:.]/g, '-')}_${Math.random().toString(36).slice(2, 8)}`; -} - -// ... rest of implementation (parseArgs, loadConfig, parseVerb, getVerbSpec, runVerb, etc.) -``` - -### 18.2 Real Use Case — Trinity Loop Calling Tools - -```python -# .ai/cli/commands/loop.py — kernel loop calls tools -import subprocess, json - -def call_tool(tool_bin, command, run_id, policy='normal'): - result = subprocess.run( - [*tool_bin.split(), '--cmd', command, '--run-id', run_id, '--policy', policy, - '--log-file', f'.ai/audit/tool-{tool_bin.split()[-1]}.ndjson'], - capture_output=True, text=True, timeout=60 - ) - return json.loads(result.stdout.strip().split('\n')[-1]) - -# Trinity loop -def trinity_loop(goal, max_iter=10): - run_id = f"run_{goal[:20]}_{int(time.time())}" - - for i in range(max_iter): - # Step 1: get memory context - ctx = call_tool('node memory-cli/index.js', f"search '{goal}'", run_id, 'safe') - if not ctx['ok']: break - - # Step 2: verify evidence - evidence = call_tool('python verify-cli', f"check '{goal}'", run_id, 'safe') - - # ... etc -``` - ---- - -## 19. Migration Path for browser-cli - -browser-cli ปัจจุบันใกล้ contract นี้แล้ว — ส่วนที่ต้องปรับ: - -| Item | Current | Target | Effort | -|------|---------|--------|--------| -| Response envelope v1 | partial | full | 🟡 Med | -| `--list-commands` | ❌ | ✅ | 🟢 Low | -| `--describe ` | ❌ | ✅ | 🟢 Low | -| `--health` | ❌ | ✅ | 🟢 Low | -| `error.recoverable` | partial | full | 🟢 Low | -| `meta.timestamp` | ⚠️ in v2 | required | 🟢 Low | -| Helpers YAML | ✅ | ✅ | - | -| Policy tiers | ✅ | ✅ | - | -| NDJSON log | ✅ | ✅ | - | - -> browser-cli should hit **v2.1** to be fully contract-compliant — small additions, no breaking - ---- - -## 20. Open Questions - -1. **JSON vs YAML config** — บังคับ JSON หรือเปิดเลือก? -2. **Schema location** — ภายใน tool repo หรือ shared schema repo? -3. **Run ID format** — UUID v4 หรือ timestamp-based? -4. **Helper recursion** — helper เรียก helper อื่นได้ไหม? -5. **Streaming responses** — สำหรับ long-running commands ทำยังไง? -6. **Multi-language tools** — Python tool รองรับครบเหมือน Node ไหม? -7. **Tool versioning vs schema versioning** — ผูกกัน หรือแยก? -8. **Error code namespace** — globally unique หรือ tool-scoped? -9. **Capability taxonomy** — มี registry กลางไหม? -10. **MCP bridge mapping** — verb → MCP tool ทำอัตโนมัติ? - ---- - -## Appendix A: browser-cli as Reference - -`browser-cli` เป็น reference implementation: -- ✅ stdin/stdout JSON -- ✅ Schema-locked (v1/v2) -- ✅ NDJSON log -- ✅ Policy tiers (safe/normal/aggressive) -- ✅ Run ID -- ✅ JSON config + helpers YAML -- ✅ REPL + pipe + run-file modes -- ✅ Documentation suite (docs/) - -ทุก tool ใหม่ — ดู browser-cli แล้ว clone pattern - -## Appendix B: JSON Schemas (preview) - -### B.1 Response Envelope v1 -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "required": ["ok", "command", "data", "artifacts", "error", "meta"], - "properties": { - "ok": { "type": "boolean" }, - "command": { "type": "string" }, - "data": { "type": ["object", "null"] }, - "artifacts": { "type": "array", "items": { "$ref": "#/definitions/artifact" } }, - "error": { "oneOf": [{ "type": "null" }, { "$ref": "#/definitions/error" }] }, - "meta": { "$ref": "#/definitions/meta" } - }, - "definitions": { - "artifact": { - "type": "object", - "required": ["type", "path"], - "properties": { - "type": { "enum": ["file", "url", "ref"] }, - "path": { "type": "string" }, - "sha256": { "type": "string" }, - "size_bytes": { "type": "integer" }, - "mime": { "type": "string" } - } - }, - "error": { - "type": "object", - "required": ["code", "message"], - "properties": { - "code": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" }, - "message": { "type": "string" }, - "details": { "type": "object" }, - "recoverable": { "type": "boolean" } - } - }, - "meta": { - "type": "object", - "required": ["tool", "schema_version", "run_id", "duration_ms", "timestamp"], - "properties": { - "tool": { "type": "string" }, - "schema_version": { "type": "string" }, - "run_id": { "type": "string" }, - "duration_ms": { "type": "number", "minimum": 0 }, - "timestamp": { "type": "string", "format": "date-time" } - } - } - } -} -``` - -### B.2 Tool Registry Schema -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "required": ["version", "tools"], - "properties": { - "version": { "const": 1 }, - "tools": { - "type": "array", - "items": { - "type": "object", - "required": ["name", "bin", "schema_version", "capabilities", "contract_version"], - "properties": { - "name": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" }, - "path": { "type": "string" }, - "bin": { "type": "string" }, - "schema_version": { "type": "string" }, - "capabilities": { "type": "array", "items": { "type": "string" } }, - "policy_default": { "enum": ["safe", "normal", "aggressive"] }, - "health_check": { "type": "string" }, - "contract_version": { "type": "string" } - } - } - } - } -} -``` - ---- - -## Changelog - -- **v1.0.0-draft (2026-04-28)** — Initial draft based on browser-cli reference + blueprint synthesis - ---- - -## See also - -- [`00_BLUEPRINT.md`](00_BLUEPRINT.md) — Trinity Big Evolution Blueprint -- `browser-cli/docs/COMMAND_CONTRACT.md` — Reference implementation contract -- `browser-cli/docs/RESPONSE_SCHEMA.md` — Reference v1/v2 schemas -- `browser-cli/docs/POLICY_TIERS.md` — Reference tier mapping +Trinity Protocol may keep internal implementation notes, but the public Tool +Contract authority now lives in `postmunnet/trinity-tool-contract`. diff --git a/docs/specs/INDEX.md b/docs/specs/INDEX.md index 710ff21..3f5622a 100644 --- a/docs/specs/INDEX.md +++ b/docs/specs/INDEX.md @@ -313,7 +313,7 @@ Bootstrap Pack ← Template for new projects |-------------|-----------| | **Master vision** | `00_BLUEPRINT.md` | | **How to scaffold new project** | `00b_BOOTSTRAP_PACK.md` | -| **How to write a CLI tool** | `01_TOOL_CONTRACT.md` | +| **How to write a CLI tool** | `01_TOOL_CONTRACT.md` redirect → [`postmunnet/trinity-tool-contract`](https://github.com/postmunnet/trinity-tool-contract) | | **How verifier works** | `02_VERIFIER_SPEC.md` | | **How loop works** | `03_GOAL_LOOP_SPEC.md` | | **How workflow graph works** | `04_GRAPH_SPEC.md` | @@ -836,7 +836,7 @@ Phase 10 Extension Platform 🌐 Future | 0 | [`INDEX.md`](INDEX.md) | This document — master overview | ~700 | 15 min | | 1 | [`00_BLUEPRINT.md`](00_BLUEPRINT.md) | Master spec v2 | 693 | 30 min | | 2 | [`00b_BOOTSTRAP_PACK.md`](00b_BOOTSTRAP_PACK.md) | Phase 0.5 portability | 1,071 | 25 min | -| 3 | [`01_TOOL_CONTRACT.md`](01_TOOL_CONTRACT.md) | Universal CLI contract | 1,298 | 30 min | +| 3 | [`01_TOOL_CONTRACT.md`](01_TOOL_CONTRACT.md) | Redirect to canonical Tool Contract repo | redirect | 1 min | | 4 | [`02_VERIFIER_SPEC.md`](02_VERIFIER_SPEC.md) | Judge with rules | 710 | 20 min | | 5 | [`03_GOAL_LOOP_SPEC.md`](03_GOAL_LOOP_SPEC.md) | Goal tree + loop | 644 | 20 min | | 6 | [`04_GRAPH_SPEC.md`](04_GRAPH_SPEC.md) | Workflow + authority | 710 | 20 min | diff --git a/docs/specs/en/01_TOOL_CONTRACT.md b/docs/specs/en/01_TOOL_CONTRACT.md index 8f3247b..ab713b9 100644 --- a/docs/specs/en/01_TOOL_CONTRACT.md +++ b/docs/specs/en/01_TOOL_CONTRACT.md @@ -1,820 +1,19 @@ ---- -title: "Trinity Tool Contract v1.1 (English)" -subtitle: "Universal CLI tool contract — POSIX of Trinity" -language: English -version: 1.1.0 -last-updated: 2026-04-28 -note: "Translation of ../01_TOOL_CONTRACT.md (essential parts)" ---- +# Tool Contract (Moved) -# Trinity Tool Contract v1.1 (English) +Canonical spec: -> **Universal contract for CLI tools in Trinity OS ecosystem** -> -> Tool not following this → Trinity kernel won't orchestrate. -> Tool following this fully → plug-and-play with Trinity. +- https://github.com/postmunnet/trinity-tool-contract ---- +Pinned stable ABI: -## Public Freeze Status +- https://github.com/postmunnet/trinity-tool-contract/tree/v1.0.0 -Public ecosystem messaging should treat the Tool Contract as: +Latest validation tooling: -```text -Tool Contract v1.0 = freeze candidate -Current working spec = v1.1.0-draft -``` +- https://github.com/postmunnet/trinity-tool-contract/releases/tag/v1.0.1 -Before declaring a stable external tool interface, Trinity must freeze at -least these 10 surfaces: +This file is kept as a redirect so older Trinity Protocol links do not break. +Do not edit this file as the source of truth. -1. Input envelope -2. Output envelope -3. Exit code meaning -4. Verdict schema -5. Artifact declaration -6. Error taxonomy -7. Retry semantics -8. Idempotency expectation -9. Audit log requirements -10. Security boundary - -Until that checklist is complete, public docs should say **v1.0 freeze -candidate** or **v1.1 draft working spec**, not stable interface. - ---- - -## 0. Compliance Levels - -| Level | Description | -|-------|-------------| -| **MUST** | Required — kernel rejects tool if missing | -| **SHOULD** | Recommended — works but not best practice | -| **MAY** | Optional | - ---- - -## 1. Scope - -### In Scope -- Binary entry point conventions -- Stdin/stdout JSON protocol -- Response envelope schema -- Universal CLI flags -- Logging format (NDJSON) -- Policy tiers (safe/normal/aggressive) -- Error codes -- Schema versioning -- Discovery (`--list-commands`, `--describe`, `--health`) -- Helpers (YAML composition) -- Documentation requirements -- Test harness pattern -- Tool registry format - -### Out of Scope -- ❌ Tool internal architecture -- ❌ Programming language (any works) -- ❌ External libraries -- ❌ Database choice -- ❌ **MCP protocol as default core path** — Trinity is CLI-first by default. - MCP-only capabilities may be wrapped by an adapter, but they must enter - Trinity through the Tool Contract envelope before they reach the audit chain. - ---- - -## 2. Terminology - -| Term | Definition | -|------|-----------| -| **Tool** | CLI binary implementing this contract | -| **Verb / Command** | Action a tool exposes (e.g., `search`, `goto`) | -| **Run** | One invocation of a tool | -| **Run ID** | Unique identifier for a run | -| **Envelope** | Response JSON wrapper | -| **Artifact** | File/data created — kept as truth | -| **Policy** | Tier limiting which verbs allowed | -| **Schema version** | Version of response format | -| **Helper** | YAML composition of commands | - ---- - -## 3. Binary Interface - -### 3.1 Entry Point (MUST) - -```bash - [universal-flags] [tool-flags] [-- ] -``` - -**Examples:** -```bash -memory-cli --config configs/.json --cmd "search 'auth bug'" -browser-cli --config configs/.json --login backend -``` - -### 3.2 Execution Modes (MUST support all 4) - -#### Mode A: Single Command -```bash -memory-cli --cmd "search 'auth bug'" -``` - -#### Mode B: REPL (interactive) -```bash -memory-cli -> search auth -> get r123 -> exit -``` - -#### Mode C: Pipe (stdin) -```bash -echo "search auth -get r123 -exit" | memory-cli -``` - -#### Mode D: Run File -```bash -memory-cli --run-file batch.txt -``` - -### 3.3 Exit Codes (MUST) - -| Code | Meaning | -|------|---------| -| `0` | Success | -| `1` | Generic error | -| `2` | Invalid usage | -| `3` | Policy violation | -| `4` | Configuration error | -| `5` | Permission denied | -| `10` | Timeout | -| `100+` | Tool-specific | - -### 3.4 Stream Discipline (MUST) - -| Stream | Purpose | Format | -|--------|---------|--------| -| **stdin** | Commands input | Plain text (1 command per line) | -| **stdout** | Responses | JSON (NDJSON) | -| **stderr** | Diagnostics | Free-form | - -> **CRITICAL:** stdout must be **machine-parseable JSON only** — no banners, no debug - ---- - -## 4. Response Envelope - -### 4.1 Success Envelope (MUST) - -```json -{ - "ok": true, - "command": "search", - "action": "memory.search", - "data": { "...": "tool-specific" }, - "artifacts": [ - { "type": "file", "path": "./out/result.json", "sha256": "..." } - ], - "error": null, - "meta": { - "tool": "memory-cli@0.1.0", - "schema_version": "1", - "run_id": "run_2026-04-28_xyz", - "duration_ms": 42, - "timestamp": "2026-04-28T12:34:56Z" - } -} -``` - -### 4.2 Error Envelope (MUST) - -```json -{ - "ok": false, - "command": "search", - "action": "memory.search", - "data": null, - "artifacts": [], - "error": { - "code": "INDEX_NOT_FOUND", - "message": "Memory index not initialized", - "details": { "expected_path": "./.memory/index.db" }, - "recoverable": true - }, - "meta": { "...": "..." } -} -``` - -### 4.3 Field Reference - -| Field | Required | Type | -|-------|----------|------| -| `ok` | MUST | boolean | -| `command` | MUST | string (local verb) | -| `action` | MUST (v1.1+) | string (canonical `tool.verb`) | -| `data` | MUST | object\|null | -| `artifacts` | MUST | array | -| `error` | MUST | object\|null | -| `meta` | MUST | object | -| `meta.tool` | MUST | string | -| `meta.schema_version` | MUST | string | -| `meta.run_id` | MUST | string | -| `meta.duration_ms` | MUST | number | -| `meta.timestamp` | MUST | ISO 8601 | - ---- - -## 4a. Action Namespace (v1.1+) - -### Why -- `screenshot` exists in browser-cli AND wordpress-cli — conflict -- `search` exists in memory-cli AND grep-cli — conflict -- Audit needs canonical name - -### Format (MUST) - -``` -. -``` - -### Reserved Namespaces - -| Namespace | Tool | -|-----------|------| -| `browser` | browser-cli | -| `memory` | memory-cli | -| `retro` | retro-cli | -| `verify` | verify-cli | -| `wordpress` | wordpress-cli | -| `ftp` | ftp-cli | -| `seo` | seo-cli | -| `code` | grep-cli | -| `deploy` | deploy-cli | -| `god` | god-team-cli | - -### Examples - -| Local verb | Action namespace | -|-----------|------------------| -| `goto` (browser-cli) | `browser.goto` | -| `screenshot` (browser-cli) | `browser.screenshot` | -| `search` (memory-cli) | `memory.search` | -| `validate` (retro-cli) | `retro.validate` | -| `put` (ftp-cli) | `ftp.put` | - ---- - -## 5. Stdin/Stdout Protocol - -- Each input command = 1 line, terminated by `\n` -- Each output envelope = 1 line, terminated by `\n` (NDJSON) -- No multi-line JSON — single-line only -- UTF-8 encoding -- stdout: line-buffered (flush after each envelope) -- stderr: unbuffered - ---- - -## 6. Universal CLI Flags - -### Required (MUST support) - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--config ` | path | `./.config.json` | Config file | -| `--run-id ` | string | auto | Run correlation | -| `--log-file ` | path | none | NDJSON log output | -| `--policy ` | enum | `normal` | safe/normal/aggressive | -| `--response-schema ` | string | `1` | Schema version | -| `--cmd ""` | string | none | Single command mode | -| `--run-file ` | path | none | Batch from file | - -### Standard (SHOULD support) - -| Flag | Description | -|------|-------------| -| `--help, -h` | Print help | -| `--version, -v` | Print version | -| `--list-commands` | List verbs (JSON) | -| `--describe ` | Verb spec (JSON) | -| `--health` | Health check (JSON) | -| `--quiet, -q` | Suppress stderr | -| `--verbose` | Extra diagnostics | -| `--dry-run` | Validate without effects | - ---- - -## 7. Configuration - -### 7.1 Format (MUST) -- JSON (preferred) -- YAML (acceptable) - -### 7.2 Standard Fields - -```json -{ - "$schema": "https://trinity.local/schemas/tool-config-v1.json", - "version": "1.0", - "tool": "memory-cli", - "run": { - "default_policy": "normal", - "default_log_file": "./logs/memory-cli.ndjson", - "max_duration_ms": 60000 - }, - "paths": { - "data_dir": "./.memory", - "artifact_dir": "./out" - }, - "tool_specific": { "...": "tool-defined" } -} -``` - -### 7.3 Resolution Order (MUST) - -1. `--config` flag -2. ENV `_CONFIG` -3. CWD `./.config.json` -4. CWD `./configs/.json` -5. Built-in default - ---- - -## 8. Logging (NDJSON) - -### Format (MUST when `--log-file`) - -```json -{"ts":"2026-04-28T12:34:56Z","level":"INFO","tool":"memory-cli","run_id":"run_xyz","event":"command_start","command":"search","args":["auth bug"]} -{"ts":"2026-04-28T12:34:56Z","level":"DEBUG","tool":"memory-cli","run_id":"run_xyz","event":"db_query","sql":"SELECT ..."} -{"ts":"2026-04-28T12:34:56Z","level":"INFO","tool":"memory-cli","run_id":"run_xyz","event":"command_end","duration_ms":42,"ok":true} -``` - -### Required Fields - -| Field | Type | -|-------|------| -| `ts` | ISO 8601 UTC | -| `level` | DEBUG/INFO/WARN/ERROR | -| `tool` | tool name | -| `run_id` | correlation | -| `event` | snake_case event | - -### Standard Events - -`run_start`, `run_end`, `command_start`, `command_end`, `policy_violation`, `artifact_created`, `external_call`, `error_caught` - -### Append-only (MUST) - -Log file is append-only. Rotation = new file (don't rewrite). - ---- - -## 9. Policy Tiers - -### Tiers (MUST honor) - -| Tier | Allows | -|------|--------| -| **safe** | Read-only verbs | -| **normal** | + Write verbs | -| **aggressive** | + Destructive verbs | - -### Verb Classification (MUST in `--describe`) - -```json -{ - "verb": "delete", - "tier_required": "aggressive", - "destructive": true, - "writes": true -} -``` - -### Enforcement (MUST) - -Block with exit code `3` + error envelope: - -```json -{ - "ok": false, - "error": { - "code": "POLICY_VIOLATION", - "message": "Verb 'delete' requires tier=aggressive, current=normal" - } -} -``` - ---- - -## 10. Standard Error Codes - -| Code | Meaning | Recoverable | -|------|---------|-------------| -| `INVALID_ARGS` | Bad arguments | true | -| `INVALID_CONFIG` | Config malformed | false | -| `MISSING_DEPENDENCY` | External tool missing | false | -| `POLICY_VIOLATION` | Tier insufficient | false | -| `PERMISSION_DENIED` | FS/network forbidden | false | -| `RESOURCE_NOT_FOUND` | File/record missing | true | -| `RESOURCE_LOCKED` | Lock unavailable | true | -| `RESOURCE_EXHAUSTED` | Disk/memory/quota | true | -| `EXTERNAL_FAILURE` | DB/HTTP/exec failed | true | -| `TIMEOUT` | Operation too long | true | -| `SCHEMA_MISMATCH` | Schema version wrong | false | -| `INTERNAL_ERROR` | Tool bug | false | - -Tool-specific: prefix with tool name (`MEMORY_INDEX_CORRUPT`) - ---- - -## 11. Schema Versioning - -### Rules (MUST) - -- Schema version = string (`"1"`, `"2"`) -- Backward compat: v2 tool MUST support `--response-schema=v1` -- Embed `schema_version` in `meta` - -### Breaking Changes (bump major) -- Remove field -- Change type -- Change semantic -- Add required field - -### Non-breaking (bump minor) -- Add optional field -- Add enum value (clients ignore unknown) - ---- - -## 12. Discovery - -### `--list-commands` (MUST) - -```json -{ - "ok": true, - "command": "list-commands", - "data": { - "tool": "memory-cli@0.1.0", - "commands": [ - { "verb": "search", "tier": "safe", "description": "Hybrid search" }, - { "verb": "learn", "tier": "normal", "description": "Add document" } - ] - } -} -``` - -### `--describe ` (MUST) - -```json -{ - "ok": true, - "data": { - "verb": "search", - "tier_required": "safe", - "destructive": false, - "writes": false, - "args": [ - { "name": "query", "type": "string", "required": true } - ], - "options": [ - { "name": "--limit", "type": "int", "default": 10 } - ] - } -} -``` - -### `--health` (SHOULD) - -```json -{ - "ok": true, - "data": { - "tool": "memory-cli@0.1.0", - "status": "ready", - "checks": [ - { "name": "config_loaded", "ok": true }, - { "name": "db_connection", "ok": true } - ] - } -} -``` - ---- - -## 13. Helpers (YAML) - -### File Format (SHOULD) - -```yaml -helpers: - fresh-search: - args: [query] - description: "Reindex then search" - steps: - - reindex - - search {query} - - weekly-stats: - description: "Stats + recent learnings" - steps: - - stats - - list --since=7d --tag=lesson -``` - -### Invocation - -```bash -memory-cli --cmd "helper fresh-search 'auth bug'" -``` - ---- - -## 14. Documentation Requirements - -### Required Files (MUST) - -``` -/ -├── README.md -├── docs/ -│ ├── ARCHITECTURE.md -│ ├── COMMAND_CONTRACT.md -│ ├── CONFIG_SCHEMA.md -│ ├── AI_AGENT_GUIDE.md -│ ├── USER_GUIDE.md -│ ├── POLICY_TIERS.md -│ └── TROUBLESHOOTING.md -├── schema/ -│ ├── config.schema.json -│ └── response-v.schema.json -├── tests/ -│ ├── harness.js (unit, no deps) -│ └── golden.js (integration) -├── package.json (or pyproject.toml) -└── CHANGELOG.md -``` - ---- - -## 15. Test Harness Pattern - -### Unit (MUST) - -`tests/harness.js`: -- No external dependencies -- Run < 5 seconds -- Exit 0 on full pass - -### Golden (MUST) - -`tests/golden.js`: -- Integration test against real deps -- Run < 60 seconds -- Idempotent - ---- - -## 16. Tool Registry - -### Format - -`.ai/tools.yaml`: - -```yaml -version: 1 -tools: - - name: browser-cli - path: ///Downloads/yai_project/browser-cli - bin: node ///Downloads/yai_project/browser-cli/index.js - schema_version: "2" - capabilities: [browser, dom, screenshot] - policy_default: normal - health_check: --health - contract_version: "1.1" -``` - ---- - -## 16a. Contract Compliance Test - -### `trinity-contract-test ` - -Validates compliance: -- Binary interface (4 modes, exit codes, stdio) -- Universal flags -- Discovery (help/version/list/describe/health) -- Response envelope schema -- Logging (NDJSON format) -- Policy enforcement -- Schema versioning -- Action namespace (v1.1+) - -### Compliance Levels - -| Level | Definition | -|-------|------------| -| **Bronze** | Binary + envelope tests pass | -| **Silver** | + Discovery + logging | -| **Gold** | + Policy + schema + namespace | -| **Platinum** | + Golden integration tests | - -Trinity kernel rejects below Bronze in production registry. - ---- - -## 17. Compliance Checklist - -Before registering a tool: - -### Binary Interface -- [ ] 4 execution modes -- [ ] Exit codes per spec -- [ ] stdio discipline correct -- [ ] UTF-8 encoding - -### Response Envelope -- [ ] All required fields -- [ ] `meta` complete (tool, schema_version, run_id, duration_ms, timestamp) -- [ ] `error.code` + `error.message` on errors -- [ ] Single-line NDJSON - -### CLI Flags -- [ ] Universal flags (`--config`, `--run-id`, `--log-file`, `--policy`, `--response-schema`) -- [ ] Standard flags (`--help`, `--version`, `--list-commands`, `--describe`, `--health`) - -### Configuration -- [ ] JSON or YAML config -- [ ] Resolution order correct -- [ ] Schema validation -- [ ] Exit `4` on invalid - -### Logging -- [ ] NDJSON format with `--log-file` -- [ ] Required fields per line -- [ ] Standard events used - -### Policy -- [ ] Verbs classified -- [ ] Tier enforcement before execute -- [ ] Exit `3` on violation - -### Documentation -- [ ] README.md -- [ ] docs/ARCHITECTURE.md -- [ ] docs/COMMAND_CONTRACT.md -- [ ] docs/AI_AGENT_GUIDE.md -- [ ] schema/config.schema.json -- [ ] schema/response-v1.schema.json - -### Tests -- [ ] tests/harness.js < 5s -- [ ] tests/golden.js < 60s -- [ ] Schema validation tests - -### Registry -- [ ] Added to `.ai/tools.yaml` -- [ ] `trinity-contract-test ` passes -- [ ] `trinity tool health ` passes - ---- - -## 18. Minimal Skeleton (Node.js) - -```javascript -#!/usr/bin/env node -const fs = require('fs'); -const readline = require('readline'); - -const TOOL_NAME = 'memory-cli'; -const TOOL_VERSION = '0.1.0'; -const SCHEMA_VERSION = '1'; - -const args = parseArgs(process.argv.slice(2)); -const config = loadConfig(args.config); -const runId = args['run-id'] || generateRunId(); -const policy = args.policy || 'normal'; -const logFile = args['log-file'] ? fs.createWriteStream(args['log-file'], { flags: 'a' }) : null; - -if (args.help) { printHelp(); process.exit(0); } -if (args.version) { console.log(`${TOOL_NAME}@${TOOL_VERSION}`); process.exit(0); } -if (args['list-commands']) { send(listCommands()); process.exit(0); } -if (args.describe) { send(describeVerb(args.describe)); process.exit(0); } -if (args.health) { send(healthCheck()); process.exit(0); } - -if (args.cmd) { - executeOne(args.cmd).then(env => { send(env); process.exit(env.ok ? 0 : 1); }); -} else if (args['run-file']) { - executeBatch(args['run-file']); -} else { - startRepl(); -} - -async function executeOne(cmdLine) { - const start = Date.now(); - log({ event: 'command_start', command: cmdLine }); - - try { - const { verb, args: verbArgs } = parseVerb(cmdLine); - const verbSpec = getVerbSpec(verb); - - if (!isPolicyAllowed(verbSpec.tier_required, policy)) { - return errorEnvelope(verb, 'POLICY_VIOLATION', - `Verb '${verb}' requires tier=${verbSpec.tier_required}, current=${policy}`); - } - - const data = await runVerb(verb, verbArgs); - const env = successEnvelope(verb, data, Date.now() - start); - log({ event: 'command_end', command: verb, duration_ms: env.meta.duration_ms, ok: true }); - return env; - } catch (e) { - log({ event: 'command_end', command: cmdLine, ok: false, error: e.message }); - return errorEnvelope(cmdLine, e.code || 'INTERNAL_ERROR', e.message); - } -} - -function successEnvelope(command, data, duration_ms) { - return { - ok: true, command, action: `memory.${command}`, - data: data || {}, artifacts: [], error: null, - meta: { - tool: `${TOOL_NAME}@${TOOL_VERSION}`, - schema_version: SCHEMA_VERSION, - run_id: runId, duration_ms, - timestamp: new Date().toISOString() - } - }; -} - -function errorEnvelope(command, code, message, details = {}) { - return { - ok: false, command, action: `memory.${command}`, - data: null, artifacts: [], - error: { code, message, details, - recoverable: !['INVALID_CONFIG', 'POLICY_VIOLATION', 'INTERNAL_ERROR'].includes(code) }, - meta: { /* same as success */ } - }; -} - -function send(envelope) { - process.stdout.write(JSON.stringify(envelope) + '\n'); -} - -function log(entry) { - if (!logFile) return; - logFile.write(JSON.stringify({ - ts: new Date().toISOString(), level: 'INFO', - tool: TOOL_NAME, run_id: runId, ...entry - }) + '\n'); -} -``` - ---- - -## 19. Migration Path: browser-cli to v1.1 - -| Item | Current | Target | Effort | -|------|---------|--------|--------| -| Response envelope v1 | partial | full | Med | -| `--list-commands` | ❌ | ✅ | Low | -| `--describe ` | ❌ | ✅ | Low | -| `--health` | ❌ | ✅ | Low | -| `error.recoverable` | partial | full | Low | -| `meta.timestamp` | ⚠️ in v2 | required | Low | -| Action namespace `browser.*` | ❌ | ✅ | Low | - -→ browser-cli should hit v2.1 to be fully contract-compliant - ---- - -## 20. Open Questions - -1. JSON vs YAML config — enforce JSON? -2. Run ID format — UUID v4 or timestamp-based? -3. Helper recursion — allow helper calling helper? -4. Streaming responses for long-running commands? -5. Multi-language tools — Python tool support same as Node? -6. Tool versioning vs schema versioning — link or separate? -7. Error code namespace — global unique or tool-scoped? -8. Capability taxonomy — central registry? -9. MCP bridge mapping — auto verb → MCP tool? - ---- - -## See also - -- [`README.md`](README.md) -- [`INDEX.md`](INDEX.md) -- [`00_BLUEPRINT.md`](00_BLUEPRINT.md) -- [`12_GLOSSARY.md`](12_GLOSSARY.md) -- [`../01_TOOL_CONTRACT.md`](../01_TOOL_CONTRACT.md) — Thai version (full detail) - ---- - -## Changelog - -- **v1.1.0 (2026-04-28)** — English translation, includes Action Namespace + Compliance Test +Trinity Protocol may keep internal implementation notes, but the public Tool +Contract authority now lives in `postmunnet/trinity-tool-contract`. diff --git a/docs/specs/en/INDEX.md b/docs/specs/en/INDEX.md index ff2c1e1..ace3e3c 100644 --- a/docs/specs/en/INDEX.md +++ b/docs/specs/en/INDEX.md @@ -206,7 +206,7 @@ yai_project/ |-------------|-----------| | Master vision | `00_BLUEPRINT.md` (Thai) or [`00_BLUEPRINT.md`](00_BLUEPRINT.md) (English) | | New project scaffold | `00b_BOOTSTRAP_PACK.md` | -| Write a CLI tool | `01_TOOL_CONTRACT.md` (English available) | +| Write a CLI tool | `01_TOOL_CONTRACT.md` redirect → [`postmunnet/trinity-tool-contract`](https://github.com/postmunnet/trinity-tool-contract) | | How verifier works | `02_VERIFIER_SPEC.md` | | How loop works | `03_GOAL_LOOP_SPEC.md` | | Workflow graph | `04_GRAPH_SPEC.md` | @@ -527,7 +527,7 @@ kernel → mechanical | 0 | INDEX.md (this) | Master overview | ~950 | ✅ | | 1 | 00_BLUEPRINT.md | Master spec | 705 | ✅ | | 2 | 00b_BOOTSTRAP_PACK.md | Phase 0.5 | 1,071 | ⏳ TBD | -| 3 | 01_TOOL_CONTRACT.md | Tool ABI | 1,298 | ✅ | +| 3 | 01_TOOL_CONTRACT.md | Redirect to canonical Tool Contract repo | redirect | ✅ | | 4 | 02_VERIFIER_SPEC.md | Judge | 710 | ⏳ TBD | | 5 | 03_GOAL_LOOP_SPEC.md | Loop | 644 | ⏳ TBD | | 6 | 04_GRAPH_SPEC.md | Graph | 710 | ⏳ TBD |