Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
6760b12
Merge master (v0.21.1 release) back into develop
jdogresorg Oct 1, 2026
e4f6454
Merge master (v0.21.2 release) back into develop
jdogresorg Oct 2, 2026
a842a10
Bounded container stop budget and bootstrap restore fixes (review rou…
jdogresorg Oct 2, 2026
7d80c33
Refuse reset on an unreadable node registry, a partial unstake, a mal…
jdogresorg Oct 2, 2026
0776456
Let a re-executed release update wait out a mutator that takes the co…
jdogresorg Oct 2, 2026
3769b60
Pass origin indexer endpoints to indexers
jdogresorg Oct 2, 2026
9169ef5
Merge: Pass origin indexer endpoints to indexers
jdogresorg Oct 2, 2026
8814293
Wire anchor arm heights into rail legs
jdogresorg Oct 2, 2026
641aa5c
Preserve unset rail drive environment
jdogresorg Oct 2, 2026
402a23b
Add follower hash comparison utility
jdogresorg Oct 2, 2026
23c4e21
Split follower comparison test groups
jdogresorg Oct 2, 2026
484c812
Split rail anchor workflow test registration
jdogresorg Oct 2, 2026
3414ce3
Merge: Split follower comparison test groups
jdogresorg Oct 2, 2026
a083795
Merge: Split rail anchor workflow test registration
jdogresorg Oct 2, 2026
543ea28
Add follower clone planning helpers
jdogresorg Oct 2, 2026
991cdef
Add follower hash row reader
jdogresorg Oct 2, 2026
e767f70
Split follower clone test groups
jdogresorg Oct 2, 2026
3f9edd7
Merge: Add follower hash row reader
jdogresorg Oct 2, 2026
e4d409f
Merge: Split follower clone test groups
jdogresorg Oct 2, 2026
f8aba8b
Add DOGE follower rail comparison
jdogresorg Oct 2, 2026
2e80739
Prove the DOGE follower mismatch control by running the compare on fi…
jdogresorg Oct 2, 2026
108809e
Split the DOGE follower comparison tests into three describe blocks u…
jdogresorg Oct 2, 2026
8b5925a
Add optional rail activation inputs
jdogresorg Oct 2, 2026
f20cee6
Split rail arm workflow test suites
jdogresorg Oct 2, 2026
1af00db
Merge: Split rail arm workflow test suites
jdogresorg Oct 2, 2026
16a6f57
Write cross-stack URLs to rail drive env
jdogresorg Oct 2, 2026
2ff9bd4
Merge: Write cross-stack URLs to rail drive env
jdogresorg Oct 2, 2026
134ceb8
Configure armed rail hub anchor publishing
jdogresorg Oct 2, 2026
9a8a1e2
Add rail publisher funding helper
jdogresorg Oct 2, 2026
5b7e77c
Merge: Configure armed rail hub anchor publishing
jdogresorg Oct 2, 2026
8f9cdc2
Merge: Add rail publisher funding helper
jdogresorg Oct 2, 2026
6e027d3
Pass anchor stake and slash arms through to the hub and regtest indexers
jdogresorg Oct 2, 2026
add151c
Treat any null follower hash as MISSING in the compare
jdogresorg Oct 2, 2026
10fe263
Refuse zero anchor arm heights and assert output structure
jdogresorg Oct 2, 2026
47fc850
Merge remote-tracking branch 'origin/develop' into hand/v0213-e3hubpass
jdogresorg Oct 2, 2026
b04a5f0
Merge remote-tracking branch 'origin/develop' into hand/v0213-e3hubpass
jdogresorg Oct 2, 2026
fcbb021
Fund the standing hub's DOGE publisher on anchor-armed rail legs
jdogresorg Oct 2, 2026
1aed657
Select rail drive coin from matrix leg
jdogresorg Oct 3, 2026
6ce657f
Forward the hub llm credential to attest-mirror legs on request
jdogresorg Oct 3, 2026
fba765c
Merge: Select rail drive coin from matrix leg
jdogresorg Oct 3, 2026
387a026
Probe the hub llm credential once before an attest-mirror leg
jdogresorg Oct 3, 2026
7d098d5
chore(release): v0.21.3
jdogresorg Oct 3, 2026
b9de407
Add per-leg rail expectation resolver
jdogresorg Oct 3, 2026
314dfb9
Give a non-bitcoin rail leg a bitcoin .env.btc for the federation seed
jdogresorg Oct 3, 2026
e0109b3
Merge remote-tracking branch 'origin/develop' into lane/R-2-p8
jdogresorg Oct 3, 2026
8c375eb
Merge remote-tracking branch 'origin/develop' into hand/v0213-r2p8
jdogresorg Oct 3, 2026
7608a65
Merge remote-tracking branch 'origin/develop' into release/v0.21.3
jdogresorg Oct 3, 2026
1741cfc
Pin the v0.21.3 release manifest
jdogresorg Oct 3, 2026
b962972
Merge pull request #56 from XChain-Platform/release-manifest-v0.21.3
jdogresorg Oct 3, 2026
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
76 changes: 76 additions & 0 deletions .github/attest-mirror/hub-llm-probe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env node
'use strict'

// Copyright (c) 2025-2026 Dankest, LLC
// Based on XChain Platform by Dankest, LLC - https://dankest.llc
//
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This file is part of XChain Platform. Licensed under the GNU Affero
// General Public License v3.0 or later; see LICENSE.md. A commercial
// license (without AGPL source-disclosure terms) is available -
// contact legal@dankest.llc.

// One `--print` turn with the argv and credential env a venue hub's spawn
// transport uses, printing the CLI's verdict so a provider_error on the leg
// has a named cause. The hub logs only stderr, while the CLI reports auth and
// vendor failures as JSON on stdout. Never prints the credential.

const { spawnSync } = require('child_process')
const os = require('os')

const PROBE_MODEL = 'claude-sonnet-4-6'
const CREDENTIAL_KEYS = ['CLAUDE_CONFIG_DIR', 'CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY']

// The hub's buildCliArgs (xchain-hub src/providers/llm/claude_spawn.js) for a turn with no system prompt.
function probeArgs (model) {
return ['--print', '--output-format', 'json', '--model', model, '--tools', '',
'--no-session-persistence', '--setting-sources', '']
}

// The hub's childEnv over the hub_token resolution: ambient credentials out, the hub's pair in.
function probeEnv (env) {
const out = Object.assign({}, env)
for (const key of CREDENTIAL_KEYS) delete out[key]
out.CLAUDE_CODE_OAUTH_TOKEN = env.HUB_CLAUDE_CODE_OAUTH_TOKEN
out.CLAUDE_CONFIG_DIR = env.HUB_CLAUDE_CONFIG_DIR
return out
}

function redact (text, secret) {
const s = String(text || '')
return secret ? s.split(secret).join('***') : s
}

// The verdict line: exit code, the envelope's error fields and the first 300 characters of its text.
function describe (result, secret) {
let json = null
try { json = JSON.parse(result.stdout) } catch (_) { json = null }
const fields = json ? {
is_error: json.is_error, subtype: json.subtype, api_error_status: json.api_error_status,
result: redact(json.result, secret).slice(0, 300),
} : { stdout: redact(result.stdout, secret).slice(0, 300) }
return 'hub llm probe: exit ' + result.status + ' ' + JSON.stringify(fields) +
(result.stderr ? ' stderr: ' + redact(result.stderr, secret).trim().slice(0, 300) : '')
}

function main (env) {
const secret = env.HUB_CLAUDE_CODE_OAUTH_TOKEN
if (!secret || !env.HUB_CLAUDE_CONFIG_DIR) {
console.log('hub llm probe: skipped, no hub credential on this leg')
return 0
}
console.log('hub llm probe: credential length ' + secret.length +
', oauth-token form ' + /^sk-ant-oat/.test(secret))
const result = spawnSync(env.CLAUDE_BIN || 'claude', probeArgs(PROBE_MODEL), {
input: 'Reply with the single word: ok', env: probeEnv(env), cwd: os.tmpdir(),
encoding: 'utf8', timeout: 90000,
})
if (result.error) console.log('hub llm probe: spawn failed: ' + result.error.message)
else console.log(describe(result, secret))
return result.status === 0 ? 0 : 1
}

if (require.main === module) process.exitCode = main(process.env)

module.exports = { probeArgs, probeEnv, describe, main }
35 changes: 34 additions & 1 deletion .github/workflows/attest-mirror-leg.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Attest-mirror leg (regtest)

run-name: >-
Attest-mirror legs @ e2e ${{ inputs.e2e_ref || 'develop' }} ${{ inputs.legs || '(all)' }}
Attest-mirror legs @ e2e ${{ inputs.e2e_ref || 'develop' }} ${{ inputs.legs || '(all)' }}${{ inputs.hub_llm && ' +llm' || '' }}

# Runs L004-ACC's attest-mirror legs (`BF_STAMP_AHEAD_S=900 npm run test:attest-mirror`
# in xchain-e2e-test) on GitHub-hosted runners, ONE leg per job, all in parallel,
Expand Down Expand Up @@ -36,6 +36,10 @@ on:
description: 'Ref the service images and source roots are built at'
type: string
default: develop
hub_llm:
description: 'Give the venue hubs the HUB_CLAUDE_CODE_OAUTH_TOKEN secret so llm attestation cases run (regtest rail only)'
type: boolean
default: false

permissions:
contents: read
Expand Down Expand Up @@ -199,11 +203,40 @@ jobs:
echo "L004_LOG_DIR=$RUNNER_TEMP/am-logs" >> "$GITHUB_ENV"
mkdir -p "$RUNNER_TEMP/am-logs"

# The llm attestation provider on the venue hubs, ONLY when the dispatch asks
# for it (hub_llm, off by default and off on the schedule). A validator on
# testnet or mainnet answers ATTEST with its own LLM setup, which the hub
# resolves through xchain-hub src/lib/hub_credentials.js: a HUB_CLAUDE_CONFIG_DIR
# the hub owns, and on this rail the session's HUB_CLAUDE_CODE_OAUTH_TOKEN
# paired with it. The venue refuses an llm case unless all three of its
# needs are on the box (attestMirrorVenue assertLlmAvailable): the directory,
# a credential the hub's resolver accepts, and `claude` on the PATH the hub
# children inherit, pinned to the hub image's CLI version (xchain-hub Dockerfile).
# The directory sits outside am-logs, so the uploaded artifact never holds
# what the CLI writes there.
- name: Install the hub llm CLI (hub_llm only)
if: inputs.hub_llm == true
run: |
npm install -g --no-audit --no-fund @anthropic-ai/claude-code@2.1.266
command -v claude
mkdir -m 700 -p "$RUNNER_TEMP/hub-claude"

# The token rides this step's env and nothing else: the image builds and the
# standing stacks above never see it, and the leg forwards it only to its
# venue hub children (at5 forwardedHubCredentialEnv). It is masked before any
# leg output and never printed. With the credential on, one probe turn with
# the hub's own argv names the CLI's verdict first, because the hub logs only
# stderr and the CLI reports an auth or vendor failure on stdout.
- name: Run ${{ matrix.leg }}
working-directory: ${{ env.RAIL_ROOT }}/xchain-e2e-test
env:
LEG: ${{ matrix.leg }}
HUB_CLAUDE_CONFIG_DIR: ${{ inputs.hub_llm == true && format('{0}/hub-claude', runner.temp) || '' }}
HUB_CLAUDE_CODE_OAUTH_TOKEN: ${{ inputs.hub_llm == true && secrets.HUB_CLAUDE_CODE_OAUTH_TOKEN || '' }}
run: |
if [ -n "$HUB_CLAUDE_CODE_OAUTH_TOKEN" ]; then echo "::add-mask::$HUB_CLAUDE_CODE_OAUTH_TOKEN"; fi
node "$GITHUB_WORKSPACE/.github/attest-mirror/hub-llm-probe.js" | tee "$L004_LOG_DIR/hub-llm-probe.log" ||
echo "::warning::hub llm probe failed; llm cases on this leg will answer provider_error"
set +e
env L004_VENUE_ROOT="$RAIL_ROOT" ATTEST_MIRROR_CONCURRENCY=1 ATTEST_MIRROR_READY_TIMEOUT_MS=1200000 \
ATTEST_MIRROR_STACK_ROOT="$AM_ROOT" ATTEST_MIRROR_STACK_PREFIX=xca7 \
Expand Down
Loading
Loading