Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Release

on:
push:
tags:
- 'sdk-v*'
- 'v*'
release:
types: [published]

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
cache: npm
cache-dependency-path: typescript-sdk/package-lock.json

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install root npm metadata
run: npm install

- name: Install TypeScript dependencies
working-directory: typescript-sdk
run: npm ci

- name: TypeScript typecheck
working-directory: typescript-sdk
run: npm run typecheck

- name: TypeScript build
working-directory: typescript-sdk
run: npm run build

- name: TypeScript tests
working-directory: typescript-sdk
run: npm run test

- name: Install Python dependencies
working-directory: python-sdk
run: pip install -e '.[dev]'

- name: Python lint
working-directory: python-sdk
run: python -m ruff check .

- name: Python type check
working-directory: python-sdk
run: python -m mypy commandlayer

- name: Python tests
working-directory: python-sdk
run: python -m pytest tests/ -v

- name: Build npm package
working-directory: typescript-sdk
run: npm pack --dry-run

- name: Build Python package
working-directory: python-sdk
run: python -m build

- name: Validate Python package
working-directory: python-sdk
run: python -m twine check dist/*

- name: Publish npm
if: github.event_name == 'push' || github.event_name == 'release'
working-directory: typescript-sdk
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish PyPI
if: github.event_name == 'push' || github.event_name == 'release'
working-directory: python-sdk
run: python -m twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
51 changes: 51 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Contributing

## Repo structure

- `typescript-sdk/` — npm package, CLI, and runtime-facing verification code.
- `python-sdk/` — PyPI package and Python verification code.
- `runtime/tests/` — cross-SDK tests that execute against `typescript-sdk/dist`.
- `test_vectors/` — shared fixtures for receipts, ENS cases, malformed inputs, and rotation cases.
- root docs — public usage docs plus maintainer/release policy docs.

## Install dependencies

```bash
npm install
cd python-sdk && pip install -e '.[dev]'
```

## Run TypeScript tests

```bash
npm run build
npm run test
```

## Run Python tests

```bash
cd python-sdk
pytest
```

## Run runtime tests without guessing about build order

```bash
npm run test:full
```

## `test_vectors/`

`test_vectors/` contains shared canonical receipts, ENS resolution cases, invalid signature cases, key rotation cases, and envelope-vs-receipt coverage used by both SDKs and the runtime tests.

## Pull requests

- keep changes scoped to the task,
- update shared docs and fixtures when behavior changes,
- run the relevant test commands before opening the PR,
- describe user-visible behavior changes and release impact clearly.

## Release rules

Release process and publish requirements live in `RELEASE_GUIDE.md`.
34 changes: 21 additions & 13 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ const response = await client.explain({

```ts
const response = await client.format({
content: "a: 1\nb: 2",
content: "a: 1
b: 2",
to: "table"
});
```
Expand Down Expand Up @@ -162,7 +163,8 @@ cleaned = client.clean(content=" test@example.com ", operations=["trim", "red
converted = client.convert(content='{"a":1}', from_format="json", to_format="csv")
description = client.describe(subject="receipt verification")
explanation = client.explain(subject="receipt verification", style="step-by-step")
formatted = client.format(content="a: 1\nb: 2", to="table")
formatted = client.format(content="a: 1
b: 2", to="table")
parsed = client.parse(content='{ "a": 1 }', content_type="json", mode="strict")
fetched = client.fetch(source="https://example.com", include_metadata=True)
```
Expand Down Expand Up @@ -207,30 +209,36 @@ result = verify_receipt(

## 5. CLI examples

The CLI has two usage layers:
- verb-specific commands such as `summarize` and `analyze` for the fast, common paths,
- `call` for generic or less common verbs when you want to provide the raw JSON body yourself.

### Summarize

```bash
commandlayer summarize \
--content "CommandLayer defines semantic verbs." \
--style bullet_points \
--json
commandlayer summarize --content "CommandLayer defines semantic verbs." --style bullet_points --json
```

### Analyze

```bash
commandlayer analyze \
--content "Invoice total: $500" \
--goal "detect finance intent" \
--json
commandlayer analyze --content "Invoice total: $500" --goal "detect finance intent" --json
```

### Generic call

```bash
commandlayer call --verb classify --body '{"content":"Contact support@example.com"}' --json
```

### Verify a saved receipt

`commandlayer verify` accepts either:
- a canonical receipt JSON object, or
- a full response envelope JSON object with a top-level `receipt` field.

```bash
commandlayer verify \
--file receipt.json \
--public-key "ed25519:BASE64_PUBLIC_KEY"
commandlayer verify --file receipt.json --public-key "ed25519:BASE64_PUBLIC_KEY"
```

## 6. Runtime override
Expand Down
32 changes: 23 additions & 9 deletions DEVELOPER_EXPERIENCE.md → MAINTAINER_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Developer Experience Guide
# Maintainer Guide

This document is for maintainers and advanced integrators. Start with `README.md` or `QUICKSTART.md` if you are adopting the SDK.
This document is for maintainers changing SDK internals, fixtures, CI, or release mechanics. It is not for application developers using the SDK in their own projects; use `README.md`, `QUICKSTART.md`, or the package READMEs instead.

## Product rules this repo now enforces

Expand All @@ -15,7 +15,7 @@ This document is for maintainers and advanced integrators. Start with `README.md
- `python-sdk/`: PyPI package and Python verification helpers.
- `test_vectors/`: shared receipt fixtures used across SDKs.
- `runtime/tests/`: cross-SDK protocol checks run against the built TypeScript package.
- root docs: public landing page, quickstart, examples, and release guide.
- root docs: public landing page, quickstart, examples, contributor guide, versioning policy, and release guide.

## Shared protocol model

Expand All @@ -40,8 +40,8 @@ Clients normalize runtime responses into:

```json
{
"receipt": { ...canonical signed receipt... },
"runtime_metadata": { ...optional unsigned context... }
"receipt": { "...": "canonical signed receipt" },
"runtime_metadata": { "...": "optional unsigned context" }
}
```

Expand All @@ -66,17 +66,31 @@ Both SDKs use the same verification contract:
3. recompute `sha256`,
4. compare against `metadata.proof.hash_sha256`,
5. verify the Ed25519 signature over the UTF-8 hash string,
6. optionally discover the signing key via ENS.
6. resolve signer keys via ENS when an explicit key is not provided,
7. when a receipt carries `kid`, prefer the matching `cl.sig.pub.<kid>` record so older receipts still verify after key rotation.

## CLI rules

The npm package owns the primary `commandlayer` CLI.
The npm package owns the only supported `commandlayer` CLI. The Python package does not ship a CLI.

The CLI should remain:
- installable with `npm install -g @commandlayer/sdk`,
- aligned with SDK examples,
- useful for CI smoke tests,
- capable of verifying saved receipts.
- capable of verifying saved receipts or full response envelopes.

## Test execution and ordering

`runtime/tests` import `typescript-sdk/dist/index.cjs`, so a fresh clone must build the TypeScript SDK before running runtime tests.

Use the root scripts to avoid hidden ordering requirements:

```bash
npm install
npm run test:full
```

`npm run test:full` runs the TypeScript install/build/tests, then the runtime tests against the built output.

## Maintenance checklist

Expand All @@ -85,4 +99,4 @@ When protocol versions change:
2. update root docs and per-package READMEs,
3. regenerate or update shared fixtures,
4. run both SDK test suites plus `runtime/tests`,
5. confirm release instructions in `DEPLOYMENT_GUIDE.md` still match reality.
5. confirm release automation and `RELEASE_GUIDE.md` still match reality.
21 changes: 11 additions & 10 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ pip install commandlayer

### CLI

The CLI ships with the npm package:
The CLI ships with the TypeScript/npm package only:

```bash
npm install -g @commandlayer/sdk
```

The Python SDK does not ship a CLI. Python users should use the TypeScript CLI or call the Python API directly.

## 2. Make your first call

### TypeScript
Expand Down Expand Up @@ -117,24 +119,22 @@ Use the same signer-discovery model in both SDKs:
- agent ENS TXT: `cl.receipt.signer`
- signer ENS TXT: `cl.sig.pub`
- signer ENS TXT: `cl.sig.kid`
- signer ENS TXT: `cl.sig.pub.<kid>` for older receipts after key rotation

## 5. Try the CLI

```bash
commandlayer summarize \
--content "CommandLayer makes agent execution verifiable." \
--style bullet_points \
--json
commandlayer summarize --content "CommandLayer makes agent execution verifiable." --style bullet_points --json
```

Save the returned JSON and verify it:

```bash
commandlayer verify \
--file receipt.json \
--public-key "ed25519:BASE64_PUBLIC_KEY"
commandlayer verify --file receipt.json --public-key "ed25519:BASE64_PUBLIC_KEY"
```

`commandlayer verify` accepts either a canonical receipt JSON object or a full response envelope with a top-level `receipt` field. New integrations should pass the canonical receipt explicitly.

## 6. What is stable today?

Stable in this repo:
Expand All @@ -152,5 +152,6 @@ Not claimed as first-class SDK support here:

- More recipes: `EXAMPLES.md`
- Package docs: `typescript-sdk/README.md`, `python-sdk/README.md`
- Maintainer notes: `DEVELOPER_EXPERIENCE.md`
- Release flow: `DEPLOYMENT_GUIDE.md`
- Contributor workflow: `CONTRIBUTING.md`
- Maintainer notes: `MAINTAINER_GUIDE.md`
- Release flow: `RELEASE_GUIDE.md`
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ const result = await verifyReceipt(response.receipt, {
ENS signer discovery resolves:
1. `cl.receipt.signer` on the agent ENS name,
2. `cl.sig.pub` on the signer ENS name,
3. `cl.sig.kid` on the signer ENS name.
3. `cl.sig.kid` on the signer ENS name,
4. `cl.sig.pub.<kid>` on the signer ENS name when verifying an older receipt after key rotation.

## CLI

Expand All @@ -158,13 +159,21 @@ commandlayer summarize --content "Test text" --style bullet_points --json
commandlayer verify --file receipt.json --public-key "ed25519:BASE64_PUBLIC_KEY"
```

The TypeScript SDK includes the `commandlayer` CLI. The Python SDK does not include a CLI.

Python users should either:
- use the TypeScript CLI for smoke tests, demos, and CI workflows, or
- use the Python API directly inside Python applications and scripts.

The CLI is intended for demos, CI smoke tests, debugging, and reproducing SDK flows without writing app code.

## Repo guide

- Fast onboarding: `QUICKSTART.md`
- Cookbook examples: `EXAMPLES.md`
- Maintainer / architecture notes: `DEVELOPER_EXPERIENCE.md`
- Build, release, and publish flow: `DEPLOYMENT_GUIDE.md`
- Contributor workflow: `CONTRIBUTING.md`
- Maintainer / release operations: `MAINTAINER_GUIDE.md`
- Build, release, and publish flow: `RELEASE_GUIDE.md`
- Versioning policy: `VERSIONING.md`
- TypeScript package docs: `typescript-sdk/README.md`
- Python package docs: `python-sdk/README.md`
Loading
Loading