Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ jobs:
- run: pnpm typecheck
- run: pnpm build
- run: pnpm test
env:
POWERCONTEXT_CLIENT_CALLTHROUGH: '1'
- run: pnpm license:check
- run: pnpm generate:check
- run: python conformance/runners/python/run.py --export-check
Expand Down
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@ are published.

### Added

- Official `@powercontext/client` typed HTTP Client: 52 methods, strict
transport, runtime validation, and Python Server call-through for the
`client` / C1 profile.
- Generated Protocol contracts, runtime validators, and C1 wire / canonical
conformance fixtures against the pinned Python OpenAPI 0.0.2 baseline.
- Repository documentation for policies, ADRs, contributing, and security.

### Changed

- Public documentation now describes product profiles and milestones instead of
construction-phase exit reviews.
- OpenAPI-derived request types preserve required fields while leaving
server-defaulted fields optional.
- Undeclared 2xx responses are classified as Server errors, and malformed UTF-8
success bodies are rejected instead of being decoded with replacement text.
- The Python-side DSH reuse design now uses the Client's exact Node range,
`>=22 <25`.
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pnpm lint
pnpm typecheck
pnpm build
pnpm test
# Optional: require Python Server call-through after oracle bootstrap
# POWERCONTEXT_CLIENT_CALLTHROUGH=1 pnpm test
pnpm generate:check
python conformance/runners/python/run.py --export-check
pnpm conformance
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ kit.
## Status

The `client` profile has Protocol types, 52 operation contracts, runtime
validators, and C1 wire / canonical fixtures. The official HTTP Client
transport, Runtime, Server, MCP, and CLI are not shipped.
validators, C1 wire / canonical fixtures, and the official typed HTTP Client.
Runtime, Server, MCP, and CLI are not shipped. Docs claim `client` / C1, not
full-product.

See [Current status](docs/user/README.md) and the
[compatibility policy](docs/policies/compatibility.md).
Expand Down
6 changes: 4 additions & 2 deletions conformance/runners/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ The harness:

1. Verifies the pinned `uv.lock` digest from the baseline lock;
2. Creates `.venv` with `uv` and Python 3.11;
3. Checks out `python_commit` and runs `uv sync --locked --no-dev --no-editable`
into that environment;
3. Checks out `python_commit` and runs
`uv sync --locked --no-dev --no-editable --extra cli --extra server`
into that environment so the pinned Server CLI can start for Client
call-through;
4. Writes and verifies a lock marker containing the Python commit and dependency
lock digest.

Expand Down
4 changes: 4 additions & 0 deletions conformance/runners/python/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ def sync_locked_project(source: Path, python: Path, lock: dict[str, object]) ->
"--locked",
"--no-dev",
"--no-editable",
"--extra",
"cli",
"--extra",
"server",
"--active",
"--python",
str(python),
Expand Down
3 changes: 2 additions & 1 deletion docs/adr/0007-node-lts-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
2. Client 与 Protocol 必须在 Node 22 与 Node 24 上由 CI 验证。`engines` 写
`>=22 <25`,或等价的“支持 22 与 24 LTS”。
3. 不维护 Node 20 兼容构建。EOL 运行时不进入支持矩阵。
4. DSH 插件的 `>=20` 声明必须提升到 `>=22`。改造在 Python 仓库独立 PR 中进行,
4. DSH 插件的 `>=20` 声明必须调整为 `>=22 <25`,与 Client 的已验证范围一致,
不得无测试地宣称支持 Node 25+。改造在 Python 仓库独立 PR 中进行,
可随官方 Client 发布一并落地。在那之前,官方 Client 文档必须写明
Node 20 不受支持。
5. 选择“提升 DSH 最低版本”,不选择“为 Node 20 维持第二套构建”。
Expand Down
1 change: 1 addition & 0 deletions docs/develop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ The only Python → TypeScript channels are contract-sync and the oracle exporte
| --- | --- |
| Package boundaries | [packages.md](packages.md) |
| Protocol generation | [generating-protocol.md](generating-protocol.md) |
| Official Client / DSH reuse | [dsh-reuse.md](dsh-reuse.md) |
| Conformance kit | [conformance.md](conformance.md) |
| Investigation notes | [investigations/README.md](investigations/README.md) |
74 changes: 74 additions & 0 deletions docs/develop/dsh-reuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# DSH plugin reuse of `@powercontext/client`

Phase 3 produces this design. Implementation is a Python-repository pull
request and may wait until the later host-acceptance milestone.

## Current split

