mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
1250 lines
73 KiB
YAML
1250 lines
73 KiB
YAML
name: CI
|
|
|
|
# studio is a parallel release line, not a feature branch: it carries the
|
|
# kernel changes Studio is built on, so it needs the same kernel gates main-v2
|
|
# has. Studio's own surface (desktop/next, desktop/frontend-next) exists only
|
|
# there and is covered by studio.yml.
|
|
on:
|
|
push:
|
|
branches: [main-v2, studio]
|
|
pull_request:
|
|
branches: [main-v2, studio]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
jobs:
|
|
# Cheap path gate for pull requests. PRs confined to docs/release-notes
|
|
# (or top-level Markdown) skip the heavy Go jobs, and PRs that cannot affect
|
|
# the desktop module skip the desktop jobs. Job-level `if` reports skipped,
|
|
# which satisfies the required status checks (lint, race, test) — a
|
|
# workflow-level paths-ignore would leave required checks pending and block
|
|
# merges. Gated jobs skip only on an explicit `false` output: wrapped in
|
|
# `always()`, a failed `changes` job (or a missing output) makes them run
|
|
# the full matrix instead of silently passing required checks as skipped.
|
|
# Pushes to main-v2 always run everything. Pull requests run the macOS and
|
|
# Windows legs only when `platform` is not 'false'; the rule lives in
|
|
# scripts/ci-platform-scope.sh and fails toward running them.
|
|
changes:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
code: ${{ steps.filter.outputs.code }}
|
|
desktop: ${{ steps.filter.outputs.desktop }}
|
|
sdk: ${{ steps.filter.outputs.sdk }}
|
|
scripts: ${{ steps.filter.outputs.scripts }}
|
|
platform: ${{ steps.filter.outputs.platform }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
fetch-depth: 0
|
|
- id: filter
|
|
run: |
|
|
code=true; desktop=true; sdk=true; scripts=true; platform=true
|
|
base=""
|
|
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
|
base="${{ github.event.pull_request.base.sha }}"
|
|
elif [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then
|
|
base="${{ github.event.before }}"
|
|
fi
|
|
if [ -n "$base" ] && git cat-file -e "$base^{commit}" 2>/dev/null; then
|
|
files=$(git diff --name-only --no-renames "$base" HEAD)
|
|
if [ -n "$files" ]; then
|
|
code=false; desktop=false; sdk=false; scripts=false
|
|
# Root-module CI: desktop/ is a separate module, so only the
|
|
# clearly unrelated paths below can skip it.
|
|
if echo "$files" | grep -qvE '^(docs/|release-notes/|desktop/|workers/|[^/]+\.md$)'; then code=true; fi
|
|
# desktop/ imports the root kernel via `replace reasonix => ../`,
|
|
# so only this clearly-unrelated set is safe to skip.
|
|
if echo "$files" | grep -qvE '^(docs/|release-notes/|workers/|benchmarks/|npm/|[^/]+\.md$)'; then desktop=true; fi
|
|
# sdk/go is a nested module invisible to root `go test ./...`;
|
|
# its DTOs are generated from internal/ext/extension/protocol, so
|
|
# both paths must trigger the sdk job.
|
|
if echo "$files" | grep -qE '^(sdk/|internal/ext/extension/)'; then sdk=true; fi
|
|
# The release-note tests render every committed Studio note; npm/ holds the publish tests.
|
|
if echo "$files" | grep -qE '^(scripts/|npm/|release-notes/studio/|\.github/workflows/release-studio\.yml$)'; then scripts=true; fi
|
|
platform=$(git diff -z --name-only --no-renames "$base" HEAD | bash scripts/ci-platform-scope.sh)
|
|
fi
|
|
fi
|
|
{ echo "code=$code"; echo "desktop=$desktop"; echo "sdk=$sdk"; echo "scripts=$scripts"; echo "platform=$platform"; } >> "$GITHUB_OUTPUT"
|
|
|
|
release-notes-scripts:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || needs.changes.outputs.scripts != 'false')
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7
|
|
with:
|
|
node-version: "22"
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
- run: node --test scripts/linux-install-smoke.test.mjs scripts/studio-artifacts.test.mjs scripts/ci-platform-scope.test.mjs scripts/cli-archive-build.test.mjs scripts/cli-archive-contents.test.mjs scripts/release-credits.test.mjs scripts/update-contributors.test.mjs scripts/update-acknowledgments.test.mjs scripts/markdown-refs.test.mjs scripts/studio-release-notes.test.mjs scripts/publish-cli-pointer.test.mjs scripts/studio-release-flags.test.mjs scripts/studio-notes-publish.test.mjs scripts/withdraw-version.test.mjs scripts/brew-cask-guard.test.mjs scripts/feedback-sync.test.mjs npm/publish.test.mjs
|
|
|
|
# The ruleset requires the per-OS check names (test (ubuntu-latest) etc.).
|
|
# A matrix job skipped at job level reports no per-leg checks at all, so
|
|
# those required checks would stay "Expected" and block merging. The job
|
|
# therefore always runs and the steps do the gating: when the changes
|
|
# detector reports the diff is unrelated, every step skips and each leg
|
|
# reports success in seconds. `always()` also keeps the legs alive when
|
|
# the changes job itself fails (fail-open: an empty output != 'false').
|
|
# A pull request with no platform-relevant change moves the macOS and
|
|
# Windows legs onto an ubuntu runner with every step skipped: the check
|
|
# names the ruleset requires still report, without a scarce runner.
|
|
test:
|
|
needs: changes
|
|
if: always()
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
runs-on: ${{ github.event_name == 'pull_request' && needs.changes.outputs.platform == 'false' && 'ubuntu-latest' || matrix.os }}
|
|
env:
|
|
RUN_STEPS: ${{ github.event_name != 'pull_request' || (needs.changes.outputs.code != 'false' && (matrix.os == 'ubuntu-latest' || needs.changes.outputs.platform != 'false')) }}
|
|
steps:
|
|
- if: env.RUN_STEPS == 'true'
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- if: env.RUN_STEPS == 'true'
|
|
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
|
|
- name: Install and verify Linux sandbox backend
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Linux'
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y bubblewrap
|
|
if sysctl -n kernel.unprivileged_userns_clone >/dev/null 2>&1; then
|
|
sudo sysctl -w kernel.unprivileged_userns_clone=1
|
|
fi
|
|
if sysctl -n kernel.apparmor_restrict_unprivileged_userns >/dev/null 2>&1; then
|
|
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
|
fi
|
|
bwrap --ro-bind / / --dev /dev --proc /proc -- true || \
|
|
echo "::warning::bubblewrap is installed but this runner denies user namespaces; unavailable-backend tests will run fail-closed"
|
|
|
|
# Skipped on Windows: the runner checks out CRLF, so gofmt -l flags every
|
|
# file. gofmt output is OS-independent, so the Unix legs already cover it.
|
|
- name: gofmt
|
|
if: env.RUN_STEPS == 'true' && runner.os != 'Windows'
|
|
run: |
|
|
# Root module only — desktop/ is a separate module with its own tooling.
|
|
unformatted=$(gofmt -l . | grep -v '^desktop/' || true)
|
|
if [ -n "$unformatted" ]; then
|
|
echo "These files are not gofmt-clean:"
|
|
echo "$unformatted"
|
|
exit 1
|
|
fi
|
|
|
|
- name: vet
|
|
if: env.RUN_STEPS == 'true'
|
|
run: go vet ./...
|
|
|
|
- name: build
|
|
if: env.RUN_STEPS == 'true'
|
|
run: go build ./...
|
|
|
|
# The trajectory analyzer is the last consumer of the todo_progress frame,
|
|
# so a rename anywhere upstream has to fail somewhere. Standard library
|
|
# only; the runner's python3 is enough.
|
|
- name: test (trajectory tools)
|
|
if: env.RUN_STEPS == 'true' && runner.os != 'Windows'
|
|
run: python3 -m unittest discover -s tools/trajectory -t tools/trajectory
|
|
|
|
# A hardware exception on a Windows host whose CPU saves a large XSTATE
|
|
# (Intel AMX) can corrupt the Go heap (golang/go#81238). The runner pool
|
|
# mixes hosts, so a runtime crash is only attributable with the CPU on record.
|
|
- name: runner CPU
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows'
|
|
shell: pwsh
|
|
run: Get-CimInstance Win32_Processor | Select-Object -ExpandProperty Name
|
|
|
|
- name: test
|
|
if: env.RUN_STEPS == 'true' && runner.os != 'Windows'
|
|
env:
|
|
# Run the prompt-cache prefix-stability guard (TestCacheHit*) in CI: a
|
|
# regression there silently tanks the cache hit rate the project is
|
|
# built around.
|
|
REASONIX_RELEASE_CACHE_GUARD: "1"
|
|
run: go test ./...
|
|
|
|
- name: test (Windows composition links)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(CaptureDirectoryMaterializesContainedLinks|CaptureDirectoryRefusesUnsafeLinks|CaptureHookFileFlattensContainedLink|MaterializeStillRejectsLinkedRetainedFilesAndRoot|WindowsCompositionJunctions|WindowsLiveSkillJunctions|CompositionRetainsLinkedSkillAcrossRestart|CompositionLinkedSkillRejectsLinkedResources|CompositionLinkedExtensionResources|CompositionLinkedHookResources)$' ./internal/state/agentpreset ./internal/ext/skill ./internal/assembly/boot | tee "$RUNNER_TEMP/composition-links.jsonl"
|
|
jq -se '
|
|
["TestCaptureDirectoryMaterializesContainedLinks", "TestCaptureDirectoryRefusesUnsafeLinks",
|
|
"TestCaptureHookFileFlattensContainedLink", "TestMaterializeStillRejectsLinkedRetainedFilesAndRoot",
|
|
"TestWindowsCompositionJunctions", "TestWindowsLiveSkillJunctions", "TestCompositionRetainsLinkedSkillAcrossRestart",
|
|
"TestCompositionLinkedSkillRejectsLinkedResources", "TestCompositionLinkedExtensionResources",
|
|
"TestCompositionLinkedHookResources"] as $required |
|
|
[.[] | select(.Action == "pass") | .Test] as $passed |
|
|
all(.[]; .Action != "skip") and (($required - $passed) | length == 0)
|
|
' "$RUNNER_TEMP/composition-links.jsonl"
|
|
|
|
# Pull requests run a Windows smoke suite: the packages that actually
|
|
# carry *_windows.go code, the startup/checkpoint packages with portable
|
|
# filesystem contracts, plus cmd/. Isolation/worktree/mutation have a
|
|
# complete JSON inventory below. The full ./... sweep stays on pushes
|
|
# to main-v2; the Unix legs always run the full suite. Keep the job-level
|
|
# budget above normal 7-9 minute runner variance; each package test binary
|
|
# remains independently bounded by Go's per-package timeout below.
|
|
#
|
|
# The per-package timeout is 18m: internal/assembly/boot took 478-717s
|
|
# (12 push runs) on the Windows runner, so 18m is 1.5x the worst. A hang
|
|
# still trips the step budget (25m smoke, 35m full).
|
|
#
|
|
# Every root-module `go test` that runs on Windows passes -count=1. With
|
|
# the result cache on, go test records each file and environment access
|
|
# a test binary makes, and before and after the run resolves every
|
|
# recorded path outside the module through filepath.EvalSymlinks.
|
|
# internal/assembly/boot records about 1.9M accesses; on a Windows runner
|
|
# that bookkeeping costs minutes per pass while nothing is printed.
|
|
# internal/base/testenv holds every such step to it.
|
|
- name: test (Windows smoke)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 25
|
|
env:
|
|
REASONIX_RELEASE_CACHE_GUARD: "1"
|
|
WINDOWS_SANDBOX_WAIT_MS: "20000"
|
|
run: go test -count=1 -p 4 -timeout=18m ./internal/runtime/agent/... ./internal/platform/appidentity/... ./internal/assembly/boot/... ./internal/state/checkpoint/... ./internal/frontend/cli/... ./internal/session/control/... ./internal/base/filelock/... ./internal/base/fileutil/... ./internal/ext/hook/... ./internal/state/instruction/... ./internal/ext/mcplaunch/... ./internal/platform/notify/... ./internal/base/proc/... ./internal/platform/remote/... ./internal/platform/repair/... ./internal/safety/sandbox/... ./internal/base/sysproxy/... ./internal/state/workspacelease/... ./cmd/...
|
|
|
|
- name: test (Windows published command job owner)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
evidence="$RUNNER_TEMP/published-job-owner"
|
|
mkdir -p "$evidence"
|
|
go test -count=1 -timeout=3m -json -run '^TestPublishedJob' ./internal/base/proc | tee "$evidence/positive.jsonl"
|
|
node scripts/published-job-evidence.mjs positive "$evidence/positive.jsonl"
|
|
node scripts/published-job-evidence.mjs overlay "$evidence"
|
|
set +e
|
|
go test -count=1 -timeout=3m -json -overlay="$evidence/overlay.json" -run '^TestPublishedJob' ./internal/base/proc > "$evidence/negative.jsonl"
|
|
old_result=$?
|
|
set -e
|
|
test "$old_result" -eq 1
|
|
node scripts/published-job-evidence.mjs negative "$evidence/negative.jsonl"
|
|
|
|
- name: upload Windows published command job owner evidence
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: published-job-owner-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/published-job-owner/
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
- name: test (Windows isolation owners)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 25
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -p 4 -timeout=18m -json ./internal/runtime/isolation/... ./internal/platform/worktree/... ./internal/state/mutation/... | tee "$RUNNER_TEMP/isolation-owners.jsonl" |
|
|
jq -rj --unbuffered 'select(.Action == "output" and .Test == null) | .Output'
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $passed |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
(["reasonix/internal/runtime/isolation", "reasonix/internal/platform/worktree", "reasonix/internal/state/mutation"] - $passed | length) == 0 and
|
|
(["TestResultOperationUsesCrossProcessOwnership",
|
|
"TestActualResultOperationHoldsOwnershipThroughWriteAndCleanup/restore",
|
|
"TestActualResultOperationHoldsOwnershipThroughWriteAndCleanup/remove",
|
|
"TestApplyPathsWithUntrustedModesPreservesTheIndex/content",
|
|
"TestApplyPathsWithUntrustedModesPreservesTheIndex/source_index_mode",
|
|
"TestApplyPathsWithUntrustedModesPreservesTheIndex/candidate_mode",
|
|
"TestApplyPathsWithUntrustedModesPreservesTheIndex/candidate_type",
|
|
"TestApplyPathsEmulatedLinksUseSnapshotFilters",
|
|
"TestHeldPathsCoverOnlyTheSameFileAcrossCaseSpellings",
|
|
"TestLegacyWaitDoesNotConsumeExecutionCapacity"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/isolation-owners.jsonl"
|
|
|
|
- name: upload Windows isolation test inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: isolation-owners-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/isolation-owners.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows background resource owners)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 25
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -p 2 -timeout=18m -json ./internal/tools/jobs/... ./internal/runtime/delegation/... | tee "$RUNNER_TEMP/background-resources.jsonl" |
|
|
jq -rj --unbuffered 'select(.Action == "output" and .Test == null) | .Output'
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
(["reasonix/internal/tools/jobs", "reasonix/internal/runtime/delegation"] - $packages | length) == 0 and
|
|
(["TestJobFinalizationCoversInvokedAndUninvoked/success",
|
|
"TestJobFinalizationCoversInvokedAndUninvoked/error",
|
|
"TestJobFinalizationCoversInvokedAndUninvoked/panic",
|
|
"TestJobFinalizationCoversInvokedAndUninvoked/closed",
|
|
"TestJobFinalizationCoversInvokedAndUninvoked/invalid_session",
|
|
"TestJobFinalizationCoversInvokedAndUninvoked/invalid_kind",
|
|
"TestJobFinalizationFailuresAttemptAllCallbacksAndKeepCauses/invoked",
|
|
"TestJobFinalizationFailuresAttemptAllCallbacksAndKeepCauses/uninvoked",
|
|
"TestJobFinalizationPrecedesCompletionPublication",
|
|
"TestJobFinalizationCloseBetweenPublicationAndLaunch",
|
|
"TestJobFinalizationWaitsForClosureAfterLogicalCancellation",
|
|
"TestBackgroundNoLaunchFinalizesOwnedResources/task/closed_manager",
|
|
"TestBackgroundNoLaunchFinalizesOwnedResources/task/invalid_session",
|
|
"TestBackgroundNoLaunchFinalizesOwnedResources/fleet/closed_manager",
|
|
"TestBackgroundNoLaunchFinalizesOwnedResources/fleet/invalid_session"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/background-resources.jsonl"
|
|
|
|
- name: upload Windows background resource inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: background-resources-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/background-resources.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows delegated Goal usage scope)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(UsageScope.*|DelegatedUsageKeepsGoalOwner|EffectDelegatedUsageKeepsGoalOwner)$' ./internal/contract/event ./internal/session/control ./internal/assembly/boot | tee "$RUNNER_TEMP/goal-usage-scope.jsonl"
|
|
jq -se '
|
|
["TestUsageScopePreservesCapturedOwnerAndWire", "TestUsageScopeKeepsEarlierEventOwner",
|
|
"TestUsageScopeWithoutCapability", "TestDelegatedUsageKeepsGoalOwner",
|
|
"TestDelegatedUsageKeepsGoalOwner/chat_to_goal", "TestDelegatedUsageKeepsGoalOwner/replaced_goal",
|
|
"TestDelegatedUsageKeepsGoalOwner/cleared_goal", "TestDelegatedUsageKeepsGoalOwner/resumed_goal",
|
|
"TestDelegatedUsageKeepsGoalOwner/same_goal_next_turn", "TestDelegatedUsageKeepsGoalOwner/between_turns",
|
|
"TestDelegatedUsageKeepsGoalOwner/nested_after_replacement", "TestEffectDelegatedUsageKeepsGoalOwner",
|
|
"TestEffectDelegatedUsageKeepsGoalOwner/chat_to_goal", "TestEffectDelegatedUsageKeepsGoalOwner/replaced_goal",
|
|
"TestEffectDelegatedUsageKeepsGoalOwner/nested_chat_to_goal", "TestEffectDelegatedUsageKeepsGoalOwner/same_goal",
|
|
"TestEffectDelegatedUsageKeepsGoalOwner/completed_before_goal"] as $required |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $passed |
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
all(.[]; .Action != "fail" and .Action != "skip") and
|
|
(($required - $passed) | length == 0) and
|
|
((["reasonix/internal/contract/event", "reasonix/internal/session/control", "reasonix/internal/assembly/boot"] - $packages) | length == 0)
|
|
' "$RUNNER_TEMP/goal-usage-scope.jsonl"
|
|
|
|
- name: upload Windows delegated Goal usage scope inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: goal-usage-scope-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/goal-usage-scope.jsonl
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
- name: test (Windows planner local budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^TestEffectPlannerConfiguredTaskBudget$' ./internal/assembly/boot | tee "$RUNNER_TEMP/planner-local-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestEffectPlannerConfiguredTaskBudget", "TestEffectPlannerConfiguredTaskBudget/tokens",
|
|
"TestEffectPlannerConfiguredTaskBudget/cost", "TestEffectPlannerConfiguredTaskBudget/wall",
|
|
"TestEffectPlannerConfiguredTaskBudget/unconfigured", "TestEffectPlannerConfiguredTaskBudget/explicit_zero",
|
|
"TestEffectPlannerConfiguredTaskBudget/unpriced_cost", "TestEffectPlannerConfiguredTaskBudget/missing_usage_cost",
|
|
"TestEffectPlannerConfiguredTaskBudget/context_bound", "TestEffectPlannerConfiguredTaskBudget/context_disables",
|
|
"TestEffectPlannerConfiguredTaskBudget/executor_only"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/planner-local-budget.jsonl"
|
|
|
|
- name: upload Windows planner local budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: planner-local-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/planner-local-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows Controller routing root budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(SemanticRootUsage|EffectRoutingRootBudget)$' ./internal/runtime/capability ./internal/assembly/boot | tee "$RUNNER_TEMP/controller-routing-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/runtime/capability", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
([
|
|
"TestEffectRoutingRootBudget",
|
|
"TestEffectRoutingRootBudget/balanced",
|
|
"TestEffectRoutingRootBudget/cached_continuation",
|
|
"TestEffectRoutingRootBudget/cached_new_scope",
|
|
"TestEffectRoutingRootBudget/cached_new_task",
|
|
"TestEffectRoutingRootBudget/cached_reset",
|
|
"TestEffectRoutingRootBudget/context_zero",
|
|
"TestEffectRoutingRootBudget/dual",
|
|
"TestEffectRoutingRootBudget/headless",
|
|
"TestEffectRoutingRootBudget/interactive",
|
|
"TestEffectRoutingRootBudget/missing",
|
|
"TestEffectRoutingRootBudget/unconfigured",
|
|
"TestSemanticRootUsage",
|
|
"TestSemanticRootUsage/billed_error",
|
|
"TestSemanticRootUsage/cache",
|
|
"TestSemanticRootUsage/estimated",
|
|
"TestSemanticRootUsage/invalid_answer",
|
|
"TestSemanticRootUsage/missing",
|
|
"TestSemanticRootUsage/nil_sink",
|
|
"TestSemanticRootUsage/no_observer",
|
|
"TestSemanticRootUsage/reported"
|
|
] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/controller-routing-budget.jsonl"
|
|
|
|
- name: upload Windows Controller routing root budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: controller-routing-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/controller-routing-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows Coordinator root budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(PreparedRootBudget|CoordinatorRootBudget|EffectCoordinatorRoot)' ./internal/runtime/agent ./internal/runtime/coordinator ./internal/assembly/boot | tee "$RUNNER_TEMP/coordinator-root-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/runtime/agent", "reasonix/internal/runtime/coordinator", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestPreparedRootBudgetLifetime", "TestPreparedRootBudgetLifetime/continuation",
|
|
"TestPreparedRootBudgetLifetime/new_scope", "TestPreparedRootBudgetLifetime/new_task",
|
|
"TestPreparedRootBudgetLifetime/reset", "TestPreparedRootBudgetLifetime/new_session",
|
|
"TestPreparedRootBudgetProjectionAndPreservedTurn", "TestCoordinatorRootBudgetRoutes",
|
|
"TestCoordinatorRootBudgetRoutes/raw", "TestCoordinatorRootBudgetRoutes/tool_planner",
|
|
"TestCoordinatorRootBudgetRoutes/failure_fallback", "TestCoordinatorRootBudgetRoutes/plan_only_continuation",
|
|
"TestCoordinatorRootBudgetRoutes/approval_declined_continuation", "TestCoordinatorRootBudgetRoutes/approval_allowed",
|
|
"TestEffectCoordinatorRootTokenBudget", "TestEffectCoordinatorRootTokenBudget/shared",
|
|
"TestEffectCoordinatorRootTokenBudget/unconfigured", "TestEffectCoordinatorRootTokenBudget/context_disables",
|
|
"TestEffectCoordinatorRootTokenBudget/missing_planner", "TestEffectCoordinatorRootTokenBudget/executor_only"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/coordinator-root-budget.jsonl"
|
|
|
|
- name: upload Windows Coordinator root budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: coordinator-root-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/coordinator-root-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows resumed Goal planner budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(GoalResumeRenewsPlannerBudget|GoalNonBudgetResumeKeepsPlannerBudget|GoalTokenBudgetPausesAndResumes|EffectGoalResumeRenewsPlannerBudget)$' ./internal/session/control ./internal/assembly/boot | tee "$RUNNER_TEMP/goal-planner-resume.jsonl"
|
|
jq -se '
|
|
["TestGoalResumeRenewsPlannerBudget",
|
|
"TestGoalNonBudgetResumeKeepsPlannerBudget",
|
|
"TestGoalNonBudgetResumeKeepsPlannerBudget/manual_pause",
|
|
"TestGoalNonBudgetResumeKeepsPlannerBudget/not_resumable",
|
|
"TestGoalTokenBudgetPausesAndResumes",
|
|
"TestEffectGoalResumeRenewsPlannerBudget"] as $required |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $passed |
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
all(.[]; .Action != "fail" and .Action != "skip") and
|
|
(($required - $passed) | length == 0) and
|
|
((["reasonix/internal/session/control", "reasonix/internal/assembly/boot"] - $packages) | length == 0)
|
|
' "$RUNNER_TEMP/goal-planner-resume.jsonl"
|
|
|
|
- name: upload Windows resumed Goal planner budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: goal-planner-resume-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/goal-planner-resume.jsonl
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
- name: test (Windows root wall budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(RootWall|EffectRootWall)' ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/root-wall-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestRootWallBudgetReachesDelegatedAgents", "TestRootWallBudgetReachesDelegatedAgents/foreground",
|
|
"TestRootWallBudgetReachesDelegatedAgents/nested", "TestRootWallBudgetReachesDelegatedAgents/siblings",
|
|
"TestRootWallBudgetReachesDelegatedAgents/context", "TestRootWallBudgetReachesDelegatedAgents/unconfigured",
|
|
"TestRootWallBudgetReachesDelegatedAgents/explicit_zero", "TestRootWallBudgetContinuationAndReset",
|
|
"TestRootWallBudgetContinuationAndReset/continuation", "TestRootWallBudgetContinuationAndReset/new_task",
|
|
"TestRootWallBudgetContinuationAndReset/reset", "TestRootWallBudgetContinuationAndReset/override",
|
|
"TestRootWallBudgetProjectionKeepsJobDeadline", "TestEffectRootWallBudgetReachesManagedJobs",
|
|
"TestEffectRootWallBudgetReachesManagedJobs/task", "TestEffectRootWallBudgetReachesManagedJobs/capability",
|
|
"TestEffectRootWallBudgetReachesManagedJobs/fleet"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/root-wall-budget.jsonl"
|
|
|
|
- name: upload Windows root wall budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: root-wall-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/root-wall-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows root token budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(RootToken|EffectRootToken)' ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/root-token-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestRootTokenBudgetIncludesChildProviderUsage", "TestRootTokenBudgetIncludesChildProviderUsage/configured",
|
|
"TestRootTokenBudgetIncludesChildProviderUsage/context", "TestRootTokenBudgetIncludesChildProviderUsage/unconfigured",
|
|
"TestRootTokenBudgetIncludesChildProviderUsage/explicit_zero", "TestRootTokenBudgetSurvivesNestedAndConcurrentChildren",
|
|
"TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/nested", "TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/siblings",
|
|
"TestRootTokenBudgetSurvivesNestedAndConcurrentChildren/child_override", "TestRootTokenBudgetContinuationAndReset",
|
|
"TestRootTokenBudgetContinuationAndReset/continuation", "TestRootTokenBudgetContinuationAndReset/new_task",
|
|
"TestRootTokenBudgetContinuationAndReset/reset", "TestRootTokenScopeAtomicAccountingAndJobCancellation",
|
|
"TestEffectRootTokenBudgetReachesDelegatedJobs", "TestEffectRootTokenBudgetReachesDelegatedJobs/foreground",
|
|
"TestEffectRootTokenBudgetReachesDelegatedJobs/foreground_capability", "TestEffectRootTokenBudgetReachesDelegatedJobs/background",
|
|
"TestEffectRootTokenBudgetReachesDelegatedJobs/background_capability", "TestEffectRootTokenBudgetReachesDelegatedJobs/background_fleet"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/root-token-budget.jsonl"
|
|
|
|
- name: upload Windows root token budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: root-token-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/root-token-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows budget usage completeness)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(RequestOnlyUsage|RunBudgetMissingUsage|TaskBudgetKnownCost|RunBudgetExplicitZero|TaskBudgetUsageCompleteness|TaskBudgetCostUses|EffectBudgetCompleteness|TaskBudgetGateIgnoresCostWhenUnpriced)' ./internal/contract/provider ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/budget-usage.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/contract/provider", "reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestRequestOnlyUsageDoesNotCertifyTokenAccounting", "TestRunBudgetMissingUsageKeepsCostIncomplete",
|
|
"TestRunBudgetMissingUsageKeepsCostIncomplete/complete", "TestRunBudgetMissingUsageKeepsCostIncomplete/missing_first",
|
|
"TestRunBudgetMissingUsageKeepsCostIncomplete/missing_last", "TestRunBudgetMissingUsageKeepsCostIncomplete/all_missing",
|
|
"TestTaskBudgetKnownCostStillLandsAfterMissingUsage", "TestRunBudgetExplicitZeroUsageIsPriced",
|
|
"TestTaskBudgetUsageCompletenessFollowsItsLifetime", "TestTaskBudgetUsageCompletenessFollowsItsLifetime/continuation",
|
|
"TestTaskBudgetUsageCompletenessFollowsItsLifetime/new_task", "TestTaskBudgetUsageCompletenessFollowsItsLifetime/explicit_reset",
|
|
"TestTaskBudgetCostUsesOnlyTheReportedSubtotal", "TestTaskBudgetGateIgnoresCostWhenUnpriced",
|
|
"TestEffectBudgetCompletenessFromOpenAIStream", "TestEffectBudgetCompletenessFromOpenAIStream/missing_0",
|
|
"TestEffectBudgetCompletenessFromOpenAIStream/missing_1", "TestEffectBudgetCompletenessFromOpenAIStream/missing_2"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/budget-usage.jsonl"
|
|
|
|
- name: upload Windows budget usage inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: budget-usage-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/budget-usage.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
|
|
- name: test (Windows Git storage environment)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(HostStorageEnvironment|HostObjectStorage|HostExplicitStorageControls|DetachedStorageEnvironment|WorktreePreparationOwnsItsIndex|EffectIsolatedTaskOwnsGitStorage)$' ./internal/platform/gitcmd ./internal/platform/worktree ./internal/assembly/boot | tee "$RUNNER_TEMP/git-storage-environment.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/platform/gitcmd", "reasonix/internal/platform/worktree", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
([
|
|
"TestDetachedStorageEnvironment",
|
|
"TestDetachedStorageEnvironment/explicit_env",
|
|
"TestDetachedStorageEnvironment/inherited_env",
|
|
"TestEffectIsolatedTaskOwnsGitStorage",
|
|
"TestEffectIsolatedTaskOwnsGitStorage/ambient_existing",
|
|
"TestEffectIsolatedTaskOwnsGitStorage/ambient_missing",
|
|
"TestEffectIsolatedTaskOwnsGitStorage/control",
|
|
"TestHostExplicitStorageControls",
|
|
"TestHostExplicitStorageControls/explicit_object_directory",
|
|
"TestHostExplicitStorageControls/private_index",
|
|
"TestHostExplicitStorageControls/repository_declared_alternate",
|
|
"TestHostObjectStorage",
|
|
"TestHostObjectStorage/ambient_alternate_not_read",
|
|
"TestHostObjectStorage/writes_stay_in_repository",
|
|
"TestHostStorageEnvironment",
|
|
"TestHostStorageEnvironment/GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
|
"TestHostStorageEnvironment/GIT_INDEX_FILE",
|
|
"TestHostStorageEnvironment/GIT_OBJECT_DIRECTORY",
|
|
"TestWorktreePreparationOwnsItsIndex",
|
|
"TestWorktreePreparationOwnsItsIndex/candidate_ambient_existing",
|
|
"TestWorktreePreparationOwnsItsIndex/candidate_ambient_missing",
|
|
"TestWorktreePreparationOwnsItsIndex/candidate_control",
|
|
"TestWorktreePreparationOwnsItsIndex/delivery_ambient_existing",
|
|
"TestWorktreePreparationOwnsItsIndex/delivery_ambient_missing",
|
|
"TestWorktreePreparationOwnsItsIndex/delivery_control"
|
|
] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/git-storage-environment.jsonl"
|
|
|
|
- name: upload Windows Git storage environment inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: git-storage-environment-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/git-storage-environment.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows Anthropic interrupted usage)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(InterruptedUsage|EffectAnthropicPartialUsageRecovery)' ./internal/model/anthropic ./internal/assembly/boot | tee "$RUNNER_TEMP/anthropic-interrupted-usage.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/model/anthropic", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestInterruptedUsageTerminal", "TestInterruptedUsageTerminal/upstream_error",
|
|
"TestInterruptedUsageTerminal/payload_error", "TestInterruptedUsageTerminal/premature_eof",
|
|
"TestInterruptedUsageTerminal/decode_error", "TestInterruptedUsageTerminal/reported_zero",
|
|
"TestInterruptedUsageTerminal/missing_control", "TestInterruptedUsageTerminal/complete_control",
|
|
"TestInterruptedUsageBoundedConsumer", "TestInterruptedUsageReadErrorAndCancellation",
|
|
"TestInterruptedUsageReadErrorAndCancellation/read_error", "TestInterruptedUsageReadErrorAndCancellation/cancelled_buffered_reader",
|
|
"TestInterruptedUsageAbandonedConsumer", "TestInterruptedUsageIdleTimeout",
|
|
"TestEffectAnthropicPartialUsageRecovery", "TestEffectAnthropicPartialUsageRecovery/upstream_error",
|
|
"TestEffectAnthropicPartialUsageRecovery/premature_eof", "TestEffectAnthropicPartialUsageRecovery/complete_control"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/anthropic-interrupted-usage.jsonl"
|
|
|
|
- name: upload Windows Anthropic interrupted usage inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: anthropic-interrupted-usage-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/anthropic-interrupted-usage.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows root websearch budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(RootWebSearch|EffectRootWebSearch)' ./internal/tools/websearch ./internal/assembly/boot | tee "$RUNNER_TEMP/root-websearch-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/tools/websearch", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestRootWebSearchUsageTerminal", "TestRootWebSearchUsageTerminal/reported",
|
|
"TestRootWebSearchUsageTerminal/no_reporter", "TestRootWebSearchUsageTerminal/missing",
|
|
"TestRootWebSearchUsageTerminal/no_observer", "TestRootWebSearchUsageTerminal/input_refused",
|
|
"TestRootWebSearchUsageTerminal/no_factory", "TestRootWebSearchUsageTerminal/factory_error",
|
|
"TestRootWebSearchUsageTerminal/billed_failure", "TestRootWebSearchUsageTerminal/cancel_after_usage",
|
|
"TestRootWebSearchUsageTerminal/cancel_before_start", "TestRootWebSearchUsageTerminal/stream_error",
|
|
"TestEffectRootWebSearchTokenBudget", "TestEffectRootWebSearchTokenBudget/reported",
|
|
"TestEffectRootWebSearchTokenBudget/disabled", "TestEffectRootWebSearchTokenBudget/missing"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/root-websearch-budget.jsonl"
|
|
|
|
- name: upload Windows root websearch budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: root-websearch-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/root-websearch-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows explicit skill root budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^(TestProfileRootBudgetLifetime|TestProfileBudgetPreparationUsesTurnAdmission|TestEffectExplicitSkillRootBudget)$' ./internal/session/control ./internal/assembly/boot | tee "$RUNNER_TEMP/explicit-skill-root-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/session/control", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestProfileRootBudgetLifetime", "TestProfileRootBudgetLifetime/new_task",
|
|
"TestProfileRootBudgetLifetime/same_scope", "TestProfileRootBudgetLifetime/new_scope",
|
|
"TestProfileRootBudgetLifetime/reset", "TestProfileRootBudgetLifetime/new_session",
|
|
"TestProfileRootBudgetLifetime/inherited", "TestProfileRootBudgetLifetime/context_zero",
|
|
"TestProfileBudgetPreparationUsesTurnAdmission", "TestEffectExplicitSkillRootBudget",
|
|
"TestEffectExplicitSkillRootBudget/profile", "TestEffectExplicitSkillRootBudget/preview",
|
|
"TestEffectExplicitSkillRootBudget/slash", "TestEffectExplicitSkillRootBudget/chips",
|
|
"TestEffectExplicitSkillRootBudget/goal", "TestEffectExplicitSkillRootBudget/context_zero",
|
|
"TestEffectExplicitSkillRootBudget/unconfigured"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/explicit-skill-root-budget.jsonl"
|
|
|
|
- name: upload Windows explicit skill root budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: explicit-skill-root-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/explicit-skill-root-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows root triage budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(RootTriage|EffectRootTriage)' ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/root-triage-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestRootTriageTokenBudget", "TestRootTriageTokenBudget/classifier", "TestRootTriageTokenBudget/screen",
|
|
"TestRootTriageTokenBudget/billed_failure", "TestRootTriageTokenBudget/missing", "TestRootTriageTokenBudget/disabled",
|
|
"TestRootTriageTokenBudget/no_sink", "TestRootTriageTokenBudget/counts_without_total",
|
|
"TestRootTriageOutsideRunDoesNotCreateScope", "TestEffectRootTriageScreenBudget",
|
|
"TestEffectRootTriageScreenBudget/reported", "TestEffectRootTriageScreenBudget/flagged",
|
|
"TestEffectRootTriageScreenBudget/disabled", "TestEffectRootTriageScreenBudget/missing",
|
|
"TestEffectRootTriageScreenBudget/screen_disabled"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/root-triage-budget.jsonl"
|
|
|
|
- name: upload Windows root triage budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: root-triage-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/root-triage-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows root auxiliary budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(RootAuxiliary|EffectRootAuxiliary)' ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/root-auxiliary-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestRootAuxiliaryAutomaticCompaction", "TestRootAuxiliaryTokenBudget",
|
|
"TestRootAuxiliaryTokenBudget/summary", "TestRootAuxiliaryTokenBudget/summary_failed",
|
|
"TestRootAuxiliaryTokenBudget/summary_missing", "TestRootAuxiliaryTokenBudget/summary_disabled",
|
|
"TestRootAuxiliaryTokenBudget/diagnosis", "TestRootAuxiliaryTokenBudget/diagnosis_failed",
|
|
"TestRootAuxiliaryTokenBudget/diagnosis_missing", "TestRootAuxiliaryTokenBudget/diagnosis_disabled",
|
|
"TestRootAuxiliaryManualCompactionOutsideRun", "TestRootAuxiliaryBudgetProjectionKeepsOldTask",
|
|
"TestEffectRootAuxiliarySummaryBudget", "TestEffectRootAuxiliarySummaryBudget/configured",
|
|
"TestEffectRootAuxiliarySummaryBudget/disabled", "TestEffectRootAuxiliarySummaryBudget/missing_usage"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/root-auxiliary-budget.jsonl"
|
|
|
|
- name: upload Windows root auxiliary budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: root-auxiliary-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/root-auxiliary-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows local cost quote)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(LocalBudgetUsesOccurrenceQuote|LocalCost.*|UsageQuote.*|EffectLocalCostUsesOccurrenceQuote)$' ./internal/contract/event ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/local-cost-quote.jsonl"
|
|
jq -se '
|
|
["TestLocalBudgetUsesOccurrenceQuote", "TestLocalBudgetUsesOccurrenceQuote/peak", "TestLocalBudgetUsesOccurrenceQuote/offpeak",
|
|
"TestLocalCostKeepsOriginalCurrencyBuckets", "TestLocalCostFixedPointThresholdAndUnknown",
|
|
"TestUsageQuoteUsesOneOwnerAndOccurrence", "TestUsageQuoteLegacyAndNilSinks",
|
|
"TestEffectLocalCostUsesOccurrenceQuote", "TestEffectLocalCostUsesOccurrenceQuote/peak",
|
|
"TestEffectLocalCostUsesOccurrenceQuote/offpeak", "TestEffectLocalCostUsesOccurrenceQuote/relay"] as $required |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $passed |
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
all(.[]; .Action != "fail" and .Action != "skip") and
|
|
(($required - $passed) | length == 0) and
|
|
((["reasonix/internal/contract/event", "reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages) | length == 0)
|
|
' "$RUNNER_TEMP/local-cost-quote.jsonl"
|
|
|
|
- name: upload Windows local cost quote inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: local-cost-quote-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/local-cost-quote.jsonl
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
- name: test (Windows estimated usage quotes)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(EstimatedUsage|EffectEstimatedUsage|ToWireUsagePayloadJSON$|StatusExtensionTracksMultipleSessionsAndUsage$|CacheSplitProvenanceIsRecorded$|RecordedPlainCallIsUnchanged$)' ./internal/contract/pricing ./internal/contract/event ./internal/contract/config ./internal/assembly/boot ./internal/contract/eventwire ./internal/frontend/acp ./internal/state/stats | tee "$RUNNER_TEMP/estimated-quote.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/contract/pricing", "reasonix/internal/contract/event", "reasonix/internal/contract/config", "reasonix/internal/assembly/boot",
|
|
"reasonix/internal/contract/eventwire", "reasonix/internal/frontend/acp", "reasonix/internal/state/stats"] - $packages | length) == 0 and
|
|
(["TestEstimatedUsageQuotePreservesAmountsWithoutCompleteFacts", "TestEstimatedUsageQuotePreservesAmountsWithoutCompleteFacts/CNY",
|
|
"TestEstimatedUsageQuotePreservesAmountsWithoutCompleteFacts/USD", "TestEstimatedUsageLedgerRetainsPartialCoverage",
|
|
"TestEstimatedUsageLedgerRetainsPartialCoverage/separate_keys", "TestEstimatedUsageLedgerRetainsPartialCoverage/same_key",
|
|
"TestEstimatedUsageSavedQuoteReader", "TestEstimatedUsageQuoteSinkCoversTurnAndGuardian",
|
|
"TestEstimatedUsageQuoteSinkCoversTurnAndGuardian/turn", "TestEstimatedUsageQuoteSinkCoversTurnAndGuardian/guardian",
|
|
"TestEstimatedUsageConfiguredQuote", "TestEffectEstimatedUsageQuoteAfterStreamRecovery",
|
|
"TestEffectEstimatedUsageQuoteAfterStreamRecovery/reported_control", "TestEffectEstimatedUsageQuoteAfterStreamRecovery/interrupted",
|
|
"TestToWireUsagePayloadJSON", "TestStatusExtensionTracksMultipleSessionsAndUsage", "TestCacheSplitProvenanceIsRecorded", "TestRecordedPlainCallIsUnchanged"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/estimated-quote.jsonl"
|
|
|
|
- name: upload Windows estimated quote inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: estimated-quote-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/estimated-quote.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
- name: test (Windows bounded root budget)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
shell: bash
|
|
run: |
|
|
set -o pipefail
|
|
go test -count=1 -timeout=3m -json -run '^Test(AuxiliaryUsageObserver|BoundedUsageObserver|RootBounded|EffectRootBounded)' ./internal/contract/provider ./internal/model/boundedllm ./internal/runtime/agent ./internal/assembly/boot | tee "$RUNNER_TEMP/bounded-root-budget.jsonl"
|
|
jq -se '
|
|
[.[] | select(.Test == null and .Action == "pass") | .Package] as $packages |
|
|
[.[] | select(.Test != null and .Action == "pass") | .Test] as $tests |
|
|
all(.[]; .Action != "skip" and .Action != "fail") and
|
|
(["reasonix/internal/contract/provider", "reasonix/internal/model/boundedllm",
|
|
"reasonix/internal/runtime/agent", "reasonix/internal/assembly/boot"] - $packages | length) == 0 and
|
|
(["TestAuxiliaryUsageObserverReplacesAndCopies",
|
|
"TestBoundedUsageObserverOwnsOneTerminal", "TestBoundedUsageObserverOwnsOneTerminal/reported",
|
|
"TestBoundedUsageObserverOwnsOneTerminal/billed_failure", "TestBoundedUsageObserverOwnsOneTerminal/without_sink",
|
|
"TestBoundedUsageObserverOwnsOneTerminal/missing", "TestBoundedUsageObserverOwnsOneTerminal/input_refused",
|
|
"TestRootBoundedReviewerBudget", "TestRootBoundedReviewerBudget/reported",
|
|
"TestRootBoundedReviewerBudget/billed_failure", "TestRootBoundedReviewerBudget/missing_usage",
|
|
"TestRootBoundedReviewerBudget/disabled", "TestRootBoundedReviewerBudget/no_emission",
|
|
"TestRootBoundedReviewerBudget/projected_job_context", "TestRootBoundedNestedBudgetChargesOnce",
|
|
"TestRootBoundedLateProjectionStaysWithOldTask", "TestEffectRootBoundedAdvisorBudget",
|
|
"TestEffectRootBoundedAdvisorBudget/reported", "TestEffectRootBoundedAdvisorBudget/disabled",
|
|
"TestEffectRootBoundedAdvisorBudget/missing_usage"] - $tests | length) == 0
|
|
' "$RUNNER_TEMP/bounded-root-budget.jsonl"
|
|
|
|
- name: upload Windows bounded root budget inventory
|
|
if: always() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: bounded-root-budget-windows-${{ github.run_attempt }}
|
|
path: ${{ runner.temp }}/bounded-root-budget.jsonl
|
|
if-no-files-found: ignore
|
|
retention-days: 7
|
|
|
|
# The general Windows PR smoke list intentionally omits internal/contract/tool.
|
|
# Keep the session-temp portability contract covered without widening the
|
|
# leg to every tool test: two real PowerShell launches must share the
|
|
# injected TMPDIR/TMP/TEMP directory.
|
|
- name: test (Windows session temp)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 3
|
|
run: go test -count=1 -timeout=2m -run '^TestBashSharesSessionTempAcrossCalls$' ./internal/tools/builtin
|
|
|
|
# Shell execution contract: PowerShell identity, Chinese workspace paths,
|
|
# UTF-8 output, and ExitCode retention must gate PRs on native Windows.
|
|
# Keep this focused (not full ./internal/contract/tool) so the smoke budget holds.
|
|
- name: test (Windows shell execution contract)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name == 'pull_request'
|
|
timeout-minutes: 5
|
|
run: go test -count=1 -timeout=3m -run '^TestBashPowerShellExecuteDetailedContract$|^TestBashPowerShell51PreflightRejectsAndAndDetailed$|^TestBashPowerShellOutputIsUTF8$|^TestBashPowerShellSurfacesNonZeroExit$|^TestBashPowerShellRejectsChaining$' ./internal/tools/builtin
|
|
|
|
# Full push suite uses the same 18m package timeout as Windows smoke and a
|
|
# 35m step budget above it. -count=1 as at the smoke step. A failure prints
|
|
# the failed tests' output and the 15 slowest boot tests.
|
|
- name: test (full)
|
|
if: env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name != 'pull_request'
|
|
timeout-minutes: 35
|
|
env:
|
|
# Run the prompt-cache prefix-stability guard (TestCacheHit*) in CI: a
|
|
# regression there silently tanks the cache hit rate the project is
|
|
# built around.
|
|
REASONIX_RELEASE_CACHE_GUARD: "1"
|
|
# Bound sandbox helper children in Windows tests so a failed OS-level
|
|
# launch cannot pin the Actions step after Go's package timeout fires.
|
|
WINDOWS_SANDBOX_WAIT_MS: "20000"
|
|
shell: bash
|
|
run: |
|
|
# internal/assembly/boot alone takes 14-15 minutes on a Windows runner;
|
|
# the package limit leaves headroom inside the step limit above.
|
|
go test -count=1 -p 4 -timeout=28m -json ./... | tee "$RUNNER_TEMP/full.jsonl" |
|
|
jq -rj --unbuffered 'select(.Action == "output" and .Test == null) | .Output'
|
|
|
|
- name: test (full) failure detail
|
|
if: failure() && env.RUN_STEPS == 'true' && runner.os == 'Windows' && github.event_name != 'pull_request'
|
|
shell: bash
|
|
run: |
|
|
f="$RUNNER_TEMP/full.jsonl"
|
|
[ -s "$f" ] || exit 0
|
|
echo "::group::output of failed tests"
|
|
jq -rn '[inputs | select(.Test != null)] | group_by(.Package + "/" + .Test)
|
|
| map(select(any(.[]; .Action == "fail")))[]
|
|
| map(select(.Action == "output") | .Output) | join("")' "$f" || true
|
|
echo "::endgroup::"
|
|
echo "slowest internal/assembly/boot tests (seconds, name):"
|
|
jq -rn '[inputs | select((.Package | endswith("/internal/assembly/boot")) and .Test != null and .Action == "pass")]
|
|
| sort_by(-.Elapsed)[:15][] | "\(.Elapsed)\t\(.Test)"' "$f" || true
|
|
|
|
race:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || needs.changes.outputs.code != 'false')
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
|
|
- name: Install and verify Linux sandbox backend
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y bubblewrap
|
|
if sysctl -n kernel.unprivileged_userns_clone >/dev/null 2>&1; then
|
|
sudo sysctl -w kernel.unprivileged_userns_clone=1
|
|
fi
|
|
if sysctl -n kernel.apparmor_restrict_unprivileged_userns >/dev/null 2>&1; then
|
|
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
|
fi
|
|
bwrap --ro-bind / / --dev /dev --proc /proc -- true || \
|
|
echo "::warning::bubblewrap is installed but this runner denies user namespaces; unavailable-backend tests will run fail-closed"
|
|
|
|
# The matrix never runs -race (it needs cgo); the project's concurrency
|
|
# (plugin fan-out, background phase B, jobs Kill/Wait) would otherwise
|
|
# ship without race coverage. Pull requests sweep only the
|
|
# concurrency-heavy packages so this required check stays fast; pushes
|
|
# to main-v2 keep the full ./... sweep as the safety net.
|
|
- name: test -race (concurrency packages)
|
|
if: github.event_name == 'pull_request'
|
|
env:
|
|
REASONIX_RELEASE_CACHE_GUARD: "1"
|
|
run: go test -race ./internal/runtime/agent/... ./internal/runtime/delegation/... ./internal/runtime/isolation/... ./internal/platform/worktree/... ./internal/state/mutation/... ./internal/ext/plugin/... ./internal/tools/jobs/... ./internal/base/proc/... ./internal/safety/sandbox/... ./internal/base/filelock/... ./internal/contract/eventwire/... ./internal/platform/remote/... ./internal/ext/extension/... ./internal/assembly/boot/... ./internal/session/control/... ./internal/contract/tool/...
|
|
|
|
- name: test -race (full)
|
|
if: github.event_name != 'pull_request'
|
|
env:
|
|
REASONIX_RELEASE_CACHE_GUARD: "1"
|
|
# internal/assembly/boot under -race runs past ten minutes on a shared
|
|
# runner; the package limit leaves headroom over the default.
|
|
run: go test -race -timeout=25m ./...
|
|
|
|
# sdk/go is a nested stdlib-only module invisible to root `go test ./...`.
|
|
# Its DTOs are generated from internal/ext/extension/protocol, and the
|
|
# host-side conformance tests spawn the SDK example, so the job runs the
|
|
# same three-OS matrix as the root tests.
|
|
sdk:
|
|
needs: changes
|
|
if: always()
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
runs-on: ${{ github.event_name == 'pull_request' && needs.changes.outputs.platform == 'false' && 'ubuntu-latest' || matrix.os }}
|
|
env:
|
|
RUN_STEPS: ${{ github.event_name != 'pull_request' || (needs.changes.outputs.sdk != 'false' && (matrix.os == 'ubuntu-latest' || needs.changes.outputs.platform != 'false')) }}
|
|
defaults:
|
|
run:
|
|
working-directory: sdk/go
|
|
steps:
|
|
- if: env.RUN_STEPS == 'true'
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- if: env.RUN_STEPS == 'true'
|
|
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
|
with:
|
|
go-version-file: sdk/go/go.mod
|
|
|
|
- name: gofmt
|
|
if: env.RUN_STEPS == 'true'
|
|
shell: bash
|
|
run: |
|
|
unformatted=$(gofmt -l .)
|
|
if [ -n "$unformatted" ]; then
|
|
echo "These files are not gofmt-clean:"
|
|
echo "$unformatted"
|
|
exit 1
|
|
fi
|
|
|
|
- name: vet
|
|
if: env.RUN_STEPS == 'true'
|
|
run: go vet ./...
|
|
|
|
- name: stdlib-only guard
|
|
if: env.RUN_STEPS == 'true'
|
|
shell: bash
|
|
run: |
|
|
# The SDK is a public module with a hard stdlib-only contract.
|
|
if go list -m all | grep -v '^github.com/esengine/DeepSeek-Reasonix/sdk/go$'; then
|
|
echo "sdk/go must not depend on anything outside the standard library"
|
|
exit 1
|
|
fi
|
|
|
|
- name: test
|
|
if: env.RUN_STEPS == 'true'
|
|
run: go test ./...
|
|
|
|
- name: test -race
|
|
if: github.event_name != 'pull_request' && env.RUN_STEPS == 'true'
|
|
run: go test -race ./...
|
|
|
|
desktop:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || needs.changes.outputs.desktop != 'false')
|
|
runs-on: ubuntu-22.04
|
|
defaults:
|
|
run:
|
|
working-directory: desktop
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: desktop/go.mod
|
|
cache: true
|
|
cache-dependency-path: desktop/go.sum
|
|
|
|
- name: gofmt
|
|
run: |
|
|
unformatted=$(gofmt -l .)
|
|
if [ -n "$unformatted" ]; then
|
|
echo "These files are not gofmt-clean:"
|
|
echo "$unformatted"
|
|
exit 1
|
|
fi
|
|
|
|
- name: go.mod tidy
|
|
run: |
|
|
go mod tidy
|
|
if ! git diff --quiet -- go.mod go.sum; then
|
|
echo "desktop/go.mod or go.sum is stale - run 'cd desktop && go mod tidy' and commit."
|
|
git diff -- go.mod go.sum
|
|
exit 1
|
|
fi
|
|
|
|
- name: vet
|
|
run: go vet ./...
|
|
|
|
- name: golangci-lint
|
|
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
|
|
with:
|
|
version: v2.12.2
|
|
working-directory: desktop
|
|
args: --timeout=5m
|
|
|
|
- name: build
|
|
run: go build ./...
|
|
|
|
- name: test
|
|
run: go test ./...
|
|
|
|
# The update helper replaces a running application under pkexec, so its
|
|
# own concurrency is CI-blocked rather than author-verified locally.
|
|
- name: test -race
|
|
run: go test -race ./...
|
|
|
|
# desktop/ is a separate module, so the root macOS matrix above does not
|
|
# compile it against a real macOS toolchain.
|
|
desktop-macos:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || (needs.changes.outputs.desktop != 'false' && needs.changes.outputs.platform != 'false'))
|
|
runs-on: macos-latest
|
|
defaults:
|
|
run:
|
|
working-directory: desktop
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: desktop/go.mod
|
|
cache: true
|
|
cache-dependency-path: desktop/go.sum
|
|
|
|
- name: test
|
|
run: go test -race ./...
|
|
|
|
- name: golangci-lint
|
|
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
|
|
with:
|
|
version: v2.12.2
|
|
working-directory: desktop
|
|
args: --timeout=5m
|
|
|
|
# The update helper's versioned-install and uninstall paths are Windows-only
|
|
# (//go:build windows), so the ubuntu leg above never compiles them.
|
|
desktop-windows:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || (needs.changes.outputs.desktop != 'false' && needs.changes.outputs.platform != 'false'))
|
|
runs-on: windows-latest
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
working-directory: desktop
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: desktop/go.mod
|
|
cache: true
|
|
cache-dependency-path: desktop/go.sum
|
|
|
|
- name: test (update helper and uninstaller)
|
|
timeout-minutes: 15
|
|
run: go test ./...
|
|
|
|
# repolint scans desktop/ and sdk/ too, so this job also runs for diffs the
|
|
# `code` filter would otherwise skip.
|
|
lint:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || needs.changes.outputs.code != 'false' || needs.changes.outputs.desktop != 'false' || needs.changes.outputs.sdk != 'false')
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
|
|
- name: repo standards
|
|
run: go run ./tools/repolint
|
|
|
|
# The paths the project declared sensitive, held to the coverage they
|
|
# already have. It runs only those packages' tests, not the full suite.
|
|
- name: sensitive-path coverage
|
|
run: go run ./tools/covergate
|
|
|
|
# `make lint-install` reads the same file, so a local run and this job
|
|
# cannot drift onto different linter versions.
|
|
- id: golangci
|
|
run: echo "version=$(cat .golangci-version)" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: golangci-lint
|
|
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
|
|
with:
|
|
version: ${{ steps.golangci.outputs.version }}
|
|
args: --timeout=5m
|
|
|
|
# The step above only type-checks the linux/amd64 build, so every
|
|
# //go:build windows and //go:build darwin file in the tree went unlinted.
|
|
# Both modules cross-check without a toolchain; desktop under darwin does
|
|
# not, because its watchdog is cgo, so that leg lives in desktop-macos.
|
|
- name: golangci-lint (cross-platform build tags)
|
|
run: |
|
|
set -euo pipefail
|
|
command -v golangci-lint
|
|
for target in "darwin ." "windows ." "windows desktop"; do
|
|
read -r target_os target_dir <<< "$target"
|
|
echo "::group::golangci-lint GOOS=$target_os ($target_dir)"
|
|
(cd "$target_dir" && GOOS="$target_os" golangci-lint run --timeout=5m ./...)
|
|
echo "::endgroup::"
|
|
done
|
|
|
|
- name: release workflow contracts
|
|
run: |
|
|
go run github.com/rhysd/actionlint/cmd/[email protected] \
|
|
-ignore 'label "windows-11-arm" is unknown' \
|
|
-ignore 'label "ubuntu-22.04-arm" is unknown' \
|
|
.github/workflows/release-studio.yml \
|
|
.github/workflows/studio-certum-signing-smoke.yml \
|
|
.github/workflows/ci.yml
|
|
|
|
govulncheck:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || needs.changes.outputs.code != 'false')
|
|
runs-on: ubuntu-latest
|
|
continue-on-error: true # informational — stdlib vulns need a Go patch release
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
|
|
- name: install govulncheck
|
|
run: go install golang.org/x/vuln/cmd/govulncheck@latest
|
|
|
|
- name: govulncheck
|
|
run: govulncheck ./...
|
|
|
|
coverage:
|
|
needs: changes
|
|
if: always() && (github.event_name != 'pull_request' || needs.changes.outputs.code != 'false')
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
|
|
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
|
|
with:
|
|
go-version-file: go.mod
|
|
cache: true
|
|
|
|
- name: test with coverage
|
|
run: go test -coverprofile=coverage.out -covermode=atomic ./...
|
|
|
|
- name: upload coverage
|
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
|
|
with:
|
|
name: coverage-report
|
|
path: coverage.out
|
|
retention-days: 7
|