Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codex/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[features]
collaboration_modes = true
collaboration_modes = true
42 changes: 9 additions & 33 deletions .fallowrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,12 @@
"scripts/write-xcuitest-cache-metadata.mjs",
"scripts/help-conformance-sample-outputs.d.mts"
],
"ignoreDependencies": [
"@theme"
],
"ignoreDependencies": ["@theme"],
"ignoreExports": [
{
"comment": "Authoritative supported-command list; sole consumer is the conformance oracle (scripts/maestro-conformance, an ignored tooling tree).",
"file": "src/compat/maestro/program-ir-command-parser.ts",
"exports": [
"SUPPORTED_MAESTRO_COMMAND_NAMES"
]
"exports": ["SUPPORTED_MAESTRO_COMMAND_NAMES"]
},
{
"comment": "Daemon route handlers are reached only through the dynamic `import()` table in request-handler-chain.ts, which --production analysis cannot follow to a consumer.",
Expand All @@ -60,16 +56,12 @@
{
"comment": "Published package surface (see package.json#exports); consumed by SDK users, not internally.",
"file": "src/sdk/*.ts",
"exports": [
"*"
]
"exports": ["*"]
},
{
"comment": "Tool config default exports, loaded by the tool rather than imported.",
"file": "{tsdown.config.ts,vitest.mutation.config.ts,website/rspress.config.ts,test/skillgym/skillgym.config.ts,test/skillgym/suites/*.ts}",
"exports": [
"default"
]
"exports": ["default"]
},
{
"comment": "Type-level `AssertTrue<...>` registry-totality guards. Exported only so `noUnusedLocals` keeps them alive; a consumer would defeat the point.",
Expand All @@ -84,44 +76,28 @@
{
"comment": "Mutation-lane seam: readTestScope is consumed by vitest.mutation.config.ts, a tool config outside --production analysis.",
"file": "scripts/mutation/test-scope.ts",
"exports": [
"readTestScope"
]
"exports": ["readTestScope"]
},
{
"comment": "Mutation-lane completeness gate: ownedTestFiles enumerates the whole derived ownership map, which only the assertion in ownership.test.ts consumes — a production consumer would defeat the point.",
"file": "scripts/mutation/ownership.ts",
"exports": [
"ownedTestFiles"
]
"exports": ["ownedTestFiles"]
},
{
"comment": "Help-benchmark conformance seams: helpTopicIds feeds the topic-coverage gate and PRIVATE_AX_RECOVERY_SAMPLE feeds the skillgym suite; both consumers are test-tree files outside --production analysis.",
"file": "{src/cli/parser/cli-help.ts,scripts/help-conformance-sample-outputs.mjs}",
"exports": [
"helpTopicIds",
"PRIVATE_AX_RECOVERY_SAMPLE"
]
"exports": ["helpTopicIds", "PRIVATE_AX_RECOVERY_SAMPLE"]
}
],
"usedClassMembers": [
"name",
"listActiveLeases",
"delete",
"values",
"elapsedMs",
"isExpired"
],
"usedClassMembers": ["name", "listActiveLeases", "delete", "values", "elapsedMs", "isExpired"],
"rules": {
"unused-types": "error",
"duplicate-exports": "off"
},
"production": {
"dupes": true
},
"publicPackages": [
"agent-device"
],
"publicPackages": ["agent-device"],
"audit": {
"deadCodeBaseline": "fallow-baselines/dead-code.json",
"healthBaseline": "fallow-baselines/health.json"
Expand Down
18 changes: 9 additions & 9 deletions .github/actions/boot-ios-test-simulator/action.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
name: "Boot iOS Test Simulator"
description: "Resolve and boot the preferred iOS simulator for replay tests"
name: 'Boot iOS Test Simulator'
description: 'Resolve and boot the preferred iOS simulator for replay tests'

inputs:
runtime-version:
description: "Preferred iOS runtime version"
description: 'Preferred iOS runtime version'
required: true
preferred-device-name:
description: "Preferred simulator device name"
description: 'Preferred simulator device name'
required: false
default: "iPhone 17 Pro"
default: 'iPhone 17 Pro'
boot-timeout-seconds:
description: "Maximum time to wait for simulator bootstatus"
description: 'Maximum time to wait for simulator bootstatus'
required: false
default: "300"
default: '300'

outputs:
simulator-udid:
description: "UDID of the booted iOS simulator"
description: 'UDID of the booted iOS simulator'
value: ${{ steps.boot.outputs.simulator-udid }}

runs:
using: "composite"
using: 'composite'
steps:
- name: Resolve and boot iOS test simulator
id: boot
Expand Down
8 changes: 4 additions & 4 deletions .github/actions/setup-android-replay-host/action.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name: "Setup Android Replay Host"
description: "Prepare the Android CI host for replay tests and expose the agent-device home path"
name: 'Setup Android Replay Host'
description: 'Prepare the Android CI host for replay tests and expose the agent-device home path'

outputs:
agent-home-dir:
description: "Resolved agent-device home directory"
description: 'Resolved agent-device home directory'
value: ${{ steps.agent-home.outputs.dir }}

runs:
using: "composite"
using: 'composite'
steps:
- name: Resolve agent-device home
id: agent-home
Expand Down
32 changes: 16 additions & 16 deletions .github/actions/setup-apple-replay/action.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
name: "Setup Apple Replay"
description: "Resolve shared Apple replay cache/build state and expose the agent-device home path"
name: 'Setup Apple Replay'
description: 'Resolve shared Apple replay cache/build state and expose the agent-device home path'

inputs:
derived-path:
description: "Derived data path used by the replay runner"
description: 'Derived data path used by the replay runner'
required: true
cache-key-prefix:
description: "Prefix for the cache key"
description: 'Prefix for the cache key'
required: true
cache-key-suffix:
description: "Optional suffix for the cache key"
description: 'Optional suffix for the cache key'
required: false
default: ""
default: ''
build-command:
description: "Command used to refresh replay artifacts before use"
description: 'Command used to refresh replay artifacts before use'
required: true
xcuitest-platform:
description: "Optional AGENT_DEVICE_XCUITEST_PLATFORM value"
description: 'Optional AGENT_DEVICE_XCUITEST_PLATFORM value'
required: false
default: ""
default: ''
xcuitest-destination:
description: "Optional AGENT_DEVICE_XCUITEST_DESTINATION value"
description: 'Optional AGENT_DEVICE_XCUITEST_DESTINATION value'
required: false
default: ""
default: ''
build-before-use:
description: "Whether this setup action should refresh replay artifacts after restoring the cache"
description: 'Whether this setup action should refresh replay artifacts after restoring the cache'
required: false
default: "true"
default: 'true'

outputs:
agent-home-dir:
description: "Resolved agent-device home directory"
description: 'Resolved agent-device home directory'
value: ${{ steps.agent-home.outputs.dir }}
cache-hit:
description: "Whether a replay cache was restored before any build refresh"
description: 'Whether a replay cache was restored before any build refresh'
value: ${{ steps.restore-prebuilt.outputs.cache-hit }}

runs:
using: "composite"
using: 'composite'
steps:
- name: Resolve Xcode cache key
id: xcode
Expand Down
16 changes: 8 additions & 8 deletions .github/actions/setup-fixture-app/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: "Setup Fixture App"
description: "Install a ready Release build of examples/test-app on the booted iOS simulator, from the shared build cache"
name: 'Setup Fixture App'
description: 'Install a ready Release build of examples/test-app on the booted iOS simulator, from the shared build cache'

# Any job that needs a controlled app to drive can use this instead of an Apple
# system app. It fetches the Release binary that test-app-build-cache.yml
Expand All @@ -18,17 +18,17 @@ description: "Install a ready Release build of examples/test-app on the booted i

inputs:
device-name:
description: "Simulator device name used for the inline-build fallback"
description: 'Simulator device name used for the inline-build fallback'
required: false
default: "iPhone 17 Pro"
default: 'iPhone 17 Pro'
install:
description: "Install the app onto the booted simulator"
description: 'Install the app onto the booted simulator'
required: false
default: "true"
default: 'true'

outputs:
app-path:
description: "Path to the ready .app bundle"
description: 'Path to the ready .app bundle'
value: ${{ steps.locate.outputs.app-path }}
app-id:
description: "Bundle identifier read from the app's Info.plist"
Expand All @@ -38,7 +38,7 @@ outputs:
value: ${{ steps.fetch.outputs.source }}

runs:
using: "composite"
using: 'composite'
steps:
# Installed even on a hit, because the fingerprint is derived from the
# dependency graph and cannot be computed without it.
Expand Down
39 changes: 34 additions & 5 deletions .github/actions/setup-node-pnpm/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ inputs:
description: 'Node.js version'
required: false
default: '24.13'
pnpm-version:
description: 'pnpm version'
required: false
default: '11.1.2'
install-deps:
description: 'Whether to install dependencies with pnpm install --frozen-lockfile'
required: false
Expand All @@ -18,10 +14,28 @@ inputs:
runs:
using: 'composite'
steps:
# package.json `packageManager` is the single source of truth for the pnpm
# version. This action carries no default of its own: a second default is
# how local (corepack) and CI pnpm versions drift apart silently.
- name: Resolve pnpm version from packageManager
id: package-manager
run: |
set -euo pipefail
spec="$(node -p "require('$GITHUB_WORKSPACE/package.json').packageManager ?? ''")"
case "$spec" in
pnpm@[0-9]*) ;;
*)
echo "package.json packageManager must be pnpm@<version>, got '${spec}'" >&2
exit 1
;;
esac
echo "pnpm-version=${spec#pnpm@}" >> "$GITHUB_OUTPUT"
shell: bash

- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
with:
version: ${{ inputs.pnpm-version }}
version: ${{ steps.package-manager.outputs.pnpm-version }}

- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
Expand All @@ -32,6 +46,21 @@ runs:
# miss (any lockfile-changing PR) the post-job cache save fails the job.
cache: ${{ inputs.install-deps == 'true' && 'pnpm' || '' }}

# Corepack resolves the same `packageManager` field locally, so a mismatch
# here means CI is running a pnpm nobody develops against.
- name: Assert pnpm matches packageManager
env:
EXPECTED_PNPM_VERSION: ${{ steps.package-manager.outputs.pnpm-version }}
run: |
set -euo pipefail
actual="$(pnpm --version)"
if [ "$actual" != "$EXPECTED_PNPM_VERSION" ]; then
echo "pnpm ${actual} is installed but package.json pins pnpm@${EXPECTED_PNPM_VERSION}" >&2
exit 1
fi
echo "pnpm ${actual} matches package.json packageManager"
shell: bash

- name: Install dependencies
if: ${{ inputs.install-deps == 'true' }}
run: pnpm install --frozen-lockfile
Expand Down
14 changes: 7 additions & 7 deletions .github/actions/upload-agent-device-artifacts/action.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
name: "Upload Agent Device Artifacts"
description: "Upload shared agent-device diagnostics, session logs, and replay artifacts"
name: 'Upload Agent Device Artifacts'
description: 'Upload shared agent-device diagnostics, session logs, and replay artifacts'

inputs:
artifact-name:
description: "Artifact name"
description: 'Artifact name'
required: true
agent-home-dir:
description: "Resolved agent-device daemon state directory"
description: 'Resolved agent-device daemon state directory'
required: true
runner-derived-path:
description: "Optional Apple runner derived data path to upload cache metadata and Xcode logs"
description: 'Optional Apple runner derived data path to upload cache metadata and Xcode logs'
required: false
default: ".agent-device-no-runner-derived"
default: '.agent-device-no-runner-derived'

runs:
using: "composite"
using: 'composite'
steps:
- name: Upload artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
Expand Down
Loading
Loading