The DSH plugin lives in the Python repository at `integrations/dsh`. Today it
owns a generic Fetch client, operation-id dispatch, scope derivation, mutation
approval, secret-like payload guards, PreparedContext wrapping, and fail-open
recall/capture.

The official Client now owns the generic transport. The plugin should depend
on the published `@powercontext/client` package instead of keeping a second
Fetch implementation.

## Move to the official Client

- Base URL normalization
- `Authorization` / `User-Agent` / request-id capture
- Timeout plus caller `AbortSignal`
- Manual redirect rejection
- Bounded response bodies
- JSON / Markdown / download-bytes modes
- Runtime request and success validation
- `transport` / `unavailable` / `server` / `invalid-response` /
`unknown-operation` errors
- Optional tracing injection hook

## Keep in the DSH plugin

- Host scope derivation and long scope hashes
- Mutation approval and curated tool policy
- Secret-like payload rejection
- Fail-open recall/capture so a Server outage does not block the agent
- Host UI, commands, and DSH-specific skill text
- Untrusted-context wrapping for PreparedContext injection

## Node engine

ADR 0007 does not maintain a Node 20 build. The official Client declares
`engines.node: ">=22 <25"`. The plugin's `>=20` declaration must be raised to
`>=22 <25` in the Python-repository PR so it does not claim untested Node 25+
runtimes. Hosts that remain on Node 20 keep calling the Python Server and must
not mark the official Client as supported.

## Suggested adapter

```ts
import { PowerContextClient } from '@powercontext/client'

const official = new PowerContextClient({
baseUrl,
authorization,
timeoutMs: requestTimeoutMs,
fetch,
})

export async function request(id: string, payload?: object, signal?: AbortSignal) {
return official.request(id, payload, { signal })
}
```

The plugin keeps its operation table only if host tooling still needs it.
Wire types and validators come from `@powercontext/protocol` through the
Client. Do not copy OpenAPI snapshots into the plugin.

## Acceptance

- Current DSH unit and E2E behavior must not regress after the Python PR
- Plugin tests may keep host-level mocks; transport cases should use the
official Client
- This repository only publishes the Client and this design. It does not
modify the Python plugin tree
6 changes: 4 additions & 2 deletions docs/develop/packages.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Packages

Public npm names are placeholders until the organization is confirmed.
The `@powercontext/*` names below are the public package contract. npm
namespace ownership and publication credentials are release-operations
prerequisites; they do not change consumer import paths.

| Directory | Package | First milestone |
| --- | --- | --- |
| protocol | `@powercontext/protocol` | M1 |
| client | `@powercontext/client` | M1 |
| client | `@powercontext/client` | M1 (typed HTTP Client) |
| core | `@powercontext/core` | M2 |
| builtin | `@powercontext/builtin` | M2 |
| server | `@powercontext/server` | M2 / M4 |
Expand Down
7 changes: 4 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

| Audience | Start here |
| --- | --- |
| Users | [Current status](user/README.md) |
| Users | [Current status](user/README.md), [Official typed Client](user/client.md) |
| Contributors | [Roadmap](roadmap.md), [CONTRIBUTING.md](../CONTRIBUTING.md), [development notes](develop/README.md) |
| Maintainers | [Policies](policies/README.md), [ADRs](adr/README.md), [RFC ledger](rfcs/README.md) |
| Maintainers | [Policies](policies/README.md), [ADRs](adr/README.md), [M1 exit review](reviews/m1-client-exit-review.md), [RFC ledger](rfcs/README.md) |

[Roadmap](roadmap.md) is the living route. GitHub milestones and issues hold
assignments. Do not add construction-phase folders.
assignments. Exit evidence is stored as auditable review artifacts, not as a
second issue tracker.
2 changes: 1 addition & 1 deletion docs/policies/risks.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ that can block parity or force a route change.
| R6 | Provider | Non-deterministic output used for byte comparison; secrets in CI | Medium | Fake / recorded fixtures on the main path; live providers opt-in | M4 |
| R7 | Migration | Dual writers without a global schema version | High | ADR 0002; do not write existing Python databases until it lands | ADR 0002, M2 |
| R8 | Contract drift | The independent repository silently follows Python `main` | High | Biweekly bump, PR drift check, nightly advisory | [contract-sync.md](contract-sync.md) |
| R9 | DSH Node 20 | Plugin still declares `>=20`; Client is tested on 22 / 24 | Medium | ADR 0007; raise `engines` on the Python side | ADR 0007 |
| R9 | DSH Node range | Plugin still declares `>=20`; Client is tested on 22 / 24 | Medium | ADR 0007; set Python-side `engines` to `>=22 <25` | ADR 0007 |
| R10 | Draft RFC creep | Unimplemented RFC 0048 / 0082 / 1223 clauses become M4 work | Medium | RFC ledger; Draft is not a fact source | [rfc-ledger.yaml](rfc-ledger.yaml) |

