Skip to content

AGENTS.md / Copilot instructions document a Bazel API that does not exist (17 verified defects) + no reachable lint command #3780

Description

@napetrov

Summary

The agent-facing documentation in this repository (11 AGENTS.md files + 5 .github/instructions/*.instructions.md) contains 17 verified factual defects. Several of them do not merely omit information — they document build APIs, target names, and commands that do not exist in the repository. An AI coding agent that follows them produces BUILD files that cannot build and commands that cannot run.

Separately, no file in the repository gives an executable formatting/lint command to an agent, even though clang-format is a PR-blocking check.

Everything below was verified file-by-file against main @ e3a28f0b. Every claim cites file:line. Nothing is inferred from the tool output alone.

How this was produced / how to reproduce

Initial signal came from AgentReady v0.3.0, a local-first, offline repository-readiness scanner for AI coding agents:

npx @napetrov/agentready scan . --format markdown

Headline scan result for oneDAL main @ e3a28f0b: 76/100, 0 errors, 2 warnings, 5 info. Per-dimension: ci 100, instructions 100, safety 100, docs 96, commands 93, files 87. Autonomy envelope: ready at orient/bootstrap/review/merge/deploy; not-yet-ready at navigate, edit, verify.

That score is too generous. The scanner checks whether agent-facing surfaces are present, not whether their contents are true. Every defect in Part 1 below sits inside files the scanner scored 100/100. The defects were found by manually verifying each documented claim against the code.

Two scanner findings are themselves inaccurate and are not included as oneDAL problems (reported upstream to AgentReady instead):

  • commands.lint.missing — oneDAL does expose lint via .pre-commit-config.yaml and .ci/scripts/clang-format.sh; the scanner has no pre-commit detector. The real oneDAL problem is discoverability (Part 2), not absence.
  • governance.codeowners.single-owner-risk names the wrong person (it prints the alphabetically-first owner of the union, not the actual single owner). The underlying signal is real; the message is wrong.

Part 1 — Agent instructions document a build API that does not exist

This is the highest-impact group. An agent trusts these files over reading 147 BUILD files.

1.1 dev/bazel/AGENTS.md:48-73 — bare cc_library / cc_test with hand-written flags

The file instructs agents to write:

cc_library(
    name = "library_name",
    srcs = glob(["src/**/*.cpp"]),
    deps = ["//path/to:dependency", "//dev/bazel/deps:external_lib"],
    copts = ["-std=c++17", "-O3"],
)
cc_test(
    name = "library_test",
    srcs = glob(["test/**/*.cpp"]),
    deps = [":library_name", "//dev/bazel/deps:catch2"],
    copts = ["-std=c++17", "-g"],
)

Reality:

  • 0 of 147 BUILD files under cpp/ use cc_library or cc_test. All first-party modules use dal_module / dal_test_suite / daal_module loaded from @onedal//dev/bazel:dal.bzl (dev/bazel/dal.bzl:45, :170). Reference: cpp/oneapi/dal/algo/pca/BUILD:1-70.
  • 0 of 147 BUILD files under cpp/ contain copts. Compiler flags are toolchain-owned: dev/bazel/flags.bzl:84 get_default_flags → dev/bazel/toolchains/common.bzl:19,166. Hand-written -O3 would silently bypass CPU dispatch and ISA configuration.
  • //dev/bazel/deps:external_lib and //dev/bazel/deps:catch2 do not exist. dev/bazel/deps/BUILD is an empty file — the package declares zero targets. catch2 is wired by framework = "catch2", which injects @onedal//cpp/oneapi/dal/test/engine:catch2_main (dev/bazel/dal.bzl:177,195).
  • Test sources are excluded from module globs automatically (dal.bzl:53, test_filt), so glob(["test/**/*.cpp"]) in a separate cc_test is not how tests are wired here.

1.2 dev/bazel/AGENTS.md:42-43 — stale/incorrect MODULE.bazel excerpt

Documented:

bazel_dep(name = "rules_cc", version = "0.2.18")
bazel_dep(name = "catch2", version = "3.9.1")

Actual MODULE.bazel: 5 bazel_deps total — rules_cc is 0.2.22 (MODULE.bazel:21) — and catch2 is not a bazel_dep at all; it is a repository rule with build_file = "//dev/bazel/deps:catch2.BUILD" (MODULE.bazel:43,47).

1.3 bazel test //... is not a supported invocation (2 files)

dev/bazel/AGENTS.md:80,86 and dev/AGENTS.md:52,55 tell agents to run bazel build //... and bazel test //.... That string appears nowhere in dev/bazel/README.md, which documents only scoped targets with an explicit --config (dev/bazel/README.md:340,350,355,365).

1.4 bazel test //cpp/oneapi/dal:tests is mislabeled "CPU tests" (2 files)

