chore: cleanup before bazel-contrib handoff (#918)

* chore: clenaup before bazel-contrib handoff

* chore: apply lint fixes

---------

Co-authored-by: Alex Eagle <alex@aspect.dev>
diff --git a/.aspect/cli/config.yaml b/.aspect/cli/config.yaml
index 3831545..b4f8a0a 100644
--- a/.aspect/cli/config.yaml
+++ b/.aspect/cli/config.yaml
@@ -1,6 +1,4 @@
-configure:
-  languages:
-    javascript: false
-    go: false
-    kotlin: false
-    protobuf: true
+lint:
+  aspects:
+    - //tools/lint:linters.bzl%vale
+    - //tools/lint:linters.bzl%shellcheck
diff --git a/.aspect/workflows/BUILD.bazel b/.aspect/workflows/BUILD.bazel
deleted file mode 100644
index 61fa702..0000000
--- a/.aspect/workflows/BUILD.bazel
+++ /dev/null
@@ -1,13 +0,0 @@
-load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
-
-exports_files(["config.yaml"])
-
-bzl_library(
-    name = "deps",
-    srcs = ["deps.bzl"],
-    visibility = ["//visibility:public"],
-    deps = [
-        "@bazel_tools//tools/build_defs/repo:http.bzl",
-        "@bazel_tools//tools/build_defs/repo:utils.bzl",
-    ],
-)
diff --git a/.aspect/workflows/README.md b/.aspect/workflows/README.md
deleted file mode 100644
index 5660db5..0000000
--- a/.aspect/workflows/README.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Aspect Workflows demonstration deployment
-
-This deployment of [Aspect Workflows](https://www.aspect.build/workflows) is configured to run on GCP + CircleCI.
-
-You can see this Aspect Workflows demonstration deployment live at https://app.circleci.com/pipelines/github/aspect-build/bazel-lib.
-
-The two components of the configuration in this repository are,
-
-1. Aspect Workflows configuration yaml
-1. CircleCI pipeline configuration
-
-## Aspect Workflows configuration yaml
-
-This is the [config.yaml](./config.yaml) file in this directory.
-
-## CircleCI pipeline configuration
-
-This is the [.circleci/config.yml](../../.circleci/config.yml) file.
diff --git a/.aspect/workflows/bazelrc b/.aspect/workflows/bazelrc
deleted file mode 100644
index 2fb1561..0000000
--- a/.aspect/workflows/bazelrc
+++ /dev/null
@@ -1,10 +0,0 @@
-# build without the bytes
-common --remote_download_outputs=minimal
-common --nobuild_runfile_links
-
-common:aspect_rbe --extra_execution_platforms=@aspect_bazel_lib//platforms:x86_64_linux_remote
-common:aspect_rbe --host_platform=@aspect_bazel_lib//platforms:x86_64_linux_remote
-common:aspect_rbe --remote_executor=unix:///mnt/ephemeral/buildbarn/.cache/bb_clientd/grpc
-common:aspect_rbe --genrule_strategy=remote,local
-common:aspect_rbe --jobs=32
-common:aspect_rbe --remote_timeout=3600
diff --git a/.aspect/workflows/config.yaml b/.aspect/workflows/config.yaml
deleted file mode 100644
index ec5e3b2..0000000
--- a/.aspect/workflows/config.yaml
+++ /dev/null
@@ -1,125 +0,0 @@
-queue: bazel-lib-default
-bazel:
-  flags:
-    - --config=aspect_rbe
-workspaces:
-  .:
-    tasks:
-      - test:
-          targets:
-            - //...
-            - -//lib/tests/coreutils:ls_test # Broken on workflows CI & RBE
-            - -//lib/tests/tar:test_dirs # Broken on workflows CI & RBE
-      - configure:
-          bazel:
-            flags: [] # TODO: Aspect CLI does not support --config for configure cmd
-  e2e/copy_action:
-    icon: bazel
-    tasks:
-      - test:
-          queue: bazel-lib-small
-      - format:
-          without: true
-      - gazelle:
-          without: true
-      - configure:
-          without: true
-      - buildifier:
-          without: true
-      - delivery:
-          without: true
-  e2e/copy_to_directory:
-    icon: bazel
-    tasks:
-      - test:
-          queue: bazel-lib-small
-      - format:
-          without: true
-      - gazelle:
-          without: true
-      - configure:
-          without: true
-      - buildifier:
-          without: true
-      - delivery:
-          without: true
-  e2e/coreutils:
-    icon: bazel
-    tasks:
-      - test:
-          queue: bazel-lib-small
-      - format:
-          without: true
-      - gazelle:
-          without: true
-      - configure:
-          without: true
-      - buildifier:
-          without: true
-      - delivery:
-          without: true
-  e2e/external_copy_to_directory:
-    icon: bazel
-    tasks:
-      - test:
-          queue: bazel-lib-small
-      - format:
-          without: true
-      - gazelle:
-          without: true
-      - configure:
-          without: true
-      - buildifier:
-          without: true
-      - delivery:
-          without: true
-  e2e/smoke:
-    icon: bazel
-    tasks:
-      - test:
-          queue: bazel-lib-small
-      - format:
-          without: true
-      - gazelle:
-          without: true
-      - configure:
-          without: true
-      - buildifier:
-          without: true
-      - delivery:
-          without: true
-tasks:
-  - test:
-      hooks:
-        - type: before_task
-          command: vmstat -a -S M -t 1 2>&1 > vmstat.out &
-        - type: after_task
-          command: cat vmstat.out
-      artifact_paths:
-        - vmstat.out
-  - format:
-      queue: bazel-lib-small
-  - gazelle:
-      queue: bazel-lib-small
-  - configure:
-      queue: bazel-lib-small
-  - buildifier:
-      queue: bazel-lib-small
-  - delivery:
-      queue: bazel-lib-default
-      auto_deliver: true
-      rules:
-        - deliverable: 'attr("tags", "\bdeliverable\b", //...)'
-          condition:
-            branches:
-              - main
-        - deliverable:
-            - //tools/release:tools_delivery
-          condition:
-            only_on_change: false
-            branches:
-              - main
-  - warming:
-      queue: bazel-lib-warming
-notifications:
-  github: {}
diff --git a/.aspect/workflows/deps.bzl b/.aspect/workflows/deps.bzl
deleted file mode 100644
index 962c964..0000000
--- a/.aspect/workflows/deps.bzl
+++ /dev/null
@@ -1,48 +0,0 @@
-"""Bazel dependencies for Aspect Workflows"""
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", _http_archive = "http_archive", _http_file = "http_file")
-load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
-
-# TODO: move this to a rule set so repositories on Aspect Workflows can avoid this boilerplate
-rosetta_version = "5.10.12"
-rosetta_integrity = {
-    "darwin_aarch64": "sha256-AmrO0e44haDvaVCosuNCPONPTLflSWyHMmSVv7V6iO8=",
-    "darwin_x86_64": "sha256-9g21wDZPBKqP0Z/KCmULJhwH4SqsKqOS1ceRVg3TWYs=",
-    "linux_aarch64": "sha256-KncnXJfAstOI5savV+pCF8/AuPlJs1DG8xTwXstPmuM=",
-    "linux_x86_64": "sha256-1oyhGKI0yzL1Y/5IjFmWShl27Bs4TqFZNipVL2xb9wU=",
-}
-
-# https://github.com/suzuki-shunsuke/circleci-config-merge/releases
-# https://dev.to/suzukishunsuke/splitting-circleci-config-yml-10gk
-circleci_config_merge_version = "1.1.6"
-circleci_config_merge_integrity = {
-    "darwin_aarch64": "sha256-7cQeLrSVRZR+mQu/njn+x//EIb2bhTV2+J8fafRHpr4=",
-    "darwin_x86_64": "sha256-vHKDSdDaYK58MaudJ9yOPRKh+OT/LiTQV/9E07RL8qA=",
-    "linux_aarch64": "sha256-MaXVQmRK9q9LgsfM5ZzxCIIT8rUcOBbzJ8aVDgK6zWs=",
-    "linux_x86_64": "sha256-3eYJn7dShZD1oiS3cgXfqXwdDzclf/N97A2nh7ZfW+w=",
-}
-
-def http_archive(name, **kwargs):
-    maybe(_http_archive, name = name, **kwargs)
-
-def http_file(name, **kwargs):
-    maybe(_http_file, name = name, **kwargs)
-
-# buildifier: disable=function-docstring
-def fetch_workflows_deps():
-    for platform_arch in rosetta_integrity.keys():
-        http_file(
-            name = "rosetta_{}".format(platform_arch),
-            downloaded_file_path = "rosetta",
-            executable = True,
-            integrity = rosetta_integrity[platform_arch],
-            urls = ["https://static.aspect.build/aspect/{0}/rosetta_real_{1}".format(rosetta_version, platform_arch.replace("aarch64", "arm64"))],
-        )
-
-    for platform_arch in circleci_config_merge_integrity.keys():
-        http_archive(
-            name = "circleci_config_merge_{}".format(platform_arch),
-            build_file_content = "exports_files([\"circleci-config-merge\"])",
-            integrity = circleci_config_merge_integrity[platform_arch],
-            urls = ["https://github.com/suzuki-shunsuke/circleci-config-merge/releases/download/v{0}/circleci-config-merge_{0}_{1}.tar.gz".format(circleci_config_merge_version, platform_arch.replace("aarch64", "arm64").replace("x86_64", "amd64"))],
-        )
diff --git a/.bazeliskrc b/.bazeliskrc
index 269fbb0..3e55de4 100644
--- a/.bazeliskrc
+++ b/.bazeliskrc
@@ -1,2 +1,2 @@
-BAZELISK_BASE_URL=https://github.com/aspect-build/aspect-cli/releases/download
-USE_BAZEL_VERSION=aspect/5.9.25
+BAZELISK_BASE_URL=https://static.aspect.build/aspect
+USE_BAZEL_VERSION=aspect/2024.34.43
diff --git a/.circleci/BUILD.bazel b/.circleci/BUILD.bazel
deleted file mode 100644
index 6dfea2a..0000000
--- a/.circleci/BUILD.bazel
+++ /dev/null
@@ -1,61 +0,0 @@
-load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_file")
-
-CIRCLECI_ORG = "aspect-build"
-
-CIRCLECI_USER_CONFIG_FILE = "//.circleci:user-config.yml"
-
-not_windows = select({
-    # There isn't a published rosetta binary for windows as of Feb 2024
-    "@platforms//os:windows": ["@platforms//:incompatible"],
-    "//conditions:default": [],
-})
-
-alias(
-    name = "rosetta",
-    actual = select({
-        "@bazel_tools//src/conditions:darwin_arm64": "@rosetta_darwin_aarch64//file:rosetta",
-        "@bazel_tools//src/conditions:darwin_x86_64": "@rosetta_darwin_x86_64//file:rosetta",
-        "@bazel_tools//src/conditions:linux_aarch64": "@rosetta_linux_aarch64//file:rosetta",
-        "@bazel_tools//src/conditions:linux_x86_64": "@rosetta_linux_x86_64//file:rosetta",
-    }),
-    target_compatible_with = not_windows,
-)
-
-alias(
-    name = "circleci-config-merge",
-    actual = select({
-        "@bazel_tools//src/conditions:darwin_arm64": "@circleci_config_merge_darwin_aarch64//:circleci-config-merge",
-        "@bazel_tools//src/conditions:darwin_x86_64": "@circleci_config_merge_darwin_x86_64//:circleci-config-merge",
-        "@bazel_tools//src/conditions:linux_aarch64": "@circleci_config_merge_linux_aarch64//:circleci-config-merge",
-        "@bazel_tools//src/conditions:linux_x86_64": "@circleci_config_merge_linux_x86_64//:circleci-config-merge",
-    }),
-    target_compatible_with = not_windows,
-)
-
-genrule(
-    name = "aspect_workflows_config",
-    srcs = ["//.aspect/workflows:config.yaml"],
-    outs = [":aspect-workflows-config.yml"],
-    cmd = "CI=1 CIRCLE_PROJECT_USERNAME={0} $(execpath :rosetta) steps --configuration .aspect/workflows/config.yaml --host circleci > $@".format(CIRCLECI_ORG),
-    target_compatible_with = not_windows,
-    tools = [":rosetta"],
-)
-
-genrule(
-    name = "merge_config",
-    srcs = [
-        ":aspect-workflows-config.yml",
-        CIRCLECI_USER_CONFIG_FILE,
-    ],
-    outs = [":_config.yml"],
-    cmd = "echo -e '# GENERATED FILE - DO NOT EDIT!\\n# Update with: bazel run //.circleci:write_merged_config' > $@ && $(execpath :circleci-config-merge) merge $(execpath :aspect-workflows-config.yml) $(execpath {0}) >> $@".format(CIRCLECI_USER_CONFIG_FILE),
-    target_compatible_with = not_windows,
-    tools = [":circleci-config-merge"],
-)
-
-write_source_file(
-    name = "write_merged_config",
-    in_file = ":_config.yml",
-    out_file = "config.yml",
-    target_compatible_with = not_windows,
-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 3da36c9..0000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,800 +0,0 @@
-# GENERATED FILE - DO NOT EDIT!
-# Update with: bazel run //.circleci:write_merged_config
-version: 2.1
-workflows:
-  aspect-workflows:
-    jobs:
-    - aw-auto-deliver:
-        context: []
-        filters:
-          branches:
-            only:
-            - /^main$/
-        requires:
-        - aw-root_workspace_test
-        workspace: .
-    - aw-buildifier:
-        context: []
-        workspace: .
-    - aw-format:
-        context: []
-        workspace: .
-    - aw-gazelle:
-        context: []
-        workspace: .
-    - aw-root_workspace_configure:
-        context: []
-        workspace: .
-    - aw-root_workspace_test:
-        context: []
-        workspace: .
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - scheduled_pipeline
-          - << pipeline.trigger_source >>
-  aspect-workflows-e2e-copy_action:
-    jobs:
-    - aw-e2e_copy_action_test:
-        context: []
-        delivery_manifest: false
-        workspace: e2e/copy_action
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - scheduled_pipeline
-          - << pipeline.trigger_source >>
-  aspect-workflows-e2e-copy_to_directory:
-    jobs:
-    - aw-e2e_copy_to_directory_test:
-        context: []
-        delivery_manifest: false
-        workspace: e2e/copy_to_directory
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - scheduled_pipeline
-          - << pipeline.trigger_source >>
-  aspect-workflows-e2e-coreutils:
-    jobs:
-    - aw-e2e_coreutils_test:
-        context: []
-        delivery_manifest: false
-        workspace: e2e/coreutils
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - scheduled_pipeline
-          - << pipeline.trigger_source >>
-  aspect-workflows-e2e-external_copy_to_directory:
-    jobs:
-    - aw-e2e_external_copy_to_directory_test:
-        context: []
-        delivery_manifest: false
-        workspace: e2e/external_copy_to_directory
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - scheduled_pipeline
-          - << pipeline.trigger_source >>
-  aspect-workflows-e2e-smoke:
-    jobs:
-    - aw-e2e_smoke_test:
-        context: []
-        delivery_manifest: false
-        workspace: e2e/smoke
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - scheduled_pipeline
-          - << pipeline.trigger_source >>
-  aspect-workflows-manual-deliver:
-    jobs:
-    - aw-manual-deliver:
-        context: []
-        workspace: << pipeline.parameters.workspace >>
-    when:
-      equal:
-      - true
-      - << pipeline.parameters.perform_delivery >>
-  aspect-workflows-warming:
-    jobs:
-    - aw-warming: {}
-    when:
-      and:
-      - equal:
-        - scheduled_pipeline
-        - << pipeline.trigger_source >>
-      - equal:
-        - aspect-workflows-warming
-        - << pipeline.schedule.name >>
-  user-workflow:
-    jobs:
-    - user-job
-    when:
-      and:
-      - not: << pipeline.parameters.perform_delivery >>
-      - not:
-          equal:
-          - << pipeline.trigger_source >>
-          - scheduled_pipeline
-jobs:
-  aw-auto-deliver:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      DELIVERY_COMMIT: << pipeline.parameters.delivery_commit >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-default
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: git fetch
-        name: Git fetch
-    - when:
-        condition: << pipeline.parameters.delivery_commit >>
-        steps:
-        - run:
-            command: git checkout << pipeline.parameters.delivery_commit >>
-            name: Checkout release commit
-    - run:
-        command: rosetta run delivery
-        name: Delivery
-        no_output_timeout: 180m
-    working_directory: /mnt/ephemeral/workdir
-  aw-buildifier:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run buildifier --workspace << parameters.workspace >>
-        name: Buildifier
-        no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/artifacts
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-e2e_copy_action_test:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run test --workspace << parameters.workspace >>
-        name: Test
-        no_output_timeout: 180m
-    - store_test_results:
-        path: /workflows/testlogs
-    - when:
-        condition:
-          and:
-          - <<parameters.delivery_manifest>>
-          - or:
-            - matches:
-                pattern: ^main$
-                value: << pipeline.git.branch >>
-        steps:
-        - run:
-            command: rosetta run delivery_manifest --workspace << parameters.workspace
-              >> --data TARGETS_SOURCE=test
-            name: Delivery manifest
-            no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/testlogs
-    - store_artifacts:
-        path: /workflows/artifacts
-    - store_artifacts:
-        path: e2e/copy_action/vmstat.out
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-e2e_copy_to_directory_test:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run test --workspace << parameters.workspace >>
-        name: Test
-        no_output_timeout: 180m
-    - store_test_results:
-        path: /workflows/testlogs
-    - when:
-        condition:
-          and:
-          - <<parameters.delivery_manifest>>
-          - or:
-            - matches:
-                pattern: ^main$
-                value: << pipeline.git.branch >>
-        steps:
-        - run:
-            command: rosetta run delivery_manifest --workspace << parameters.workspace
-              >> --data TARGETS_SOURCE=test
-            name: Delivery manifest
-            no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/testlogs
-    - store_artifacts:
-        path: /workflows/artifacts
-    - store_artifacts:
-        path: e2e/copy_to_directory/vmstat.out
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-e2e_coreutils_test:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run test --workspace << parameters.workspace >>
-        name: Test
-        no_output_timeout: 180m
-    - store_test_results:
-        path: /workflows/testlogs
-    - when:
-        condition:
-          and:
-          - <<parameters.delivery_manifest>>
-          - or:
-            - matches:
-                pattern: ^main$
-                value: << pipeline.git.branch >>
-        steps:
-        - run:
-            command: rosetta run delivery_manifest --workspace << parameters.workspace
-              >> --data TARGETS_SOURCE=test
-            name: Delivery manifest
-            no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/testlogs
-    - store_artifacts:
-        path: /workflows/artifacts
-    - store_artifacts:
-        path: e2e/coreutils/vmstat.out
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-e2e_external_copy_to_directory_test:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run test --workspace << parameters.workspace >>
-        name: Test
-        no_output_timeout: 180m
-    - store_test_results:
-        path: /workflows/testlogs
-    - when:
-        condition:
-          and:
-          - <<parameters.delivery_manifest>>
-          - or:
-            - matches:
-                pattern: ^main$
-                value: << pipeline.git.branch >>
-        steps:
-        - run:
-            command: rosetta run delivery_manifest --workspace << parameters.workspace
-              >> --data TARGETS_SOURCE=test
-            name: Delivery manifest
-            no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/testlogs
-    - store_artifacts:
-        path: /workflows/artifacts
-    - store_artifacts:
-        path: e2e/external_copy_to_directory/vmstat.out
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-e2e_smoke_test:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run test --workspace << parameters.workspace >>
-        name: Test
-        no_output_timeout: 180m
-    - store_test_results:
-        path: /workflows/testlogs
-    - when:
-        condition:
-          and:
-          - <<parameters.delivery_manifest>>
-          - or:
-            - matches:
-                pattern: ^main$
-                value: << pipeline.git.branch >>
-        steps:
-        - run:
-            command: rosetta run delivery_manifest --workspace << parameters.workspace
-              >> --data TARGETS_SOURCE=test
-            name: Delivery manifest
-            no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/testlogs
-    - store_artifacts:
-        path: /workflows/artifacts
-    - store_artifacts:
-        path: e2e/smoke/vmstat.out
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-format:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run format --workspace << parameters.workspace >>
-        name: Format
-        no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/artifacts
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-gazelle:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run gazelle --workspace << parameters.workspace >>
-        name: Gazelle
-        no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/artifacts
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-manual-deliver:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      DELIVERY_COMMIT: << pipeline.parameters.delivery_commit >>
-      DELIVERY_TARGETS: << pipeline.parameters.delivery_targets >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-default
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: git fetch
-        name: Git fetch
-    - when:
-        condition: << pipeline.parameters.delivery_commit >>
-        steps:
-        - run:
-            command: git checkout << pipeline.parameters.delivery_commit >>
-            name: Checkout release commit
-    - run:
-        command: rosetta run delivery
-        name: Delivery
-        no_output_timeout: 180m
-    working_directory: /mnt/ephemeral/workdir
-  aw-root_workspace_configure:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-small
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run configure --workspace << parameters.workspace >>
-        name: Configure
-        no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/artifacts
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-root_workspace_test:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      ASPECT_WORKFLOWS_WORKSPACE: << parameters.workspace >>
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    parameters:
-      delivery_manifest:
-        default: true
-        type: boolean
-      workspace:
-        type: string
-    resource_class: aspect-build/bazel-lib-default
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: rm -rf /workflows/artifacts /workflows/testlogs
-        name: Prepare archive directories
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run test --workspace << parameters.workspace >>
-        name: Test
-        no_output_timeout: 180m
-    - store_test_results:
-        path: /workflows/testlogs
-    - when:
-        condition:
-          and:
-          - <<parameters.delivery_manifest>>
-          - or:
-            - matches:
-                pattern: ^main$
-                value: << pipeline.git.branch >>
-        steps:
-        - run:
-            command: rosetta run delivery_manifest --workspace << parameters.workspace
-              >> --data TARGETS_SOURCE=test
-            name: Delivery manifest
-            no_output_timeout: 180m
-    - store_artifacts:
-        path: /workflows/testlogs
-    - store_artifacts:
-        path: /workflows/artifacts
-    - store_artifacts:
-        path: vmstat.out
-    - run:
-        command: rosetta run finalization
-        name: Finalization
-        no_output_timeout: 10m
-        when: always
-    working_directory: /mnt/ephemeral/workdir
-  aw-warming:
-    environment:
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_NUMBER: << pipeline.number >>
-      ASPECT_WORKFLOWS_CIRCLE_PIPELINE_PROJECT_TYPE: << pipeline.project.type >>
-      ASPECT_WORKFLOWS_CIRCLE_WORKFLOW_BASE_NAME: aspect-workflows
-      ASPECT_WORKFLOWS_CONFIG: .aspect/workflows/config.yaml
-      XDG_CACHE_HOME: /mnt/ephemeral/caches
-    machine: true
-    resource_class: aspect-build/bazel-lib-warming
-    steps:
-    - run:
-        command: /etc/aspect/workflows/bin/configure_workflows_env
-        name: Workflows environment
-    - checkout
-    - run:
-        command: /etc/aspect/workflows/bin/agent_health_check
-        name: Agent health check
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run warming --workspace e2e/smoke
-        name: Create warming archive for e2e/smoke
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run warming --workspace e2e/external_copy_to_directory
-        name: Create warming archive for e2e/external_copy_to_directory
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run warming --workspace e2e/coreutils
-        name: Create warming archive for e2e/coreutils
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run warming --workspace e2e/copy_to_directory
-        name: Create warming archive for e2e/copy_to_directory
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run warming --workspace e2e/copy_action
-        name: Create warming archive for e2e/copy_action
-        no_output_timeout: 180m
-    - run:
-        command: rosetta run warming --workspace .
-        name: Create warming archive for root
-        no_output_timeout: 180m
-    - run:
-        command: /etc/aspect/workflows/bin/warming_archive
-        name: Archive warming tars
-    working_directory: /mnt/ephemeral/workdir
-  user-job:
-    docker:
-    - image: cimg/base:2023.03
-    steps:
-    - checkout
-    - run: echo "Example user CircleCI job that is not generated by Aspect Workflows."
-parameters:
-  delivery_commit:
-    default: ""
-    description: The commit to checkout and run the delivery from. Targets listed
-      in the delivery manifest for this commit will be delivered unless specific targets
-      are listed in `delivery_targets`.
-    type: string
-  delivery_targets:
-    default: ""
-    description: List of Bazel targets to deliver, delimited by spaces. For example,
-      `//app/a:push_release //app/b:push_release`. If empty, targets listed in the
-      delivery manifest for the target commit will be delivered.
-    type: string
-  perform_delivery:
-    default: false
-    type: boolean
-  workspace:
-    default: .
-    description: The workspace that the `delivery_targets` live within.
-    type: string
diff --git a/.circleci/user-config.yml b/.circleci/user-config.yml
deleted file mode 100644
index a11cf53..0000000
--- a/.circleci/user-config.yml
+++ /dev/null
@@ -1,52 +0,0 @@
-# This is an example of a user CircleCI configuration that is not generated by
-# Aspect Workflows. The naming of this file is arbitrary. This configuration is
-# merged with the generated Aspect Workflows CircleCI configuration into the
-# load bearing load `.circleci/config.yaml` configuration file that is used by
-# CircleCI.
-#
-# To update `.circleci/config.yaml` after editing this file run:
-#
-#    bazel run //.circleci:write_merged_config
-#
-#
-# Aspect Workflows workflow names are all prefixed with "aspect-workflows-".
-# These currently include:
-#
-# - aspect-workflows
-# - aspect-workflows-warming
-# - aspect-workflows-manual-deliver
-#
-# Aspect Workflows job names are all prefixed with "aw-". These currently
-# include.
-#
-# - aw-auto-deliver
-# - aw-buildifier
-# - aw-configure
-# - aw-format
-# - aw-gazelle
-# - aw-manual-deliver
-# - aw-test
-# - aw-warming
-#
-# In your user CircleCI configuration, avoid workflow names prefixed with
-# `aspect-workflows-` and job names prefixed with `aw-`. Conflicting workflow or
-# job names will result in a bad configuration merge.
-version: 2.1
-jobs:
-  user-job:
-    docker:
-      - image: cimg/base:2023.03
-    steps:
-      - checkout
-      - run: echo "Example user CircleCI job that is not generated by Aspect Workflows."
-workflows:
-  user-workflow:
-    jobs:
-      - user-job
-    when:
-      and:
-        - not: << pipeline.parameters.perform_delivery >>
-        - not:
-            equal:
-              - << pipeline.trigger_source >>
-              - scheduled_pipeline
diff --git a/.github/workflows/ci.bazelrc b/.github/workflows/ci.bazelrc
index 4821d32..74059fd 100644
--- a/.github/workflows/ci.bazelrc
+++ b/.github/workflows/ci.bazelrc
@@ -4,13 +4,3 @@
 
 # Debug where options came from
 common --announce_rc
-
-# Remote build execution
-build:rbe --extra_execution_platforms=@aspect_bazel_lib//platforms:x86_64_linux_remote
-build:rbe --host_platform=@aspect_bazel_lib//platforms:x86_64_linux_remote
-build:rbe --jobs=32
-
-# BuildBuddy remote exec
-build:rbe --bes_results_url=https://app.buildbuddy.io/invocation/
-build:rbe --bes_backend=grpcs://remote.buildbuddy.io
-build:rbe --remote_executor=grpcs://remote.buildbuddy.io
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 7a7ccf9..c383d52 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -48,7 +48,6 @@
           echo "res=[${j%,}]" | tee -a $GITHUB_OUTPUT
     outputs:
       bazel-version: ${{ steps.bazel-version.outputs.res }}
-      config: ${{ steps.config.outputs.res }}
       os: ${{ steps.os.outputs.res }}
   test:
     runs-on: ${{ matrix.os }}-latest
@@ -60,7 +59,6 @@
         bazel-version: ${{ fromJSON(needs.matrix-prep.outputs.bazel-version) }}
         bzlmod: [1, 0]
         os: ${{ fromJSON(needs.matrix-prep.outputs.os) }}
-        config: ${{ fromJSON(needs.matrix-prep.outputs.config) }}
         folder:
           - "."
           - "e2e/copy_action"
@@ -70,7 +68,7 @@
           - "e2e/smoke"
           - "e2e/write_source_files"
         exclude:
-          # Root workspace is only bzlmod
+          # Root workspace is bzlmod-only
           - folder: .
             bzlmod: 0
           # Don't test MacOS and Windows against secondary bazel version to minimize minutes (billed at 10X and 2X respectively)
@@ -85,9 +83,6 @@
           - bazel-version:
               major: 6
             bzlmod: 1
-          # Root workspace is bzlmod-only
-          - folder: .
-            bzlmod: 0
           # TODO: green up root Workspace on MacOS & Windows
           - folder: .
             os: macos
@@ -131,7 +126,6 @@
             --bazelrc=${GITHUB_WORKSPACE//\\/\/}/.aspect/bazelrc/ci.bazelrc \
             --bazelrc=${GITHUB_WORKSPACE//\\/\/}/.github/workflows/ci.bazelrc \
             test \
-            --config=${{ matrix.config }} \
             --test_tag_filters=-skip-on-bazel${{ matrix.bazel-version.major }} \
             --build_tag_filters=-skip-on-bazel${{ matrix.bazel-version.major }} \
             --enable_bzlmod=${{ matrix.bzlmod }} \
diff --git a/.shellcheckrc b/.shellcheckrc
new file mode 100644
index 0000000..aade3f9
--- /dev/null
+++ b/.shellcheckrc
@@ -0,0 +1,6 @@
+# Turn on warnings for unquoted variables with safe values
+enable=quote-safe-variables
+# Turn on warnings for unassigned uppercase variables
+enable=check-unassigned-uppercase
+
+#enable=require-variable-braces
\ No newline at end of file
diff --git a/.vale.ini b/.vale.ini
new file mode 100644
index 0000000..79a2a41
--- /dev/null
+++ b/.vale.ini
@@ -0,0 +1,19 @@
+# Configuration for https://Vale.sh
+# See https://vale.sh/docs/topics/config/
+
+StylesPath = tools/lint/vale
+IgnoredScopes = code
+
+# Tell Vale to look in tools/lint/vale/config/vocabularies/engineering
+Vocab = engineering
+
+[*.md]
+BlockIgnores = ```[a-z]*\n.*?\n```
+BasedOnStyles = Vale, Google
+
+# Reduce levels to make silo error-free.
+# TODO(alex): consider promoting some to error
+Google.Exclamation = warning
+Google.Quotes = warning
+Vale.Spelling = warning
+Vale.Terms = warning
diff --git a/BUILD.bazel b/BUILD.bazel
index 1b18b97..94fb9b5 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,3 +1,4 @@
+load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin")
 load("@aspect_bazel_lib_host//:defs.bzl", "host")
 load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
 load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
@@ -10,6 +11,8 @@
 load("//lib:write_source_files.bzl", "write_source_files")
 load("//lib:yq.bzl", "yq")
 
+exports_files([".shellcheckrc"])
+
 # gazelle:prefix github.com/aspect-build/bazel-lib
 
 gazelle_binary(
@@ -163,3 +166,18 @@
     file1 = "tar_test13_mtree",
     file2 = "//lib/tests/tar:expected13.mtree",
 )
+
+# Place the .vale.ini file in bazel-bin so the relative path it contains
+# StylesPath = tools/lint/vale
+# will work when it's run as an action.
+copy_to_bin(
+    name = ".vale_ini",
+    srcs = [".vale.ini"],
+    visibility = ["//visibility:public"],
+)
+
+filegroup(
+    name = "markdown_files",
+    srcs = glob(["*.md"]),
+    tags = ["markdown"],
+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7522ab0..95dedce 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,8 +1,8 @@
-# How to Contribute
+# How to contribute
 
 ## Formatting
 
-Starlark files should be formatted by buildifier.
+Starlark files should be formatted by Buildifier.
 We suggest using a pre-commit hook to automate this.
 First [install pre-commit](https://pre-commit.com/#installation) (>= v3.2.0),
 then run
diff --git a/MODULE.bazel b/MODULE.bazel
index 7118e84..95c3ddf 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -76,7 +76,7 @@
 host_platform = use_extension("@platforms//host:extension.bzl", "host_platform", dev_dependency = True)
 use_repo(host_platform, "host_platform")
 
-bazel_dep(name = "aspect_rules_lint", version = "1.0.0-rc8", dev_dependency = True)
+bazel_dep(name = "aspect_rules_lint", version = "1.0.0-rc10", dev_dependency = True)
 bazel_dep(name = "bazel_skylib_gazelle_plugin", version = "1.5.0", dev_dependency = True)
 bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
 bazel_dep(name = "bazel_features", version = "0.2.0", dev_dependency = True)
diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel
index 876b382..9bdbd08 100644
--- a/WORKSPACE.bazel
+++ b/WORKSPACE.bazel
@@ -15,7 +15,7 @@
 go_dependencies()
 
 ############################################
-# Aspect Workflows
-load("//.aspect/workflows:deps.bzl", "fetch_workflows_deps")
+# Lint
+load("@aspect_rules_lint//lint:vale.bzl", "fetch_vale")
 
-fetch_workflows_deps()
+fetch_vale()
diff --git a/deps.bzl b/deps.bzl
index 651bce7..f3fd520 100644
--- a/deps.bzl
+++ b/deps.bzl
@@ -34,3 +34,10 @@
         sum = "h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=",
         version = "v0.14.0",
     )
+    go_repository(
+        name = "org_golang_x_sys",
+        build_file_proto_mode = "disable_global",
+        importpath = "golang.org/x/sys",
+        sum = "h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=",
+        version = "v0.24.0",
+    )
diff --git a/go.mod b/go.mod
index 14f0521..0329eab 100644
--- a/go.mod
+++ b/go.mod
@@ -5,4 +5,5 @@
 require (
 	github.com/bmatcuk/doublestar/v4 v4.6.1
 	golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
+	golang.org/x/sys v0.24.0
 )
diff --git a/go.sum b/go.sum
index 3dc5ecc..874c84b 100644
--- a/go.sum
+++ b/go.sum
@@ -1,18 +1,6 @@
-github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
-github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
 github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I=
 github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
-golang.org/x/exp v0.0.0-20221230185412-738e83a70c30 h1:m9O6OTJ627iFnN2JIWfdqlZCzneRO6EEBsHXI25P8ws=
-golang.org/x/exp v0.0.0-20221230185412-738e83a70c30/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
-golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug=
-golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
-golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o=
-golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
-golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
-golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
-golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
-golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
-golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
-golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
+golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
+golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
diff --git a/lib/tests/run_binary_expansions/expansions.sh b/lib/tests/run_binary_expansions/expansions.sh
index 54e636c..63f8980 100755
--- a/lib/tests/run_binary_expansions/expansions.sh
+++ b/lib/tests/run_binary_expansions/expansions.sh
@@ -1,12 +1,12 @@
 #!/usr/bin/env bash
 set -o errexit -o nounset -o pipefail
 
-mkdir -p $(dirname $1)
+mkdir -p $(dirname "$1")
 outfile=$1
-rm -f $outfile
+rm -f "$outfile"
 for each in $@; do
   sanitized=${each/darwin/PLATFORM}
   sanitized=${sanitized/k8/PLATFORM}
   sanitized=${sanitized/_arm64/}
-  echo $sanitized >>$outfile
+  echo "$sanitized" >>"$outfile"
 done
diff --git a/lib/tests/stamping/stamper.sh b/lib/tests/stamping/stamper.sh
index 35e1349..a24622d 100755
--- a/lib/tests/stamping/stamper.sh
+++ b/lib/tests/stamping/stamper.sh
@@ -6,8 +6,8 @@
 # is another option, which requires Bash 4 for associative arrays.
 while IFS= read -r line; do
   read key value <<<"$line"
-  declare $key="$value"
+  declare "$key"="$value"
 done < <(cat "${BAZEL_STABLE_STATUS_FILE:-/dev/null}" "${BAZEL_VOLATILE_STATUS_FILE:-/dev/null}")
 
 # A real program would do something useful with the stamp info, like pass it to a linker.
-echo "${BUILD_USER:-unstamped}" >$1
+echo "${BUILD_USER:-unstamped}" >"$1"
diff --git a/platforms/BUILD.bazel b/platforms/BUILD.bazel
index 27de620..031b173 100644
--- a/platforms/BUILD.bazel
+++ b/platforms/BUILD.bazel
@@ -1,3 +1,29 @@
+load("//platforms/config:defs.bzl", "platforms")
+
+[platform(
+    name = "{}_{}".format(
+        p.os,
+        p.cpu,
+    ),
+    constraint_values = [
+        "@platforms//os:{}".format(p.os),
+        "@platforms//cpu:{}".format(p.cpu),
+    ],
+    visibility = ["//visibility:public"],
+) for p in platforms]
+
+alias(
+    name = "linux_amd64",
+    actual = ":linux_x86_64",
+    visibility = ["//visibility:public"],
+)
+
+alias(
+    name = "linux_arm64",
+    actual = ":linux_aarch64",
+    visibility = ["//visibility:public"],
+)
+
 platform(
     name = "x86_64_linux_remote",
     constraint_values = [
diff --git a/platforms/config/BUILD.bazel b/platforms/config/BUILD.bazel
new file mode 100644
index 0000000..c48e4a2
--- /dev/null
+++ b/platforms/config/BUILD.bazel
@@ -0,0 +1,29 @@
+load(":defs.bzl", "platforms")
+
+config_setting(
+    name = "aarch64",
+    constraint_values = [
+        "@platforms//cpu:aarch64",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+config_setting(
+    name = "x86_64",
+    constraint_values = [
+        "@platforms//cpu:x86_64",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+[config_setting(
+    name = "{}_{}".format(
+        p.os,
+        p.cpu,
+    ),
+    constraint_values = [
+        "@platforms//os:{}".format(p.os),
+        "@platforms//cpu:{}".format(p.cpu),
+    ],
+    visibility = ["//visibility:public"],
+) for p in platforms]
diff --git a/platforms/config/defs.bzl b/platforms/config/defs.bzl
new file mode 100644
index 0000000..6269294
--- /dev/null
+++ b/platforms/config/defs.bzl
@@ -0,0 +1,7 @@
+"""This module generated the platforms list for the build matrix."""
+
+platforms = [
+    struct(os = os, cpu = cpu)
+    for os in ["linux", "macos"]
+    for cpu in ["aarch64", "x86_64"]
+]
diff --git a/tools/lint/BUILD.bazel b/tools/lint/BUILD.bazel
new file mode 100644
index 0000000..6a28b9b
--- /dev/null
+++ b/tools/lint/BUILD.bazel
@@ -0,0 +1,28 @@
+load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
+load("@bazel_skylib//rules:native_binary.bzl", "native_binary")
+
+package(default_visibility = ["//visibility:public"])
+
+native_binary(
+    name = "vale_bin",
+    src = select({
+        "//platforms/config:linux_x86_64": "@vale_Linux_64-bit//:vale",
+        "//platforms/config:macos_aarch64": "@vale_macOS_arm64//:vale",
+        "//platforms/config:macos_x86_64": "@vale_macOS_64-bit//:vale",
+    }),
+    out = "vale_bin",
+)
+
+# Take care to keep the StylesPath entry in /.vale.ini working:
+# - the editor sees tools/lint/vale in the source tree
+# - the linting aspect sees bazel-bin/tools/lint/vale
+copy_to_directory(
+    name = "vale_styles",
+    srcs = [
+        "vale",
+        "@vale_Google//:Google",
+    ],
+    out = "vale",
+    include_external_repositories = ["vale_*"],
+    replace_prefixes = {"vale/": ""},
+)
diff --git a/tools/lint/linters.bzl b/tools/lint/linters.bzl
new file mode 100644
index 0000000..16c3d87
--- /dev/null
+++ b/tools/lint/linters.bzl
@@ -0,0 +1,15 @@
+"Create linter aspects, see https://github.com/aspect-build/rules_lint/blob/main/docs/linting.md#installation"
+
+load("@aspect_rules_lint//lint:shellcheck.bzl", "lint_shellcheck_aspect")
+load("@aspect_rules_lint//lint:vale.bzl", "lint_vale_aspect")
+
+shellcheck = lint_shellcheck_aspect(
+    binary = "@multitool//tools/shellcheck",
+    config = "@@//:.shellcheckrc",
+)
+
+vale = lint_vale_aspect(
+    binary = "@@//tools/lint:vale_bin",
+    config = "@@//:.vale_ini",
+    styles = "@@//tools/lint:vale_styles",
+)
diff --git a/tools/lint/vale/config/vocabularies/engineering/accept.txt b/tools/lint/vale/config/vocabularies/engineering/accept.txt
new file mode 100644
index 0000000..39935fc
--- /dev/null
+++ b/tools/lint/vale/config/vocabularies/engineering/accept.txt
@@ -0,0 +1,84 @@
+# Proper Nouns
+Aspect
+Bazel
+Buildbarn
+Buildkite
+Coursier
+GitHub
+Gerrit
+Grafana
+GitLab
+Googlers
+HashiCorp
+BuildCop
+JUnit
+Buildifier
+Buildozer
+KPIs
+Kubernetes
+Memorystore
+MSBuild
+Redis
+Starlark
+Skymeld
+PyPI
+Netlify
+NVMe
+Plaintext
+Testcontainers
+YouTube
+
+[Rr]unbook
+[Ii]nvalidations?
+
+# Commonly understood acronyms
+ACLs
+AMIs
+APIs
+ASGs
+CPUs
+MRs
+
+# Language-specific ecosystem terms
+p?npm
+classpath
+virtualenv
+protobuf
+
+# Software quality terms
+auditable
+hermeticity
+incrementality
+performant
+composable
+
+# DevX terms
+abandonware
+codelab
+cron
+downloader
+monorepo
+rebase
+mutex
+hotfix
+oncall
+poisioning
+statefulness
+teardown
+toolchain
+transpile
+vendored
+vendoring
+
+# Bazel terms
+genrule
+rules_lint
+rules_py
+rules_oci
+formatters
+sandboxing
+sandboxed
+subprocess
+bzlmod
+rosetta
+ruleset
diff --git a/tools/lint/vale/config/vocabularies/engineering/reject.txt b/tools/lint/vale/config/vocabularies/engineering/reject.txt
new file mode 100644
index 0000000..ba0e162
--- /dev/null
+++ b/tools/lint/vale/config/vocabularies/engineering/reject.txt
@@ -0,0 +1 @@
+bar
\ No newline at end of file
diff --git a/tools/release/BUILD.bazel b/tools/release/BUILD.bazel
index e540b84..b5078be 100644
--- a/tools/release/BUILD.bazel
+++ b/tools/release/BUILD.bazel
@@ -33,23 +33,6 @@
     deps = ["@bazel_tools//tools/bash/runfiles"],
 )
 
-# Demonstration delivery target for Aspect Workflows.
-# In the future this could be wired up to push dev releases to an S3 bucket.
-sh_binary(
-    name = "tools_delivery_only_on_change",
-    srcs = ["delivery.sh"],
-    data = RELEASE_ARTIFACTS,
-    tags = ["deliverable"],
-)
-
-# Demonstration delivery target for Aspect Workflows.
-# In the future this could be wired up to push dev releases to an S3 bucket.
-sh_binary(
-    name = "tools_delivery",
-    srcs = ["delivery.sh"],
-    data = RELEASE_ARTIFACTS,
-)
-
 bzl_library(
     name = "hashes",
     srcs = ["hashes.bzl"],
diff --git a/tools/release/copy_release_artifacts.sh b/tools/release/copy_release_artifacts.sh
index 3432592..46c952a 100755
--- a/tools/release/copy_release_artifacts.sh
+++ b/tools/release/copy_release_artifacts.sh
@@ -25,7 +25,7 @@
   exit 1
 fi
 
-cd $BUILD_WORKSPACE_DIRECTORY
+cd "$BUILD_WORKSPACE_DIRECTORY"
 for arg in "$@"; do
-  cp -pv "$(rlocation $arg)" $DEST
+  cp -pv "$(rlocation "$arg")" "$DEST"
 done