When a risk becomes fact, write a compatibility decision before changing
Expand Down
43 changes: 43 additions & 0 deletions docs/reviews/m1-client-exit-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# M1 Client Exit Review

- Review date: 2026-08-26
- Construction scope: Phase 3
- Status: release candidate; final commit-bound CI is still required before npm publication
- Baseline lock: [`contract/baseline.lock.yaml`](../../contract/baseline.lock.yaml), Python commit `733e4bf6b378785e76274ff07632029c699ecb09`
- Target profiles: `client` / C1
- Capability report: [`conformance/reports/typescript.json`](../../conformance/reports/typescript.json) plus the Client transport tests listed below
- OpenAPI digest/count: `a97488e85ab3a9f1db3f1dce720ec74b07c626b1974cc860c67b91cabb22f7e3`; 52 operations; 177 schemas
- Database contract version: not applicable; the Client has no persistence or native database dependency
- MCP protocol/allowlist: not applicable; the Client does not ship an MCP server
- Supported Node/OS/CPU/database: Node 22 and 24; Client CI is configured for Node 22/24, and package smoke is configured for Linux, macOS, and Windows. The local review ran on Node 24.14.1, Windows x64. Database support is not part of this profile.
- Required CI runs: local gates passed on 2026-08-26: format, lint, typecheck, build, full test suite, license header check, generated-artifact drift check, pinned-contract verification, conformance, dependency-license check, and package smoke. The final commit must still pass the repository `quality`, Node 22/24 `client-matrix`, and three-OS `smoke` jobs before publication.
- Differential mismatches: none accepted for the `client` / C1 scope. Undeclared 2xx statuses now follow the Python Client's Server-error classification, and malformed UTF-8 is rejected.
- Security findings: no open Client finding in this review. URL credentials/query tokens, redirects, oversized bodies, malformed success bodies, and unsafe JSON integers are rejected; response bodies and timeouts are bounded.
- Performance budget/result: no standalone latency budget for a network Client. The implementation adds no retry loop, native addon, database, or model call.
- Known limitations: Python remains the semantic oracle and Server. Runtime, persistence, MCP, CLI, Dashboard, and DSH host policy are not shipped. The DSH implementation PR is intentionally deferred to the Python repository. npm publication still requires a final version/credentials and green commit-bound CI.
- Migration/recovery evidence: not applicable to state because the package is stateless. Consumers can roll back by restoring their previous Client package version; the Python Server and databases are unchanged.
- Product-line Go/No-Go and owners: Go for M1 release-candidate review; No-Go for npm publication until final commit-bound CI passes. Owners: `product-owner`, `protocol-owner`, and `conformance-owner`.
- Succession conclusion: `keep-python-mainline`
- Remaining Python-only capabilities: all local Runtime, SQLite/OceanBase persistence, inference/provider integration, HTTP Server, MCP, CLI, Dashboard, and host integrations
- Cutover / dual-run / rollback-to-Python evidence: the TypeScript Client calls the unchanged pinned Python Server. No database writer or Server cutover occurs. DSH stays on its existing Python-repository implementation until its separate adapter PR passes existing unit/E2E tests.
- Authority recommendation: keep the pinned Python implementation as semantic oracle; use the pinned OpenAPI snapshot plus generated validators for `client` / C1 wire enforcement

## Phase 3 acceptance evidence

| Requirement | Result | Evidence |
| --- | --- | --- |
| Transport core | Pass | [`packages/client/tests/transport.test.ts`](../../packages/client/tests/transport.test.ts) covers URL/auth/User-Agent/request ID, timeout, caller abort, redirect, body bound, JSON, text, and bytes. |
| 52 typed methods | Pass | Generated `OperationId` mapping, compile-time request assertions in [`packages/client/tests/request-types.ts`](../../packages/client/tests/request-types.ts), and 52-method runtime enumeration. |
| Success runtime validation and error layers | Pass | Protocol-generated validators plus invalid JSON/schema/UTF-8/status tests; public error classes are exercised by Client tests. |
| Optional tracing hook | Pass | [`packages/client/tests/tracing.test.ts`](../../packages/client/tests/tracing.test.ts); no OpenTelemetry SDK dependency. |
| TypeScript Client to Python Server 52/52 | Pass locally | [`packages/client/tests/call-through.test.ts`](../../packages/client/tests/call-through.test.ts) starts the pinned Python Server and requires every operation to return either a validated success or an OpenAPI-declared Server error. |
| DSH reuse design | Pass for Phase 3 design scope | [`docs/develop/dsh-reuse.md`](../develop/dsh-reuse.md) moves generic transport to the official Client, preserves host policy, and aligns the plugin engine to `>=22 <25`. Python-repository implementation remains a later acceptance item. |
| Release docs and compatibility | Pass | [`packages/client/README.md`](../../packages/client/README.md) provides install, quickstart, compatibility, transport, errors, and DSH boundaries. |
| Clean, no-native tarball | Pass locally | `pnpm pack:smoke` builds and installs the packed Protocol and Client in a clean temporary project and rejects native dependencies or unexpected tarball files. |

## Release decision

The Phase 3 implementation and local acceptance gates are complete for the
M1 release candidate. This review does not substitute for CI on the final
commit and does not claim that npm publication has occurred. M1 may be
published only after the commit-bound gates above are green.
5 changes: 3 additions & 2 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The 2026-08-23 construction study is background only. It is not the tracker.
| --- | --- |
| Protocol types, 52 operation contracts, runtime validators | Done |
| C1 wire and canonical conformance fixtures | Done |
| Official typed HTTP Client transport | Not started |
| Official typed HTTP Client transport | M1 release candidate (`client` / C1); see [exit review](reviews/m1-client-exit-review.md) |
| Deterministic Core, SQLite Runtime, Server, MCP, CLI | Not started |

Python remains the reference implementation and semantic oracle.
Expand Down Expand Up @@ -75,7 +75,8 @@ the RFC ledger.
2. Issues for the workstreams above. Labels name the area (`client`, `core`,
`persistence`, `conformance`), not a construction phase.
3. Closing a milestone updates [Current status](user/README.md) and
[CHANGELOG.md](../CHANGELOG.md). Do not add stage-exit review folders.
[CHANGELOG.md](../CHANGELOG.md), and records the applicable evidence in an
auditable [exit review](reviews/m1-client-exit-review.md).

## Background

Expand Down
14 changes: 10 additions & 4 deletions docs/user/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ reference and semantic oracle.

| Surface | Status |
| --- | --- |
| Protocol types, operation metadata, and runtime validators | Available (`client` / C1 foundation) |
| Official typed HTTP Client transport | Not shipped |
| Protocol types, operation metadata, and runtime validators | Available (`client` / C1) |
| Official typed HTTP Client transport | M1 release candidate (`client` / C1) |
| SQLite / OceanBase Runtime | Not shipped |
| HTTP Server, MCP, CLI, Dashboard | Not shipped |

Installable packages currently publish packable skeletons. Protocol and Client
tarballs must install without compiling a native addon.
`@powercontext/client` is the first independently packable product. Install it, import
`PowerContextClient`, and call operations against a compliant Server. Protocol
and Client tarballs must install without compiling a native addon.

See [Official typed Client](client.md).

The auditable acceptance record is the
[M1 Client exit review](../reviews/m1-client-exit-review.md).

See [Compatibility policy](../policies/compatibility.md) for what each profile
may claim.
23 changes: 23 additions & 0 deletions docs/user/client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Official typed Client

`@powercontext/client` is the M1 product. It is a Fetch-based typed HTTP
Client for the pinned OpenAPI snapshot (52 operations). Install it in a clean
project, import `PowerContextClient`, and call operations against a compliant
Server.

This package claims **`client` / C1** only. It is not a local Runtime, SQLite
database, MCP server, CLI, or full-product replacement for Python.

## Support matrix

| Surface | Claim |
| --- | --- |
| Protocol types and runtime validators | Available |
| Typed methods for 52 operations | Available |
| TypeScript Client → Python Server | C1 wire parity |
| Node 22 and Node 24 LTS | Supported |
| Node 20 | Not supported |
| Native addons on install | None |

See the [package README](../../packages/client/README.md) for the quickstart
and transport rules.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "powercontext-ts",
"private": true,
"version": "0.0.0",
"description": "TypeScript PowerContext workspace. Public package names are placeholders until npm org confirmation.",
"description": "TypeScript PowerContext workspace for the official Client and parity implementation.",
"license": "Apache-2.0",
"type": "module",
"packageManager": "pnpm@10.33.2",
Expand Down
Loading
Loading