agentxchain 2.13.0 → 2.14.0

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.
package/README.md CHANGED
@@ -14,6 +14,7 @@ Legacy IDE-window coordination is still shipped as a compatibility mode for team
14
14
  - [Adapter reference](https://agentxchain.dev/docs/adapters/)
15
15
  - [Protocol spec (v6)](https://agentxchain.dev/docs/protocol/)
16
16
  - [Protocol reference](https://agentxchain.dev/docs/protocol-reference/)
17
+ - [Build your own runner](https://agentxchain.dev/docs/build-your-own-runner/)
17
18
  - [Why governed multi-agent delivery matters](https://agentxchain.dev/why/)
18
19
 
19
20
  ## Install
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "agentxchain",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "agentxchain": "./bin/agentxchain.js"
8
8
  },
9
+ "exports": {
10
+ ".": "./bin/agentxchain.js",
11
+ "./runner-interface": "./src/lib/runner-interface.js",
12
+ "./run-loop": "./src/lib/run-loop.js"
13
+ },
9
14
  "files": [
10
15
  "bin/",
11
16
  "src/",
@@ -21,6 +26,7 @@
21
26
  "preflight:release": "bash scripts/release-preflight.sh",
22
27
  "preflight:release:strict": "bash scripts/release-preflight.sh --strict",
23
28
  "postflight:release": "bash scripts/release-postflight.sh",
29
+ "postflight:downstream": "bash scripts/release-downstream-truth.sh",
24
30
  "build:macos": "bun build bin/agentxchain.js --compile --target=bun-darwin-arm64 --outfile=dist/agentxchain-macos-arm64",
25
31
  "build:linux": "bun build bin/agentxchain.js --compile --target=bun-linux-x64 --outfile=dist/agentxchain-linux-x64",
26
32
  "publish:npm": "bash scripts/publish-npm.sh"
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env bash
2
+ # Release downstream truth — run after all downstream surfaces are updated.
3
+ # Verifies: GitHub release exists, Homebrew tap SHA and URL match registry tarball.
4
+ # Usage: bash scripts/release-downstream-truth.sh --target-version <semver>
5
+ set -uo pipefail
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+ CLI_DIR="${SCRIPT_DIR}/.."
9
+ REPO_ROOT="${CLI_DIR}/.."
10
+ cd "$CLI_DIR"
11
+
12
+ TARGET_VERSION=""
13
+ RETRY_ATTEMPTS="${RELEASE_DOWNSTREAM_RETRY_ATTEMPTS:-3}"
14
+ RETRY_DELAY_SECONDS="${RELEASE_DOWNSTREAM_RETRY_DELAY_SECONDS:-5}"
15
+
16
+ usage() {
17
+ echo "Usage: bash scripts/release-downstream-truth.sh --target-version <semver>" >&2
18
+ }
19
+
20
+ while [[ $# -gt 0 ]]; do
21
+ case "$1" in
22
+ --target-version)
23
+ if [[ -z "${2:-}" ]]; then
24
+ echo "Error: --target-version requires a semver argument" >&2
25
+ usage
26
+ exit 1
27
+ fi
28
+ if ! [[ "$2" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
29
+ echo "Invalid semver: $2" >&2
30
+ usage
31
+ exit 1
32
+ fi
33
+ TARGET_VERSION="$2"
34
+ shift 2
35
+ ;;
36
+ *)
37
+ usage
38
+ exit 1
39
+ ;;
40
+ esac
41
+ done
42
+
43
+ if [[ -z "$TARGET_VERSION" ]]; then
44
+ echo "Error: --target-version is required" >&2
45
+ usage
46
+ exit 1
47
+ fi
48
+
49
+ PACKAGE_NAME="$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json', 'utf8')).name)")"
50
+ HOMEBREW_FORMULA="${REPO_ROOT}/cli/homebrew/agentxchain.rb"
51
+
52
+ PASS=0
53
+ FAIL=0
54
+
55
+ pass() { PASS=$((PASS + 1)); echo " PASS: $1"; }
56
+ fail() { FAIL=$((FAIL + 1)); echo " FAIL: $1"; }
57
+
58
+ echo "AgentXchain v${TARGET_VERSION} Downstream Release Truth"
59
+ echo "====================================="
60
+ echo "Checks downstream surfaces after publish: GitHub release, Homebrew tap."
61
+ echo ""
62
+
63
+ # --- Check 1: GitHub Release ---
64
+ echo "[1/3] GitHub release"
65
+ if ! command -v gh >/dev/null 2>&1; then
66
+ fail "gh CLI not available — cannot verify GitHub release"
67
+ else
68
+ GH_FOUND=false
69
+ for attempt in $(seq 1 "$RETRY_ATTEMPTS"); do
70
+ GH_TAG="$(gh release view "v${TARGET_VERSION}" --json tagName -q '.tagName' 2>/dev/null || true)"
71
+ if [[ "$GH_TAG" == "v${TARGET_VERSION}" ]]; then
72
+ GH_FOUND=true
73
+ break
74
+ fi
75
+ if [[ "$attempt" -lt "$RETRY_ATTEMPTS" ]]; then
76
+ echo " INFO: GitHub release not found (attempt ${attempt}/${RETRY_ATTEMPTS}); retrying in ${RETRY_DELAY_SECONDS}s..."
77
+ sleep "$RETRY_DELAY_SECONDS"
78
+ fi
79
+ done
80
+ if $GH_FOUND; then
81
+ pass "GitHub release v${TARGET_VERSION} exists"
82
+ else
83
+ fail "GitHub release v${TARGET_VERSION} not found after ${RETRY_ATTEMPTS} attempts"
84
+ fi
85
+ fi
86
+
87
+ # --- Get registry tarball URL and compute SHA ---
88
+ echo "[2/3] Homebrew tap SHA matches registry tarball"
89
+ REGISTRY_TARBALL_URL="$(npm view "${PACKAGE_NAME}@${TARGET_VERSION}" dist.tarball 2>/dev/null || true)"
90
+ if [[ -z "$REGISTRY_TARBALL_URL" ]]; then
91
+ fail "cannot fetch registry tarball URL for ${PACKAGE_NAME}@${TARGET_VERSION}"
92
+ else
93
+ REGISTRY_SHA="$(curl -sL "$REGISTRY_TARBALL_URL" | shasum -a 256 | awk '{print $1}')"
94
+ if [[ -z "$REGISTRY_SHA" ]]; then
95
+ fail "cannot compute SHA256 of registry tarball"
96
+ elif [[ ! -f "$HOMEBREW_FORMULA" ]]; then
97
+ fail "Homebrew formula not found at ${HOMEBREW_FORMULA}"
98
+ else
99
+ FORMULA_SHA="$(grep -E '^\s*sha256\s+"' "$HOMEBREW_FORMULA" | sed 's/.*sha256 *"\([a-f0-9]*\)".*/\1/')"
100
+ if [[ "$REGISTRY_SHA" == "$FORMULA_SHA" ]]; then
101
+ pass "Homebrew formula SHA256 matches registry tarball (${REGISTRY_SHA:0:16}...)"
102
+ else
103
+ fail "Homebrew formula SHA256 mismatch: formula=${FORMULA_SHA:0:16}... registry=${REGISTRY_SHA:0:16}..."
104
+ fi
105
+ fi
106
+ fi
107
+
108
+ # --- Check 3: Homebrew tap URL matches registry tarball URL ---
109
+ echo "[3/3] Homebrew tap URL matches registry tarball"
110
+ if [[ -z "$REGISTRY_TARBALL_URL" ]]; then
111
+ fail "cannot verify URL — registry tarball URL unavailable"
112
+ elif [[ ! -f "$HOMEBREW_FORMULA" ]]; then
113
+ fail "Homebrew formula not found at ${HOMEBREW_FORMULA}"
114
+ else
115
+ FORMULA_URL="$(grep -E '^\s*url\s+"' "$HOMEBREW_FORMULA" | sed 's/.*url *"\([^"]*\)".*/\1/')"
116
+ if [[ "$FORMULA_URL" == "$REGISTRY_TARBALL_URL" ]]; then
117
+ pass "Homebrew formula URL matches registry tarball"
118
+ else
119
+ fail "Homebrew formula URL mismatch: formula=${FORMULA_URL} registry=${REGISTRY_TARBALL_URL}"
120
+ fi
121
+ fi
122
+
123
+ echo ""
124
+ echo "====================================="
125
+ echo "Results: ${PASS} passed, ${FAIL} failed"
126
+ if [ "$FAIL" -gt 0 ]; then
127
+ echo "DOWNSTREAM TRUTH FAILED — at least one downstream surface is inconsistent."
128
+ exit 1
129
+ fi
130
+
131
+ echo "DOWNSTREAM TRUTH PASSED — all downstream surfaces are consistent."
132
+ exit 0
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env bash
2
2
  # Release postflight — run this after publish succeeds.
3
3
  # Verifies: release tag exists, npm registry serves the version, metadata is present,
4
- # and the published package can execute its CLI entrypoint.
4
+ # the published package can execute its CLI entrypoint, and runner package exports
5
+ # are importable in a clean consumer project.
5
6
  # Usage: bash scripts/release-postflight.sh --target-version <semver> [--tag vX.Y.Z]
6
7
  set -uo pipefail
7
8
 
@@ -15,7 +16,7 @@ RETRY_ATTEMPTS="${RELEASE_POSTFLIGHT_RETRY_ATTEMPTS:-12}"
15
16
  RETRY_DELAY_SECONDS="${RELEASE_POSTFLIGHT_RETRY_DELAY_SECONDS:-10}"
16
17
 
17
18
  usage() {
18
- echo "Usage: bash scripts/release-postflight.sh --target-version <semver> [--tag vX.Y.Z]" >&2
19
+ echo "Usage: bash scripts/release-postflight.sh --target-version <semver> [--tag vX.Y.Z]" >&2
19
20
  }
20
21
 
21
22
  while [[ $# -gt 0 ]]; do
@@ -76,6 +77,7 @@ TARBALL_URL=""
76
77
  REGISTRY_CHECKSUM=""
77
78
  PACKAGE_NAME="$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json', 'utf8')).name)")"
78
79
  PACKAGE_BIN_NAME="$(node -e "const pkg = JSON.parse(require('fs').readFileSync('package.json', 'utf8')); if (typeof pkg.bin === 'string') { console.log(pkg.name); process.exit(0); } const names = Object.keys(pkg.bin || {}); if (names.length !== 1) { console.error('package.json bin must declare exactly one entry'); process.exit(1); } console.log(names[0]);")"
80
+ RUNNER_INTERFACE_VERSION_EXPECTED="$(node --input-type=module -e "import('./src/lib/runner-interface.js').then((mod) => { console.log(mod.RUNNER_INTERFACE_VERSION); }).catch((error) => { console.error(error.message); process.exit(1); });")"
79
81
 
80
82
  pass() { PASS=$((PASS + 1)); echo " PASS: $1"; }
81
83
  fail() { FAIL=$((FAIL + 1)); echo " FAIL: $1"; }
@@ -136,6 +138,67 @@ run_install_smoke() {
136
138
  return "$version_status"
137
139
  }
138
140
 
141
+ run_runner_export_smoke() {
142
+ if [[ -z "$TARBALL_URL" ]]; then
143
+ echo "registry tarball metadata unavailable for runner export smoke" >&2
144
+ return 1
145
+ fi
146
+
147
+ local smoke_root
148
+ local consumer_root
149
+ local smoke_npmrc
150
+ local install_status
151
+ local node_status
152
+
153
+ smoke_root="$(mktemp -d "${TMPDIR:-/tmp}/agentxchain-runner-postflight.XXXXXX")"
154
+ consumer_root="${smoke_root}/consumer"
155
+ mkdir -p "$consumer_root"
156
+
157
+ smoke_npmrc="${smoke_root}/.npmrc"
158
+ echo "registry=https://registry.npmjs.org/" > "$smoke_npmrc"
159
+
160
+ cat > "${consumer_root}/package.json" <<'EOF'
161
+ {
162
+ "name": "agentxchain-runner-postflight-smoke",
163
+ "private": true,
164
+ "type": "module"
165
+ }
166
+ EOF
167
+
168
+ (
169
+ cd "$consumer_root" || exit 1
170
+ env -u NODE_AUTH_TOKEN NPM_CONFIG_USERCONFIG="$smoke_npmrc" \
171
+ npm install "$TARBALL_URL" >/dev/null 2>&1
172
+ )
173
+ install_status=$?
174
+ if [[ "$install_status" -ne 0 ]]; then
175
+ rm -rf "$smoke_root"
176
+ return "$install_status"
177
+ fi
178
+
179
+ cat > "${consumer_root}/runner-export-smoke.mjs" <<'EOF'
180
+ import { RUNNER_INTERFACE_VERSION, loadContext } from 'agentxchain/runner-interface';
181
+ import { runLoop } from 'agentxchain/run-loop';
182
+
183
+ if (typeof loadContext !== 'function') {
184
+ throw new Error('loadContext export missing');
185
+ }
186
+
187
+ if (typeof runLoop !== 'function') {
188
+ throw new Error('runLoop export missing');
189
+ }
190
+
191
+ console.log(RUNNER_INTERFACE_VERSION);
192
+ EOF
193
+
194
+ local runner_output
195
+ runner_output="$(cd "$consumer_root" && node runner-export-smoke.mjs 2>&1)"
196
+ node_status=$?
197
+ printf '%s\n' "$runner_output"
198
+ rm -rf "$smoke_root"
199
+ return "$node_status"
200
+ }
201
+
139
202
  run_with_retry() {
140
203
  local __output_var="$1"
141
204
  local description="$2"
@@ -189,17 +252,17 @@ run_with_retry() {
189
252
 
190
253
  echo "AgentXchain v${TARGET_VERSION} Release Postflight"
191
254
  echo "====================================="
192
- echo "Checks release truth after publish: tag, registry visibility, metadata, and install smoke."
255
+ echo "Checks release truth after publish: tag, registry visibility, metadata, CLI install smoke, and runner export smoke."
193
256
  echo ""
194
257
 
195
- echo "[1/5] Git tag"
258
+ echo "[1/6] Git tag"
196
259
  if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null 2>&1; then
197
260
  pass "Git tag ${TAG} exists locally"
198
261
  else
199
262
  fail "Git tag ${TAG} is missing locally"
200
263
  fi
201
264
 
202
- echo "[2/5] Registry version"
265
+ echo "[2/6] Registry version"
203
266
  if run_with_retry VERSION_OUTPUT "registry version" equals "${TARGET_VERSION}" npm view "${PACKAGE_NAME}@${TARGET_VERSION}" version; then
204
267
  PUBLISHED_VERSION="$(trim_last_line "$VERSION_OUTPUT")"
205
268
  if [[ "$PUBLISHED_VERSION" == "$TARGET_VERSION" ]]; then
@@ -212,7 +275,7 @@ else
212
275
  printf '%s\n' "$VERSION_OUTPUT" | tail -20
213
276
  fi
214
277
 
215
- echo "[3/5] Registry tarball metadata"
278
+ echo "[3/6] Registry tarball metadata"
216
279
  if run_with_retry TARBALL_OUTPUT "registry tarball metadata" nonempty "" npm view "${PACKAGE_NAME}@${TARGET_VERSION}" dist.tarball; then
217
280
  TARBALL_URL="$(trim_last_line "$TARBALL_OUTPUT")"
218
281
  if [[ -n "$TARBALL_URL" ]]; then
@@ -225,7 +288,7 @@ else
225
288
  printf '%s\n' "$TARBALL_OUTPUT" | tail -20
226
289
  fi
227
290
 
228
- echo "[4/5] Registry checksum metadata"
291
+ echo "[4/6] Registry checksum metadata"
229
292
  if run_with_retry INTEGRITY_OUTPUT "registry checksum metadata" nonempty "" npm view "${PACKAGE_NAME}@${TARGET_VERSION}" dist.integrity; then
230
293
  REGISTRY_CHECKSUM="$(trim_last_line "$INTEGRITY_OUTPUT")"
231
294
  fi
@@ -240,7 +303,7 @@ else
240
303
  fail "registry did not return checksum metadata"
241
304
  fi
242
305
 
243
- echo "[5/5] Install smoke"
306
+ echo "[5/6] Install smoke"
244
307
  if run_with_retry EXEC_OUTPUT "install smoke" nonempty "" run_install_smoke; then
245
308
  EXEC_VERSION="$(trim_last_line "$EXEC_OUTPUT")"
246
309
  if [[ "$EXEC_VERSION" == "$TARGET_VERSION" ]]; then
@@ -253,6 +316,19 @@ else
253
316
  printf '%s\n' "$EXEC_OUTPUT" | tail -20
254
317
  fi
255
318
 
319
+ echo "[6/6] Runner export smoke"
320
+ if run_with_retry RUNNER_EXPORT_OUTPUT "runner export smoke" nonempty "" run_runner_export_smoke; then
321
+ RUNNER_EXPORT_VERSION="$(trim_last_line "$RUNNER_EXPORT_OUTPUT")"
322
+ if [[ "$RUNNER_EXPORT_VERSION" == "$RUNNER_INTERFACE_VERSION_EXPECTED" ]]; then
323
+ pass "published runner exports import with interface ${RUNNER_INTERFACE_VERSION_EXPECTED}"
324
+ else
325
+ fail "published runner exports reported interface '${RUNNER_EXPORT_VERSION}', expected '${RUNNER_INTERFACE_VERSION_EXPECTED}'"
326
+ fi
327
+ else
328
+ fail "published runner exports install smoke failed"
329
+ printf '%s\n' "$RUNNER_EXPORT_OUTPUT" | tail -20
330
+ fi
331
+
256
332
  echo ""
257
333
  echo "====================================="
258
334
  echo "Results: ${PASS} passed, ${FAIL} failed"