Skip to content
Draft
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
82 changes: 82 additions & 0 deletions .github/workflows/python-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ on:
push:
paths:
- "python/**"
- "spec/SDK_DAEMON_TARGET_0_4_33.json"
- ".github/workflows/python-integration.yml"
pull_request:
paths:
- "python/**"
- "spec/SDK_DAEMON_TARGET_0_4_33.json"
- ".github/workflows/python-integration.yml"
workflow_dispatch:
inputs:
Expand All @@ -24,6 +26,9 @@ jobs:
- name: Checkout cccc-sdk
uses: actions/checkout@v4

- name: Check SDK hardening contract
run: python3 scripts/check_sdk_hardening.py

- name: Checkout cccc (daemon)
uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -51,3 +56,80 @@ jobs:
trap cleanup EXIT
cccc daemon start
python python/examples/compat_check.py

native-daemon-0433:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- uses: dtolnay/rust-toolchain@1.88.0

- name: Install exact native daemon and Python SDK
run: |
cargo install cccc --version '=0.4.33' --locked
python -m pip install -e python

- name: Verify stable Web Model completion replay
run: |
set -euo pipefail
export CCCC_HOME="$RUNNER_TEMP/cccc-sdk-python-0433"
cccc daemon start
cleanup() {
cccc daemon stop >/dev/null 2>&1 || true
}
trap cleanup EXIT

python - <<'PY'
from cccc_sdk import CCCCClient

client = CCCCClient()
created = client.group_create(title="python-sdk-native-0433")
group_id = str(created.get("group_id") or "")
if not group_id:
raise RuntimeError("group_create did not return group_id")

try:
client.group_start(group_id=group_id)
client.actor_add(
group_id=group_id,
actor_id="web-ci",
runtime="web_model",
runner="headless",
)
client.send(
group_id=group_id,
text="native runtime completion probe",
by="user",
to=["web-ci"],
)
acquired = client.web_model_runtime_wait_next_turn(
group_id=group_id,
actor_id="web-ci",
)
turn = acquired.get("turn") or {}
turn_id = str(turn.get("turn_id") or "")
event_ids = list(turn.get("event_ids") or [])
if not turn_id or not event_ids:
raise RuntimeError(f"wait_next_turn returned no work: {acquired!r}")
delivery_id = f"python-ci:{turn_id}"
options = {
"group_id": group_id,
"actor_id": "web-ci",
"turn_id": turn_id,
"delivery_id": delivery_id,
"event_ids": event_ids,
}
first = client.web_model_runtime_complete_turn(**options)
replay = client.web_model_runtime_complete_turn(**options)
if first.get("delivery_id") != delivery_id or replay.get("delivery_id") != delivery_id:
raise RuntimeError("completion did not preserve delivery_id")
if (first.get("read_event") or {}).get("id") != (replay.get("read_event") or {}).get("id"):
raise RuntimeError("completion replay created a second receipt")
finally:
client.group_delete(group_id=group_id)
PY
48 changes: 46 additions & 2 deletions .github/workflows/rust-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ on:
push:
paths:
- "rust/**"
- "spec/SDK_DAEMON_TARGET_0_4_33.json"
- ".github/workflows/rust-ci.yml"
pull_request:
paths:
- "rust/**"
- "spec/SDK_DAEMON_TARGET_0_4_33.json"
- ".github/workflows/rust-ci.yml"

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check SDK hardening contract
run: python3 scripts/check_sdk_hardening.py
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy,rustfmt
Expand All @@ -23,14 +27,54 @@ jobs:
run: cargo fmt --check
- name: Lint
working-directory: rust
run: cargo clippy --all-targets --all-features -- -D warnings
run: cargo clippy --locked --all-targets --all-features -- -D warnings
- name: Test
working-directory: rust
run: cargo test --all-targets
run: cargo test --locked --all-targets
- name: Package
working-directory: rust
run: cargo package --locked

msrv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.74.0"
- name: Check declared MSRV
working-directory: rust
run: cargo check --locked

windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Test cross-platform cursor replacement
working-directory: rust
run: cargo test --locked --all-targets

native-daemon-0433:
runs-on: ubuntu-latest
env:
CCCC_RUN_LIVE_RELIABILITY: "1"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.88.0
- name: Install exact native daemon
run: cargo install cccc --version '=0.4.33' --locked
- name: Run live reliability contract
run: |
set -euo pipefail
export CCCC_HOME="$RUNNER_TEMP/cccc-sdk-rust-0433"
cccc daemon start
cleanup() {
cccc daemon stop >/dev/null 2>&1 || true
}
trap cleanup EXIT
cargo test --locked --manifest-path rust/Cargo.toml --test live_reliability -- --nocapture

integration:
runs-on: ubuntu-latest
needs: test
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/spec-drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ on:
paths:
- "spec/**"
- "scripts/check_specs_against_cccc.sh"
- "scripts/check_sdk_hardening.py"
- ".github/workflows/spec-drift.yml"
pull_request:
paths:
- "spec/**"
- "scripts/check_specs_against_cccc.sh"
- "scripts/check_sdk_hardening.py"
- ".github/workflows/spec-drift.yml"
schedule:
- cron: "17 3 * * *"
Expand All @@ -36,3 +38,6 @@ jobs:

- name: Compare mirrored standards
run: bash scripts/check_specs_against_cccc.sh cccc-core

- name: Check SDK hardening contract
run: python3 scripts/check_sdk_hardening.py
100 changes: 100 additions & 0 deletions .github/workflows/ts-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ on:
push:
paths:
- "ts/**"
- "spec/SDK_DAEMON_TARGET_0_4_33.json"
- ".github/workflows/ts-ci.yml"
pull_request:
paths:
- "ts/**"
- "spec/SDK_DAEMON_TARGET_0_4_33.json"
- ".github/workflows/ts-ci.yml"

jobs:
Expand All @@ -17,6 +19,9 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Check SDK hardening contract
run: python3 scripts/check_sdk_hardening.py

- uses: actions/setup-node@v4
with:
node-version: "20"
Expand Down Expand Up @@ -171,3 +176,98 @@ jobs:
}
console.log('integration smoke passed', { groupId, eventId: event.id });
JS

native-daemon-0433:
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: ts/package-lock.json

- uses: dtolnay/rust-toolchain@1.88.0

- name: Build TypeScript SDK
working-directory: ts
run: |
npm ci
npm run build

- name: Install exact native daemon
run: cargo install cccc --version '=0.4.33' --locked

- name: Verify stream gating and stable completion replay
run: |
set -euo pipefail
export CCCC_HOME="$RUNNER_TEMP/cccc-sdk-ts-0433"
cccc daemon start
cleanup() {
cccc daemon stop >/dev/null 2>&1 || true
}
trap cleanup EXIT

node --input-type=module <<'JS'
import { CCCCClient, IncompatibleDaemonError } from './ts/dist/index.js';

const client = await CCCCClient.create({ ccccHome: process.env.CCCC_HOME });
const created = await client.groupCreate({ title: 'ts-sdk-native-0433' });
const groupId = String(created.group_id || '');
if (!groupId) throw new Error('groupCreate did not return group_id');

try {
await client.groupStart(groupId);
let streamProbeRejected = false;
try {
await client.assertCompatible({ requireOps: ['events_stream'] });
} catch (error) {
if (error instanceof IncompatibleDaemonError) streamProbeRejected = true;
else throw error;
}
if (!streamProbeRejected) {
throw new Error('native 0.4.33 unexpectedly accepted events_stream probe');
}

await client.actorAdd({
groupId,
actorId: 'web-ci',
runtime: 'web_model',
runner: 'headless',
});
await client.send({
groupId,
text: 'native runtime completion probe',
by: 'user',
to: ['web-ci'],
});
const acquired = await client.webModelRuntimeWaitNextTurn({
groupId,
actorId: 'web-ci',
});
const turn = acquired.turn;
if (!turn || typeof turn !== 'object') {
throw new Error(`waitNextTurn returned no work: ${JSON.stringify(acquired)}`);
}
const turnId = String(turn.turn_id || '');
const eventIds = Array.isArray(turn.event_ids) ? turn.event_ids.map(String) : [];
if (!turnId || eventIds.length === 0) {
throw new Error(`invalid native turn: ${JSON.stringify(turn)}`);
}
const deliveryId = `ts-ci:${turnId}`;
const options = { groupId, actorId: 'web-ci', turnId, deliveryId, eventIds };
const first = await client.webModelRuntimeCompleteTurn(options);
const replay = await client.webModelRuntimeCompleteTurn(options);
if (first.delivery_id !== deliveryId || replay.delivery_id !== deliveryId) {
throw new Error('completion did not preserve delivery_id');
}
if (!first.read_event || !replay.read_event || first.read_event.id !== replay.read_event.id) {
throw new Error('completion replay created a second receipt');
}
} finally {
await client.groupDelete(groupId);
}
JS
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ CCCC line and exposes the IPC surface available on that line.
after an exchange has begun.
- Scheduled CI drift detection for all three mirrored CCCC standards, automatic
Python integration coverage, and a live Rust-SDK/current-daemon smoke job.
- Python and TypeScript Web Model wait/complete helpers with a required stable
`delivery_id`, plus the exact native 0.4.33 replay fixture.
- Rust 0.0.2 identity-bound reliable messaging, durable inbox checkpoints, and
explicit reconciliation for ambiguous send/reply/read outcomes.