cpp/oneapi/AGENTS.md:20-21 labels it # Run CPU tests; .github/instructions/build-systems.instructions.md:39 presents it the same way.

dev/bazel/README.md:163-168 states that with --config unspecified (the default) Bazel will "Build and run all tests" — DPC++ included — and that host-only requires --config=host. On a machine without the Intel DPC++ compiler the documented "CPU test" command fails at toolchain resolution, which an agent will most likely report as a broken repository.

1.5 .github/instructions/build-systems.instructions.md:36 — nonexistent target

bazel build //examples/daal/cpp:association_rules. No association string in examples/daal/cpp/BUILD; no examples/daal/cpp/source/association_rules/ directory. Real targets are daal_example_suite-generated: cholesky (:33), datasource (:44), decision_forest (:56), distance (:71), …

1.6 .github/instructions/build-systems.instructions.md:46-47 — CMake recipe cannot work

cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel

There is no root CMakeLists.txt. oneDAL's CMake surface is consumer-side: examples/oneapi/cpp/CMakeLists.txt:28 does find_package(oneDAL REQUIRED) against an installed release; cmake/ contains only scripts/ and templates/.

1.7 Commands are backtick-wrapped inside ```bash fences (2 files)

cpp/oneapi/AGENTS.md:18-24 and .github/instructions/build-systems.instructions.md:35-47 render as:

`bazel build //cpp/oneapi/dal:core`

Copy-pasted verbatim, the shell performs command substitution instead of running Bazel. Every command in both blocks is affected.


Part 2 — No formatting/lint command is reachable by an agent

clang-format and editorconfig-checker are PR-blocking (.ci/pipeline/ci.yml:63-77, job FormatterChecks; pr: trigger at .ci/pipeline/ci.yml:30). Yet:

  • Root AGENTS.md contains zero commands of any kind — its only two code fences (lines 21 and 30) are the repository-tree diagram.
  • Grepping pre-commit|clang-format.sh|editorconfig-checker across all 11 AGENTS.md and all 5 .instructions.md files yields only three inventory lines in .ci/AGENTS.md:15,18,41 — descriptions of scripts that exist, never an invocation.
  • .ci/AGENTS.md:97-109 "Local Development" gives apt.sh, build.sh, test.sh — no format step.
  • pre-commit appears in no agent-facing file. Only CONTRIBUTING.md:70 mentions it, and root AGENTS.md's pointer into .ci/ is a broken link (§3.1), so the chain is severed.
  • Style is not gated in GitHub Actions: grep -n bazel .github/workflows/ci.yml is empty and the file has exactly two jobs, LinuxMakeDPCPP (:37) and LinuxABICheck (:128). An agent that inspects .github/workflows/ concludes formatting is unenforced, then gets a red Azure check from a config it was never pointed at.

Additional broken guidance in the one place formatting is documented:

  • CONTRIBUTING.md:63 — clang-format style=file <your file>: missing the leading dash. Correct form is clang-format -style=file -i <file>.
  • CONTRIBUTING.md:60 links https://github.com/uxlfoundation/oneDAL/blob/main/.clang-format — 404. There is no root .clang-format; there are seven, one per source tree (cpp/daal, cpp/oneapi, examples/daal, examples/oneapi, samples/daal, samples/oneapi, dev/l0_tools).

Part 3 — Dead links and internal contradictions

Location Says Reality
AGENTS.md:49 [ci/AGENTS.md](ci/AGENTS.md) No ci/ directory. File is .ci/AGENTS.md
AGENTS.md:87 [.clang-format](.clang-format) No root .clang-format (7 per-directory ones)
CONTRIBUTING.md:60 blob/main/.clang-format Same dead path, public 404
AGENTS.md:13 vs :56 "Modern C++ (17+)" vs "Use C++14/17 features appropriately" cpp/AGENTS.md:22: "C++17 (no C++20/23 features for compatibility)"
AGENTS.md:21-30 Root tree shown as daal/, listing only cpp/ dev/ examples/ docs/ deploy/ Actual root also has .ci/, data/, samples/, cmake/, conda-recipe/
.ci/AGENTS.md:77,79 "Mergify: Automated merge management", "Codefactor: Code quality analysis" No Mergify or Codefactor config at root or in .github/. (renovate.json exists, so :78 is accurate)

Coverage gap: samples/ has no AGENTS.md, though examples/ does and both are treated identically by CODEOWNERS (:9,:10) and by .ci/scripts/clang-format.sh.


Part 4 — CODEOWNERS: two dead rules and four single-owner paths

