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
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* @0xNyk
/.github/workflows/* @0xNyk
/scripts/* @0xNyk
10 changes: 10 additions & 0 deletions .github/workflows/capability-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
repository: 0xNyk/xint-rs
path: xint-rs


- name: Setup Bun
uses: oven-sh/setup-bun@v2

Expand All @@ -27,10 +28,19 @@ jobs:
- name: Install xint deps
run: bun install --frozen-lockfile


- name: Generate manifests
run: |
bun run xint.ts capabilities --compact > /tmp/xint-ts-capabilities.json
cargo run --manifest-path xint-rs/Cargo.toml -- capabilities --compact > /tmp/xint-rs-capabilities.json

- name: Check contract parity
run: bun scripts/check-capability-contract.mjs /tmp/xint-ts-capabilities.json /tmp/xint-rs-capabilities.json

- name: Run MCP envelope contract tests (TypeScript)
run: bun test lib/mcp-envelope-contract.test.ts

- name: Run MCP envelope contract tests (Rust)
run: |
cargo test --manifest-path xint-rs/Cargo.toml mcp::costs_tool_returns_success_payload_without_network
cargo test --manifest-path xint-rs/Cargo.toml mcp::cache_clear_tool_returns_success_payload
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
checks:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.5"

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Typecheck
run: bun run typecheck

- name: Test
run: bun run test
26 changes: 26 additions & 0 deletions .github/workflows/guardrails-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Guardrails Audit

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
schedule:
- cron: "15 6 * * *"

jobs:
audit:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Audit xint guardrails drift
env:
GH_TOKEN: ${{ github.token }}
OWNER: 0xNyk
REPOS: xint
BRANCH: main
run: ./scripts/audit-guardrails.sh
67 changes: 67 additions & 0 deletions .github/workflows/mcp-nightly-regression.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: MCP Nightly Regression

on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:

jobs:
regression:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout xint
uses: actions/checkout@v4

- name: Checkout xint-rs
uses: actions/checkout@v4
with:
repository: 0xNyk/xint-rs
path: xint-rs

- name: Checkout xint-cloud
uses: actions/checkout@v4
with:
repository: 0xNyk/xint-cloud
path: xint-cloud

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Install xint deps
run: bun install --frozen-lockfile

- name: Install xint-cloud deps
run: bun install --frozen-lockfile
working-directory: xint-cloud

- name: Generate manifests
run: |
bun run xint.ts capabilities --compact > /tmp/xint-ts-capabilities.json
cargo run --manifest-path xint-rs/Cargo.toml -- capabilities --compact > /tmp/xint-rs-capabilities.json

- name: Check contract parity
run: bun scripts/check-capability-contract.mjs /tmp/xint-ts-capabilities.json /tmp/xint-rs-capabilities.json

- name: Check release version parity
run: >
bun scripts/check-release-version-parity.mjs
package.json
xint-rs/Cargo.toml
/tmp/xint-ts-capabilities.json
/tmp/xint-rs-capabilities.json

- name: Run MCP envelope contract tests (TypeScript)
run: bun test lib/mcp-envelope-contract.test.ts

- name: Run MCP envelope contract tests (Rust)
run: |
cargo test --manifest-path xint-rs/Cargo.toml mcp::costs_tool_returns_success_payload_without_network
cargo test --manifest-path xint-rs/Cargo.toml mcp::cache_clear_tool_returns_success_payload

- name: Run package API smoke tests (xint-cloud create/query/publish)
run: bun test src/server.test.ts --filter "package status/search/query/publish/refresh endpoints operate on persisted package state"
working-directory: xint-cloud
45 changes: 45 additions & 0 deletions .github/workflows/release-parity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Release Parity

on:
release:
types: [published]
workflow_dispatch:

jobs:
parity:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout xint
uses: actions/checkout@v4

- name: Checkout xint-rs
uses: actions/checkout@v4
with:
repository: 0xNyk/xint-rs
path: xint-rs

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Install xint deps
run: bun install --frozen-lockfile

- name: Generate manifests
run: |
bun run xint.ts capabilities --compact > /tmp/xint-ts-capabilities.json
cargo run --manifest-path xint-rs/Cargo.toml -- capabilities --compact > /tmp/xint-rs-capabilities.json

- name: Check capability contract parity
run: bun scripts/check-capability-contract.mjs /tmp/xint-ts-capabilities.json /tmp/xint-rs-capabilities.json

- name: Check release version parity
run: >
bun scripts/check-release-version-parity.mjs
package.json
xint-rs/Cargo.toml
/tmp/xint-ts-capabilities.json
/tmp/xint-rs-capabilities.json
51 changes: 51 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,57 @@ lib/format.ts Output formatters (terminal + markdown)
- Mention your Bun version (`bun --version`)
- Don't include API keys or tokens in issue reports

## Branch Protection

`main` should enforce:
- required status checks
- at least 1 approving review
- stale review dismissal on new commits
- conversation resolution before merge
- linear history
- no force pushes or deletions

Automation script:

```bash
cd xint
./scripts/apply-branch-protection.sh --dry-run
./scripts/apply-branch-protection.sh --apply
```

Scope:
- `0xNyk/xint`: `CI / checks`, `Capability Contract / parity`
- `0xNyk/xint-rs`: `CI / checks`
- `0xNyk/xint-cloud`: `ci / checks`

Repository rulesets (hard guardrails):

```bash
cd xint
./scripts/apply-repo-rulesets.sh --dry-run
./scripts/apply-repo-rulesets.sh --apply
```

Ruleset name:
- `Main Branch Guardrails`

Code owners:
- `.github/CODEOWNERS` defines required owners for all paths.
- Branch protection and rulesets enforce code-owner reviews.

Guardrail drift audit:

```bash
cd xint
./scripts/audit-guardrails.sh
```

Optional strict merge-queue assertion (if your GitHub tier exposes merge-queue rulesets):

```bash
REQUIRE_MERGE_QUEUE=true ./scripts/audit-guardrails.sh
```

## License

By contributing, you agree that your contributions will be licensed under the MIT License.
22 changes: 22 additions & 0 deletions lib/action_result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ActionResultType } from "./actions";

export type ActionExecutionKind = Extract<ActionResultType, "success" | "error" | "info">;

export type ActionExecutionResult<T = unknown> = {
type: ActionExecutionKind;
message: string;
data?: T;
fallbackUsed: boolean;
};

export function actionSuccess<T>(message: string, data?: T, fallbackUsed = false): ActionExecutionResult<T> {
return { type: "success", message, data, fallbackUsed };
}

export function actionInfo<T>(message: string, data?: T, fallbackUsed = false): ActionExecutionResult<T> {
return { type: "info", message, data, fallbackUsed };
}

export function actionError(message: string): ActionExecutionResult<never> {
return { type: "error", message, fallbackUsed: false };
}
29 changes: 29 additions & 0 deletions lib/actions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, expect, test } from "bun:test";
import {
INTERACTIVE_ACTIONS,
normalizeInteractiveChoice,
scoreInteractiveAction,
} from "./actions";

describe("interactive action registry", () => {
test("normalizes key and alias inputs", () => {
expect(normalizeInteractiveChoice("1")).toBe("1");
expect(normalizeInteractiveChoice("search")).toBe("1");
expect(normalizeInteractiveChoice("Q")).toBe("0");
});

test("rejects unknown choices", () => {
expect(normalizeInteractiveChoice("")).toBe("");
expect(normalizeInteractiveChoice("unknown")).toBe("");
});

test("scores direct alias matches", () => {
const search = INTERACTIVE_ACTIONS.find((action) => action.key === "1");
expect(search).toBeDefined();
if (!search) return;

const direct = scoreInteractiveAction(search, "search");
const partial = scoreInteractiveAction(search, "sea");
expect(direct).toBeGreaterThan(partial);
});
});
Loading
Loading