### Changed

Expand Down Expand Up @@ -52,6 +56,10 @@ CCCC line and exposes the IPC surface available on that line.
- TypeScript's `INVALID_REQUEST` constant now matches the daemon's
`invalid_request` code and includes current request-size and Remote Access
administrator-token errors.
- TypeScript connection, response, and stream-handshake phases now share one
deadline; handshake cancellation closes the socket, buffered stream data is
byte-capped before decoding, and transport cleanup removes only SDK-owned
listeners.
- The daemon IPC mirror now matches current CCCC core, including Remote Access
administrator-token state and enforcement fields.

Expand All @@ -63,6 +71,18 @@ CCCC line and exposes the IPC surface available on that line.
maps and side-effect-free compatibility probing. TypeScript also compiles
exported option fixtures so documented contract values cannot silently drift
out of the published declaration surface.
- Added exact native 0.4.33 completion/reliability jobs, Rust 1.74 MSRV and
Windows cursor-replacement jobs, and a static SDK hardening contract gate.

## Rust crate [0.0.2] — Unreleased

### Added

- Least-privilege `IdentityBoundClient` adapters for idempotent send, reply,
inbox polling, and mark-read operations.
- Nullable native cursor decoding, authoritative remote-ahead read-state
reconciliation, ledger-order fallback for notifications, and atomic
same-directory `FileCursorStore` replacement.

## Rust crate [0.0.1] — 2026-08-03

Expand Down
5 changes: 3 additions & 2 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ SDK と CCCC Web が同じ `CCCC_HOME` を参照していれば、書き込み
主な用途:
- リアルタイム更新が必要な Web/IDE プラグイン(`events_stream`)
- Working Group を監視して自動応答する bot/service
- identity-bound write と永続 inbox cursor を必要とする高信頼 Rust worker
- group / actors / shared context / capability ポリシー / Group Space をプログラムから管理する社内ツール
- `tracked_send`、Context Ops v3 task/agent state、capability discovery、ローカル memory API を使う workflow 連携

Expand Down Expand Up @@ -90,7 +91,7 @@ python python/examples/auto_ack_attention.py --group g_xxx --actor user

```toml
[dependencies]
cccc-sdk = "0.0.1"
cccc-sdk = "0.0.2"
```

Rust クライアントは `CCCC_HOME` の Unix Socket/TCP daemon を自動検出し、
Expand All @@ -102,7 +103,7 @@ Rust クライアントは `CCCC_HOME` の Unix Socket/TCP daemon を自動検
## バージョニングと互換性

SDK リリースは daemon のバージョン文字列ではなく contract に追従します:
- Python と TypeScript は現在の SDK リリースラインに追従し、Rust crate `0.0.1` から開始します
- Python と TypeScript は現在の SDK リリースラインに追従し、Rust crate は当面 `0.0.x` 系列です
- 実行時互換性は `assert_compatible(...)` で必要な capability/op を指定して確認します。

互換性は “契約/能力” で保証し、バージョン文字列の厳密一致には依存しません:
Expand Down
Loading
Loading