CODEOWNERS resolves by last matching pattern wins. Two rules are consequently dead:

  1. .github/CODEOWNERS:33 .github/workflows/* @icfaust overrides both

    • :14 .github/ @napetrov @homksei @ahuber21 @ethanglaser @icfaust, and
    • :32 .github/workflows/ci-aarch64.yml @rakshithgb-fujitsu.

    Net effect: all 16 workflows are reviewer-gated on one person, and the aarch64 maintainer is not a required reviewer on the aarch64 workflow. Given that :14 and :32 exist, this is almost certainly not intended.

  2. :16 WORKSPACE @napetrov @homksei @ahuber21 @ethanglaser @icfaust — WORKSPACE no longer exists after the bzlmod migration (MODULE.bazel:17 module(name = "onedal")).

Single-individual ownership on core build infrastructure, with no team fallback:

Line Pattern Sole owner
:19 make* @Alexandr-Solovev
:20 cmake/ @Alexandr-Solovev
:23 dev/bazel/ @Alexandr-Solovev
:24 MODULE.bazel* @Alexandr-Solovev
:33 .github/workflows/* @icfaust

Not a criticism of anyone's coverage — the point is that review of the build system and all CI has a bus factor of 1 by configuration.


Part 5 — 21% of the repository is four files, none marked as generated

File Bytes
data/qr.csv 2,704,958
data/svd.csv 2,704,958
data/dbscan_dense.csv 2,117,973
docs/dalapi/doxypy/parser/compound.py 1,976,538

9,504,427 of 45,030,733 total bytes = 21.1%, in 4 of 4,081 files.

compound.py is machine-generated and checked in — its own header says so (docs/dalapi/doxypy/parser/compound.py:29-38):

# Generated Fri Apr 24 19:24:13 2020 by generateDS.py version 2.35.21.
# Command line arguments:  ./doxygen/xml/compound.xsd

43,921 lines, 503 classes, sitting inside the documentation source tree. .gitattributes marks binaries but contains no linguist-generated, so nothing signals to an agent (or to GitHub's diff view) that these files should not be read or reviewed. A grep-then-read agent can exhaust its context window on a single file.


Proposed fixes

Four independent changes. Happy to open the PRs.

PR 1 — links, typos, contradictions (AGENTS.md, CONTRIBUTING.md)

  • AGENTS.md:49: ci/AGENTS.md → .ci/AGENTS.md
  • AGENTS.md:87: drop the root .clang-format link; point at cpp/oneapi/.clang-format and note the configs are per-source-tree
  • AGENTS.md:56: C++14/17 → C++17 (no C++20/23 features), matching cpp/AGENTS.md:22
  • AGENTS.md:21-30: correct the root tree
  • CONTRIBUTING.md:60: replace the 404 link with the per-directory list
  • CONTRIBUTING.md:63: clang-format style=file <your file> → clang-format -style=file -i <your file>
  • .ci/AGENTS.md:77,79: drop the Mergify/Codefactor claims, or add the configs

PR 2 — a "Verification" section in root AGENTS.md

Proposed text
## Verification Before You Push

### Format and style (blocking check — Azure `FormatterChecks`)

```bash
# One-time setup
pip install pre-commit && pre-commit install

# Format what you touched
pre-commit run --all-files

# Or exactly what CI runs (clang-format 20.1.8; other versions differ in output)
CLANG_FORMAT_EXE=clang-format-20 .ci/scripts/clang-format.sh
editorconfig-checker
```

clang-format configs are per-directory, not at the repo root: `cpp/daal/`,
`cpp/oneapi/`, `examples/daal/`, `examples/oneapi/`, `samples/daal/`,
`samples/oneapi/`, `dev/l0_tools/`. Run from the repo root so `-style=file`
resolves the right one.

### Tests (Bazel — fastest signal)

```bash
bazel test --config=host //cpp/oneapi/dal/algo/<algo>:tests   # one algorithm, CPU only
bazel test --config=host //cpp/oneapi/dal:tests               # oneAPI interface, CPU only
bazel test --config=dpc --device=gpu //cpp/oneapi/dal:tests   # DPC++/GPU
```

`--config=host` is required for a CPU-only machine. With `--config` omitted,
Bazel builds and runs *all* tests including DPC++ and needs the Intel DPC++
compiler (see `dev/bazel/README.md`).

### Full build (Make — what release CI does)

```bash
make -f makefile daal oneapi_c PLAT=lnx32e -j$(nproc)
```

`PLAT`: `lnx32e`, `win32e`, `lnxarm`, `lnxriscv64`, `mac32e`. See `INSTALL.md`
for debug, sanitizer, and coverage variants.

### Where the checks live

| Check | System | Config |
|---|---|---|
| clang-format, editorconfig-checker | Azure DevOps | `.ci/pipeline/ci.yml` (`FormatterChecks`) |
| Make builds, Bazel, rv64, Windows | Azure DevOps | `.ci/pipeline/ci.yml` |
| Make + DPC++, ABI check | GitHub Actions | `.github/workflows/ci.yml` |
| aarch64 | GitHub Actions | `.github/workflows/ci-aarch64.yml` |
| License headers | GitHub Actions | `.github/workflows/skywalking-eyes.yml` |
| Bazel lnx/win | GitHub Actions (nightly only) | `.github/workflows/nightly-test.yml` |

Style is **not** gated in GitHub Actions. A green Actions run does not mean your
formatting passes.

Optionally, move the format gate into GitHub Actions so it is visible where agents look — .ci/env/apt.sh clang-format + .ci/env/editorconfig-checker.sh + .ci/scripts/clang-format.sh is a ~20-line workflow.

PR 3 — correct the Bazel documentation in all four files

dev/bazel/AGENTS.md, dev/AGENTS.md, cpp/oneapi/AGENTS.md, .github/instructions/build-systems.instructions.md.

Replacement for the target-pattern block
oneDAL does **not** use bare `cc_library`/`cc_test`. All modules go through
macros in `@onedal//dev/bazel:dal.bzl`. Compiler flags, CPU dispatch, and
threading are toolchain-owned (`dev/bazel/flags.bzl`) — never hand-write `copts`.

```python
load("@onedal//dev/bazel:dal.bzl", "dal_module", "dal_test_suite")

package(default_visibility = ["//visibility:public"])

dal_module(
    name = "core",
    auto = True,                       # globs sources by convention, excludes test/
    dal_deps = ["@onedal//cpp/oneapi/dal:core"],
    extra_deps = ["@onedal//cpp/daal/src/algorithms/pca:kernel"],
)

dal_test_suite(
    name = "interface_tests",
    srcs = glob(["test/*.cpp"]),
    hdrs = glob(["test/*.hpp"]),
    dal_deps = [":pca"],
    framework = "catch2",              # do not add a catch2 dep by hand
)

dal_test_suite(
    name = "tests",                    # aggregate target CI invokes
    tests = [":backend_tests", ":interface_tests"],
)
```

Reference implementation: `cpp/oneapi/dal/algo/pca/BUILD`.

Also: delete the //... commands, add --config=host where "CPU" is meant, fix the MODULE.bazel excerpt (rules_cc 0.2.22; catch2 is a repo rule, not a bazel_dep), replace //examples/daal/cpp:association_rules with a real target, replace the root cmake -B build -S . recipe with the examples-directory find_package(oneDAL) flow, and unwrap the backticks inside the ```bash fences.

Suggestion for review hygiene: anything in an AGENTS.md that cannot be copy-verified against a real BUILD/script should be deleted rather than softened. A wrong map costs an agent more than no map.

PR 4 — CODEOWNERS + generated-file markers

 .github/       @napetrov @homksei @ahuber21 @ethanglaser @icfaust
 .bazelversion  @napetrov @homksei @ahuber21 @ethanglaser @icfaust
-WORKSPACE      @napetrov @homksei @ahuber21 @ethanglaser @icfaust
@@
-make*          @Alexandr-Solovev
-cmake/         @Alexandr-Solovev
+make*          @Alexandr-Solovev @uxlfoundation/oneDAL-maintain
+cmake/         @Alexandr-Solovev @uxlfoundation/oneDAL-maintain
@@
-dev/bazel/     @Alexandr-Solovev
-MODULE.bazel*  @Alexandr-Solovev
+dev/bazel/     @Alexandr-Solovev @uxlfoundation/oneDAL-maintain
+MODULE.bazel*  @Alexandr-Solovev @uxlfoundation/oneDAL-maintain
@@
-.github/workflows/*                        @icfaust
+.github/workflows/*                        @icfaust @napetrov @homksei @ahuber21 @ethanglaser

.github/workflows/ci-aarch64.yml @rakshithgb-fujitsu must move after the .github/workflows/* rule to survive last-match-wins, and a header comment documenting that precedence rule would prevent the next occurrence.

.gitattributes:

# Generated / bulk data — agents and diffs should skip these
docs/dalapi/doxypy/parser/compound.py linguist-generated=true
data/*.csv                            linguist-generated=true -diff

Longer term, compound.py would be better regenerated at docs-build time (or moved out of docs/) than carried as a 1.9 MB checked-in artifact.


Why this matters now

The AGENTS.md and .github/instructions/ surfaces in this repository are unusually thorough — 11 nested instruction files and 5 path-scoped Copilot instruction files put oneDAL well ahead of most C++ projects on agent readiness. That is exactly why the inaccuracies are worth fixing: agents weight these files heavily, and the ones documenting Bazel currently teach an API the repository does not have.

Happy to open PRs 1-4 in that order, or split differently if maintainers prefer.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions