agent-crossbar 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. agent_crossbar-0.2.0/.github/allowed_signers +1 -0
  2. agent_crossbar-0.2.0/.github/dependabot.yml +19 -0
  3. agent_crossbar-0.2.0/.github/workflows/ci.yml +186 -0
  4. agent_crossbar-0.2.0/.github/workflows/live-gate.yml +93 -0
  5. agent_crossbar-0.2.0/.github/workflows/release.yml +200 -0
  6. agent_crossbar-0.2.0/.github/workflows/security.yml +89 -0
  7. agent_crossbar-0.2.0/.gitignore +12 -0
  8. agent_crossbar-0.2.0/.gitleaks.toml +11 -0
  9. agent_crossbar-0.2.0/AGENTS.md +43 -0
  10. agent_crossbar-0.2.0/CHANGELOG.md +40 -0
  11. agent_crossbar-0.2.0/CODE_OF_CONDUCT.md +50 -0
  12. agent_crossbar-0.2.0/CONTRIBUTING.md +50 -0
  13. agent_crossbar-0.2.0/LICENSE +21 -0
  14. agent_crossbar-0.2.0/PKG-INFO +12 -0
  15. agent_crossbar-0.2.0/PUBLIC-SNAPSHOT.json +374 -0
  16. agent_crossbar-0.2.0/README.md +223 -0
  17. agent_crossbar-0.2.0/SECURITY.md +39 -0
  18. agent_crossbar-0.2.0/bin/agent-crossbar.mjs +37 -0
  19. agent_crossbar-0.2.0/demo/PROMPTS.md +25 -0
  20. agent_crossbar-0.2.0/demo/RECORDING.md +22 -0
  21. agent_crossbar-0.2.0/demo/TRANSCRIPT.md +18 -0
  22. agent_crossbar-0.2.0/demo/fixture/crossbar_demo.py +6 -0
  23. agent_crossbar-0.2.0/demo/metadata.json +10 -0
  24. agent_crossbar-0.2.0/docs/releases/v0.2.0.md +50 -0
  25. agent_crossbar-0.2.0/package.json +27 -0
  26. agent_crossbar-0.2.0/pyproject.toml +55 -0
  27. agent_crossbar-0.2.0/src/agent_crossbar/__init__.py +1 -0
  28. agent_crossbar-0.2.0/src/agent_crossbar/acp_client.py +422 -0
  29. agent_crossbar-0.2.0/src/agent_crossbar/acp_lifecycle.py +240 -0
  30. agent_crossbar-0.2.0/src/agent_crossbar/acp_runtime.py +389 -0
  31. agent_crossbar-0.2.0/src/agent_crossbar/adapters/__init__.py +5 -0
  32. agent_crossbar-0.2.0/src/agent_crossbar/adapters/base.py +89 -0
  33. agent_crossbar-0.2.0/src/agent_crossbar/adapters/chatgpt_pro.py +20 -0
  34. agent_crossbar-0.2.0/src/agent_crossbar/adapters/claude.py +510 -0
  35. agent_crossbar-0.2.0/src/agent_crossbar/adapters/claude_model_probe.py +781 -0
  36. agent_crossbar-0.2.0/src/agent_crossbar/adapters/codex.py +145 -0
  37. agent_crossbar-0.2.0/src/agent_crossbar/adapters/opencode.py +253 -0
  38. agent_crossbar-0.2.0/src/agent_crossbar/adapters/reasonix.py +20 -0
  39. agent_crossbar-0.2.0/src/agent_crossbar/adapters/registry.py +21 -0
  40. agent_crossbar-0.2.0/src/agent_crossbar/agent_runner.py +435 -0
  41. agent_crossbar-0.2.0/src/agent_crossbar/cli.py +109 -0
  42. agent_crossbar-0.2.0/src/agent_crossbar/context.py +33 -0
  43. agent_crossbar-0.2.0/src/agent_crossbar/discovery.py +416 -0
  44. agent_crossbar-0.2.0/src/agent_crossbar/discovery_runner.py +324 -0
  45. agent_crossbar-0.2.0/src/agent_crossbar/env_compat.py +55 -0
  46. agent_crossbar-0.2.0/src/agent_crossbar/envelope.py +293 -0
  47. agent_crossbar-0.2.0/src/agent_crossbar/jobs.py +837 -0
  48. agent_crossbar-0.2.0/src/agent_crossbar/model_cache.py +204 -0
  49. agent_crossbar-0.2.0/src/agent_crossbar/models.py +67 -0
  50. agent_crossbar-0.2.0/src/agent_crossbar/profiles/__init__.py +88 -0
  51. agent_crossbar-0.2.0/src/agent_crossbar/profiles/chatgpt_pro.py +33 -0
  52. agent_crossbar-0.2.0/src/agent_crossbar/profiles/claude.py +41 -0
  53. agent_crossbar-0.2.0/src/agent_crossbar/profiles/codex.py +39 -0
  54. agent_crossbar-0.2.0/src/agent_crossbar/profiles/opencode.py +49 -0
  55. agent_crossbar-0.2.0/src/agent_crossbar/profiles/reasonix.py +35 -0
  56. agent_crossbar-0.2.0/src/agent_crossbar/providers.py +461 -0
  57. agent_crossbar-0.2.0/src/agent_crossbar/readiness.py +785 -0
  58. agent_crossbar-0.2.0/src/agent_crossbar/redaction.py +66 -0
  59. agent_crossbar-0.2.0/src/agent_crossbar/runner.py +2974 -0
  60. agent_crossbar-0.2.0/src/agent_crossbar/server.py +1156 -0
  61. agent_crossbar-0.2.0/src/agent_crossbar/shell_server.py +68 -0
  62. agent_crossbar-0.2.0/src/agent_crossbar/telemetry.py +266 -0
  63. agent_crossbar-0.2.0/src/agent_crossbar/tmux_output.py +241 -0
  64. agent_crossbar-0.2.0/src/agent_crossbar/validation.py +276 -0
  65. agent_crossbar-0.2.0/src/agent_harness_mcp/__init__.py +87 -0
  66. agent_crossbar-0.2.0/tests/test_acp_agent.py +933 -0
  67. agent_crossbar-0.2.0/tests/test_acp_client.py +842 -0
  68. agent_crossbar-0.2.0/tests/test_acp_runtime_direct.py +543 -0
  69. agent_crossbar-0.2.0/tests/test_capability_validation.py +393 -0
  70. agent_crossbar-0.2.0/tests/test_claude_adapter.py +364 -0
  71. agent_crossbar-0.2.0/tests/test_claude_agent_integration.py +1004 -0
  72. agent_crossbar-0.2.0/tests/test_claude_model_probe.py +1241 -0
  73. agent_crossbar-0.2.0/tests/test_context.py +40 -0
  74. agent_crossbar-0.2.0/tests/test_demo_assets.py +26 -0
  75. agent_crossbar-0.2.0/tests/test_discovery.py +2828 -0
  76. agent_crossbar-0.2.0/tests/test_envelope.py +483 -0
  77. agent_crossbar-0.2.0/tests/test_jobs.py +637 -0
  78. agent_crossbar-0.2.0/tests/test_local_e2e_dev_start.py +410 -0
  79. agent_crossbar-0.2.0/tests/test_minimal_public_contract.py +526 -0
  80. agent_crossbar-0.2.0/tests/test_npm_launcher.py +43 -0
  81. agent_crossbar-0.2.0/tests/test_package_metadata.py +173 -0
  82. agent_crossbar-0.2.0/tests/test_policy_validation.py +93 -0
  83. agent_crossbar-0.2.0/tests/test_provider_adapters.py +131 -0
  84. agent_crossbar-0.2.0/tests/test_provider_surface_gate.py +677 -0
  85. agent_crossbar-0.2.0/tests/test_providers.py +128 -0
  86. agent_crossbar-0.2.0/tests/test_readiness.py +1407 -0
  87. agent_crossbar-0.2.0/tests/test_redaction.py +89 -0
  88. agent_crossbar-0.2.0/tests/test_runner.py +4034 -0
  89. agent_crossbar-0.2.0/tests/test_scaffold.py +10 -0
  90. agent_crossbar-0.2.0/tests/test_server_tools.py +230 -0
  91. agent_crossbar-0.2.0/tests/test_telemetry.py +256 -0
  92. agent_crossbar-0.2.0/tests/test_tmux_output.py +343 -0
  93. agent_crossbar-0.2.0/tests/test_tool_surface_audit.py +132 -0
  94. agent_crossbar-0.2.0/tests/test_validation.py +313 -0
@@ -0,0 +1 @@
1
+ zombopanda@gmail.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBiH4qgbw/sizT5SxcfqYr8BS4T77G2sR/ph85Hwpgpw
@@ -0,0 +1,19 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "pip"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ open-pull-requests-limit: 5
8
+
9
+ - package-ecosystem: "npm"
10
+ directory: "/"
11
+ schedule:
12
+ interval: "weekly"
13
+ open-pull-requests-limit: 3
14
+
15
+ - package-ecosystem: "github-actions"
16
+ directory: "/"
17
+ schedule:
18
+ interval: "weekly"
19
+ open-pull-requests-limit: 3
@@ -0,0 +1,186 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ # ── Python test matrix (Ubuntu) ──────────────────────────────────────────
14
+ test-ubuntu:
15
+ name: "py${{ matrix.python }} on ubuntu"
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ python: ["3.11", "3.12", "3.13"]
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - uses: astral-sh/setup-uv@v5
25
+ with:
26
+ python-version: ${{ matrix.python }}
27
+
28
+ - name: Create isolated venv
29
+ run: uv venv --python ${{ matrix.python }} /tmp/ci-venv
30
+
31
+ - name: Install package + test deps
32
+ run: |
33
+ uv pip install --python /tmp/ci-venv/bin/python \
34
+ -e ".[test]"
35
+
36
+ - name: Run tests
37
+ run: |
38
+ /tmp/ci-venv/bin/python -m pytest tests/ -q \
39
+ --ignore=tests/test_claude_agent_integration.py \
40
+ --ignore=tests/test_acp_agent.py \
41
+ --ignore=tests/test_tmux_output.py \
42
+ --ignore=tests/test_local_e2e_dev_start.py
43
+
44
+ # ── Python test matrix (macOS primary version) ───────────────────────────
45
+ test-macos:
46
+ name: "py${{ matrix.python }} on macos"
47
+ runs-on: macos-latest
48
+ strategy:
49
+ fail-fast: false
50
+ matrix:
51
+ python: ["3.13"]
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - uses: astral-sh/setup-uv@v5
56
+ with:
57
+ python-version: ${{ matrix.python }}
58
+
59
+ - name: Create isolated venv
60
+ run: uv venv --python ${{ matrix.python }} /tmp/ci-venv
61
+
62
+ - name: Install package + test deps
63
+ run: |
64
+ uv pip install --python /tmp/ci-venv/bin/python \
65
+ -e ".[test]"
66
+
67
+ - name: Run tests
68
+ run: |
69
+ /tmp/ci-venv/bin/python -m pytest tests/ -q \
70
+ --ignore=tests/test_claude_agent_integration.py \
71
+ --ignore=tests/test_acp_agent.py \
72
+ --ignore=tests/test_tmux_output.py \
73
+ --ignore=tests/test_local_e2e_dev_start.py
74
+
75
+ # ── Lint & type checks ──────────────────────────────────────────────────
76
+ lint:
77
+ name: "lint + format check"
78
+ runs-on: ubuntu-latest
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+
82
+ - uses: astral-sh/setup-uv@v5
83
+ with:
84
+ python-version: "3.13"
85
+
86
+ - name: Create isolated venv
87
+ run: uv venv --python 3.13 /tmp/ci-venv
88
+
89
+ - name: Install package + test deps
90
+ run: |
91
+ uv pip install --python /tmp/ci-venv/bin/python \
92
+ -e ".[test]"
93
+
94
+ - name: Ruff lint
95
+ run: |
96
+ /tmp/ci-venv/bin/ruff check \
97
+ src/agent_crossbar/ \
98
+ scripts/provider_surface_gate.py \
99
+ tests/test_minimal_public_contract.py \
100
+ tests/test_claude_adapter.py \
101
+ tests/test_provider_surface_gate.py
102
+
103
+ - name: Ruff format check
104
+ run: |
105
+ /tmp/ci-venv/bin/ruff format --check \
106
+ src/agent_crossbar/ \
107
+ scripts/provider_surface_gate.py \
108
+ tests/test_minimal_public_contract.py \
109
+ tests/test_claude_adapter.py \
110
+ tests/test_provider_surface_gate.py
111
+
112
+ # ── Build wheel + sdist ─────────────────────────────────────────────────
113
+ build:
114
+ name: "build wheel + sdist"
115
+ runs-on: ubuntu-latest
116
+ steps:
117
+ - uses: actions/checkout@v4
118
+
119
+ - uses: astral-sh/setup-uv@v5
120
+ with:
121
+ python-version: "3.13"
122
+
123
+ - name: Build
124
+ run: uv build --out-dir dist
125
+
126
+ - name: Archive artifacts
127
+ uses: actions/upload-artifact@v4
128
+ with:
129
+ name: dist
130
+ path: dist/
131
+
132
+ # ── Install smoke ───────────────────────────────────────────────────────
133
+ install-smoke:
134
+ name: "install smoke"
135
+ needs: build
136
+ runs-on: ubuntu-latest
137
+ steps:
138
+ - uses: actions/checkout@v4
139
+
140
+ - uses: astral-sh/setup-uv@v5
141
+ with:
142
+ python-version: "3.13"
143
+
144
+ - uses: actions/download-artifact@v4
145
+ with:
146
+ name: dist
147
+ path: dist/
148
+
149
+ - name: Install from wheel
150
+ run: |
151
+ uv venv --python 3.13 /tmp/smoke-venv
152
+ uv pip install --python /tmp/smoke-venv/bin/python dist/*.whl
153
+
154
+ - name: "Smoke: CLI help"
155
+ run: /tmp/smoke-venv/bin/agent-crossbar doctor
156
+
157
+ - name: "Smoke: import"
158
+ run: |
159
+ /tmp/smoke-venv/bin/python -c \
160
+ "import agent_crossbar; print(agent_crossbar.__version__)"
161
+
162
+ # ── npm pack + launcher smoke ───────────────────────────────────────────
163
+ npm-smoke:
164
+ name: "npm pack + launcher smoke"
165
+ runs-on: ubuntu-latest
166
+ defaults:
167
+ run:
168
+ working-directory: .
169
+ steps:
170
+ - uses: actions/checkout@v4
171
+
172
+ - uses: actions/setup-node@v4
173
+ with:
174
+ node-version: "20"
175
+
176
+ - name: npm pack
177
+ run: npm pack
178
+
179
+ - name: Verify tarball contents
180
+ run: |
181
+ tar -tzf agent-crossbar-*.tgz | sort
182
+ # Must NOT contain Python source, pyproject, tests, or internal paths
183
+ ! tar -tzf agent-crossbar-*.tgz | grep -qE '\.py|pyproject\.toml|\.reasonix|\.memsearch|results/|\.pytest_cache|__pycache__|test'
184
+
185
+ - name: Launcher syntax check
186
+ run: node --check bin/agent-crossbar.mjs
@@ -0,0 +1,93 @@
1
+ name: Live Provider Gate
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ profile:
7
+ description: "Provider profile to test"
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - codex
12
+ - claude
13
+ - opencode
14
+ - reasonix
15
+ model:
16
+ description: "Model ID (leave empty for profile default)"
17
+ required: false
18
+ type: string
19
+ effort:
20
+ description: "Effort level (supported by any provider that accepts effort)"
21
+ required: false
22
+ type: string
23
+ task:
24
+ description: "Task to test"
25
+ required: true
26
+ type: choice
27
+ options:
28
+ - ask
29
+ - review
30
+ - dev
31
+ interactive:
32
+ description: "Test interactive mode"
33
+ required: false
34
+ type: boolean
35
+ default: false
36
+ max_runtime_sec:
37
+ description: "Max runtime seconds"
38
+ required: false
39
+ type: string
40
+ default: "600"
41
+
42
+ permissions:
43
+ contents: read
44
+
45
+ jobs:
46
+ live-gate:
47
+ name: "live gate: ${{ inputs.profile }} ${{ inputs.task }}"
48
+ runs-on: ubuntu-latest
49
+ environment: live-gates
50
+ timeout-minutes: 30
51
+
52
+ # Never run on forks — requires maintainer credentials
53
+ if: github.repository == 'zombopanda/agent-crossbar'
54
+
55
+ steps:
56
+ - uses: actions/checkout@v4
57
+
58
+ - uses: astral-sh/setup-uv@v5
59
+ with:
60
+ python-version: "3.13"
61
+
62
+ - name: Create isolated venv
63
+ run: uv venv --python 3.13 /tmp/ci-venv
64
+
65
+ - name: Install package + test deps
66
+ run: |
67
+ uv pip install --python /tmp/ci-venv/bin/python \
68
+ -e ".[test]"
69
+
70
+ - name: Provider surface gate
71
+ env:
72
+ PROFILE: ${{ inputs.profile }}
73
+ TASK: ${{ inputs.task }}
74
+ INTERACTIVE: ${{ inputs.interactive }}
75
+ MODEL: ${{ inputs.model }}
76
+ EFFORT: ${{ inputs.effort }}
77
+ MAX_RUNTIME_SEC: ${{ inputs.max_runtime_sec }}
78
+ run: |
79
+ MODEL_ARG=""
80
+ if [ -n "${MODEL}" ]; then
81
+ MODEL_ARG="--model ${MODEL}"
82
+ fi
83
+ EFFORT_ARG=""
84
+ if [ -n "${EFFORT}" ]; then
85
+ EFFORT_ARG="--effort ${EFFORT}"
86
+ fi
87
+ /tmp/ci-venv/bin/python scripts/provider_surface_gate.py \
88
+ --profile "${PROFILE}" \
89
+ ${MODEL_ARG} \
90
+ ${EFFORT_ARG} \
91
+ --task "${TASK}" \
92
+ --interactive "${INTERACTIVE}" \
93
+ --max-runtime-sec "${MAX_RUNTIME_SEC:-600}"
@@ -0,0 +1,200 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+ attestations: write
12
+
13
+ jobs:
14
+ # ── Build & audit ───────────────────────────────────────────────────────
15
+ build:
16
+ name: "build + audit"
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ contents: read
20
+ id-token: write
21
+ attestations: write
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+
27
+ - name: Verify signed release tag
28
+ run: |
29
+ git fetch --force origin \
30
+ "refs/tags/${GITHUB_REF_NAME}:refs/tags/${GITHUB_REF_NAME}"
31
+ git config gpg.format ssh
32
+ git config gpg.ssh.allowedSignersFile \
33
+ "${GITHUB_WORKSPACE}/.github/allowed_signers"
34
+ git verify-tag "${GITHUB_REF_NAME}"
35
+
36
+ - uses: astral-sh/setup-uv@v5
37
+ with:
38
+ python-version: "3.13"
39
+
40
+ - name: Verify tag matches package versions
41
+ shell: bash
42
+ run: |
43
+ release_version="${GITHUB_REF_NAME#v}"
44
+ python - "${release_version}" <<'PY'
45
+ import json
46
+ import sys
47
+ import tomllib
48
+ from pathlib import Path
49
+
50
+ package_root = Path(".")
51
+ tag_version = sys.argv[1]
52
+ python_version = tomllib.loads(
53
+ (package_root / "pyproject.toml").read_text()
54
+ )["project"]["version"]
55
+ npm_version = json.loads(
56
+ (package_root / "package.json").read_text()
57
+ )["version"]
58
+ if not tag_version == python_version == npm_version:
59
+ raise SystemExit(
60
+ "tag version does not match package versions: "
61
+ f"tag={tag_version}, python={python_version}, npm={npm_version}"
62
+ )
63
+ PY
64
+
65
+ - name: Build
66
+ run: uv build --out-dir dist
67
+
68
+ - name: Audit wheel
69
+ run: |
70
+ ! unzip -l dist/*.whl | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff'
71
+
72
+ - name: Audit sdist
73
+ run: |
74
+ ! tar -tzf dist/*.tar.gz | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff'
75
+
76
+ - name: Install smoke
77
+ run: |
78
+ uv venv --python 3.13 /tmp/smoke-venv
79
+ uv pip install --python /tmp/smoke-venv/bin/python dist/*.whl
80
+ /tmp/smoke-venv/bin/agent-crossbar doctor
81
+ /tmp/smoke-venv/bin/python -c \
82
+ "import agent_crossbar; print(agent_crossbar.__version__)"
83
+
84
+ - name: Attest distributions
85
+ uses: actions/attest-build-provenance@v3
86
+ with:
87
+ subject-path: dist/*
88
+
89
+ - uses: actions/upload-artifact@v4
90
+ with:
91
+ name: dist
92
+ path: dist/
93
+
94
+ # ── PyPI trusted publishing ─────────────────────────────────────────────
95
+ pypi-publish:
96
+ name: "publish to PyPI"
97
+ needs: build
98
+ runs-on: ubuntu-latest
99
+ environment:
100
+ name: pypi
101
+ url: https://pypi.org/p/agent-crossbar
102
+ permissions:
103
+ id-token: write
104
+ steps:
105
+ - uses: actions/download-artifact@v4
106
+ with:
107
+ name: dist
108
+ path: dist/
109
+
110
+ - uses: pypa/gh-action-pypi-publish@release/v1
111
+ with:
112
+ attestations: true
113
+
114
+ # ── Smoke the artifact PyPI actually serves ────────────────────────────
115
+ pypi-smoke:
116
+ name: "smoke published PyPI artifact"
117
+ needs: pypi-publish
118
+ runs-on: ubuntu-latest
119
+ steps:
120
+ - uses: astral-sh/setup-uv@v5
121
+
122
+ - name: Install and start published version
123
+ shell: bash
124
+ run: |
125
+ version="${GITHUB_REF_NAME#v}"
126
+ for attempt in {1..12}; do
127
+ if uvx --refresh --from "agent-crossbar==${version}" agent-crossbar doctor; then
128
+ exit 0
129
+ fi
130
+ if [[ "${attempt}" -eq 12 ]]; then
131
+ echo "PyPI artifact was not installable after propagation window" >&2
132
+ exit 1
133
+ fi
134
+ sleep 10
135
+ done
136
+
137
+ # ── npm publish (post-PyPI) ─────────────────────────────────────────────
138
+ npm-publish:
139
+ name: "publish to npm"
140
+ needs: pypi-smoke
141
+ runs-on: ubuntu-latest
142
+ environment:
143
+ name: npm
144
+ url: https://www.npmjs.com/package/agent-crossbar
145
+ permissions:
146
+ contents: read
147
+ id-token: write
148
+ defaults:
149
+ run:
150
+ working-directory: .
151
+ steps:
152
+ - uses: actions/checkout@v4
153
+
154
+ - uses: actions/setup-node@v4
155
+ with:
156
+ node-version: "24"
157
+ registry-url: "https://registry.npmjs.org"
158
+
159
+ - name: Update npm for trusted publishing
160
+ run: npm install --global npm@latest
161
+
162
+ - name: npm pack + verify
163
+ run: |
164
+ npm pack
165
+ ! tar -tzf agent-crossbar-*.tgz | grep -qE '\.reasonix|\.memsearch|results/|__pycache__'
166
+
167
+ - name: npm publish
168
+ shell: bash
169
+ run: |
170
+ version="$(node -p 'require("./package.json").version')"
171
+ if npm view "agent-crossbar@${version}" version >/dev/null 2>&1; then
172
+ echo "agent-crossbar@${version} is already published; skipping"
173
+ exit 0
174
+ fi
175
+ npm publish --access public
176
+
177
+ # ── GitHub release (only after both registries are healthy) ────────────
178
+ github-release:
179
+ name: "create GitHub release"
180
+ needs: npm-publish
181
+ runs-on: ubuntu-latest
182
+ permissions:
183
+ contents: write
184
+ steps:
185
+ - uses: actions/checkout@v4
186
+
187
+ - uses: actions/download-artifact@v4
188
+ with:
189
+ name: dist
190
+ path: dist/
191
+
192
+ - name: Create release with verified artifacts
193
+ env:
194
+ GH_TOKEN: ${{ github.token }}
195
+ run: |
196
+ gh release create "${GITHUB_REF_NAME}" \
197
+ --verify-tag \
198
+ --title "Agent Crossbar ${GITHUB_REF_NAME}" \
199
+ --notes-file "docs/releases/v0.2.0.md" \
200
+ dist/*
@@ -0,0 +1,89 @@
1
+ name: Security
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "0 8 * * 1" # every Monday
10
+
11
+ permissions:
12
+ contents: read
13
+ security-events: write
14
+
15
+ jobs:
16
+ # ── Secret scanning ─────────────────────────────────────────────────────
17
+ secret-scan:
18
+ name: "secret scan"
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+ - uses: gitleaks/gitleaks-action@v2
23
+
24
+ # ── Dependency audit ────────────────────────────────────────────────────
25
+ dependency-audit:
26
+ name: "dependency audit"
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: astral-sh/setup-uv@v5
31
+ with:
32
+ python-version: "3.13"
33
+
34
+ - name: Create isolated venv
35
+ run: uv venv --python 3.13 /tmp/ci-venv
36
+
37
+ - name: Install package + test deps
38
+ run: |
39
+ uv pip install --python /tmp/ci-venv/bin/python \
40
+ -e ".[test]"
41
+
42
+ - name: pip-audit
43
+ run: /tmp/ci-venv/bin/pip-audit
44
+
45
+ # ── CodeQL ──────────────────────────────────────────────────────────────
46
+ codeql:
47
+ name: "CodeQL"
48
+ runs-on: ubuntu-latest
49
+ permissions:
50
+ contents: read
51
+ security-events: write
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+
55
+ - uses: github/codeql-action/init@v3
56
+ with:
57
+ languages: python, javascript
58
+
59
+ - uses: github/codeql-action/analyze@v3
60
+
61
+ # ── Artifact allowlist check ────────────────────────────────────────────
62
+ artifact-audit:
63
+ name: "artifact audit"
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - uses: astral-sh/setup-uv@v5
69
+ with:
70
+ python-version: "3.13"
71
+
72
+ - name: Build artifacts
73
+ run: uv build --out-dir dist
74
+
75
+ - name: Audit wheel contents
76
+ run: |
77
+ echo "=== Wheel contents ==="
78
+ unzip -l dist/*.whl | grep -vE '\.pyc$|__pycache__'
79
+ echo ""
80
+ echo "=== Checking for prohibited paths ==="
81
+ ! unzip -l dist/*.whl | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff|\.pytest_cache|\.DS_Store'
82
+
83
+ - name: Audit sdist contents
84
+ run: |
85
+ echo "=== Sdist contents ==="
86
+ tar -tzf dist/*.tar.gz | grep -vE '\.pyc$|__pycache__'
87
+ echo ""
88
+ echo "=== Checking for prohibited paths ==="
89
+ ! tar -tzf dist/*.tar.gz | grep -qE '\.reasonix|\.memsearch|results/|benchmark|handoff|\.pytest_cache|\.DS_Store'
@@ -0,0 +1,12 @@
1
+ .DS_Store
2
+ .agent-crossbar/
3
+ .memsearch/
4
+ .reasonix/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .venv/
8
+ __pycache__/
9
+ *.py[cod]
10
+ *.tgz
11
+ dist/
12
+ uv.lock
@@ -0,0 +1,11 @@
1
+ # Gitleaks configuration for Agent Crossbar
2
+ # Excludes known non-secret patterns and false positives from the codebase.
3
+
4
+ title = "Agent Crossbar gitleaks config"
5
+
6
+ [allowlist]
7
+ description = "Global allowlist"
8
+ paths = [
9
+ '''uv\.lock''',
10
+ '''\.gitleaks\.toml''',
11
+ ]
@@ -0,0 +1,43 @@
1
+ # Agent Crossbar — Contributor Code Rules
2
+
3
+ These rules apply to code contributions. They are intentionally concise and focused on the public contract.
4
+
5
+ ## Public Contract (Provider-Neutral)
6
+
7
+ 1. **No top-level provider-specific fields.** The public API (`agent_start`, `job_result`, tool schemas) MUST NOT expose fields that only apply to a single provider. Provider-specific metadata lives in per-profile capability entries.
8
+
9
+ 2. **The 8-tool MCP surface is locked.** Adding or removing a tool requires a design discussion and version bump. No hidden tools. No deprecated aliases.
10
+
11
+ 3. **Stable error codes.** Error codes documented in the README troubleshooting table MUST NOT change semantics in a patch version. New codes may be added in minor versions.
12
+
13
+ 4. **`agent_start` schema is provider-neutral and minimal.** The only public fields are: `profile`, `prompt`, `task`, `interactive`, `model`, `effort`, `cwd`, `scope`, `max_runtime_sec`, plus standard client metadata (`client`, `client_name`, `client_version`, `client_session_id`). No transport enum, no provider-specific routing hints.
14
+
15
+ 5. **`interactive` is a boolean.** The public schema exposes `interactive` as a single boolean. No transport enum, no public transport field. Transport selection is an internal adapter concern.
16
+
17
+ 6. **Forbidden (dead) public fields.** The following fields MUST NOT appear in the `agent_start` signature or any shipped schema: `external_context`, `budget_usd`, `text_subtype`, `review_target`, `context_target`, `full_local`. No compatibility shims, no deprecated aliases for these.
18
+
19
+ ## Architecture
20
+
21
+ 7. **Per-profile adapter modules.** Each provider gets one bounded module under `agent_crossbar/adapters/` implementing `ProviderAdapter` from `base.py`. Adapter modules MUST NOT import from each other.
22
+
23
+ 8. **Core modules are provider-agnostic.** `server.py`, `jobs.py`, `validation.py`, `envelope.py`, `readiness.py` MUST NOT contain provider-specific branching. Provider behavior is injected through adapter lookups.
24
+
25
+ 9. **Per-profile capabilities/models live in separate profile modules.** Each profile under `agent_crossbar/profiles/` owns its capabilities, models, and default configuration. Model lists MUST come from CLI discovery (`discovery.py`), not hardcoded. Profile modules MUST NOT import from each other.
26
+
27
+ 10. **No compatibility aliases for removed fields.** Removed fields (`transport`, `autonomy`, `sensitivity`, `sanitized_context_only`, `timeout_sec`, etc.) MUST NOT have runtime compatibility shims, aliases, or warning-based remapping. They are simply absent.
28
+
29
+ 11. **Readiness probes are non-mutating and cached.** Probes inspect state, never change it. Results cache for 60 seconds. Registration alone never produces `ready`.
30
+
31
+ ## Testing
32
+
33
+ 12. **TDD for provider changes.** Any new provider adapter, capability, or transport MUST include:
34
+ - Unit tests proving validation, schema conformance, and error paths (no live provider).
35
+ - A passing live provider gate (maintainer-only workflow) on every claimed operation/transport combination.
36
+
37
+ 13. **No fake capabilities or models.** Model lists and capability declarations MUST come from live provider discovery or documentation references. Do not invent capabilities.
38
+
39
+ 14. **Deterministic CI.** All tests in public PR CI MUST pass without provider credentials. Provider-dependent tests use `pytest.skip` when credentials are absent.
40
+
41
+ ## Package Hygiene
42
+
43
+ 15. **Public artifacts exclude internal content.** Benchmark results, `.reasonix/`, `.memsearch/`, personal paths, private URLs, and handoff files MUST NOT appear in wheel/sdist/npm tarball.