necklace-lint

necklace-lint

Check whether necklace's own artifacts in .necklace/ are being picked up by the repo's test discovery, dependency scanners, linters, or code scanning, and propose the exclusions that stop it. Also probes that beads is installed and configured. Use on the first necklace run in a repo, after necklace init, or when the user asks whether necklace is polluting the repo.

necklace-lint

Check whether necklace's own artifacts are polluting the repo that hosts them, and propose fixes.

This is not a pipeline stage. It does not read spec.md or cuj.md and it never runs as part of the three-stage sequence except once, on the first run in a repo.

It is also not a general-purpose linter. It checks .necklace/ and nothing else. Do not report code quality, style, or anything the repo's own tools already cover.

The rule that keeps this honest

Detect from the repo, never from memory.

Your knowledge of build tools and scanners is for interpreting what you find, not for enumerating what might exist. Seeing .github/workflows/codeql.yml and recognising that CodeQL will scan .necklace/ is the job. Proposing CodeQL exclusions for a repo with no CodeQL is not, and neither is inventing a config key that sounds plausible.

A config file that is not in the repo generates no finding. This is what lets the check keep improving as models get better, instead of hallucinating configuration with more confidence each year.

The tables below are a starting point, not the scope. If you find a tool they do not mention, and it reads committed files, and it would act on .necklace/, that is a finding. Read its documentation for the exclusion syntax rather than guessing.

Demonstrate, do not assert

Where the tool is installed, run it and show it picking up the planning directory.

pytest --collect-only listing a scratch test from .necklace/ is a finding. "Renovate may scan this" is not.

Report findings you can demonstrate, plus findings where the config is present and the reading is unambiguous. Do not report theoretical ones. Three real findings with output attached get fixed; twelve speculative ones get this skill uninstalled.

What to check

1. Test discovery

The one that matters most, because a scratch test silently joining the suite is a green test nobody designed.

The axis: does the build tool discover directories, or is it told about them? Discovery-based tools need an exclusion; manifest-based tools already ignore an undeclared directory.

Ecosystem Risk Fix
Python pytest collects test_*.py repo-wide norecursedirs = .necklace in pytest.ini or equivalent
Go a root go.mod puts every subdirectory in the module a nested go.mod, a testdata/ directory, or a leading _ or .
Rust a nested crate inside a workspace errors exclude = [".necklace"] in the root [workspace], or an empty [workspace] in the scratch crate
.NET SDK projects glob **/*.cs keep .necklace/ at repo root outside any project directory
JVM already invisible; Maven and Gradle are told what to build nothing
Node, TypeScript root tsconfig.json include, workspace globs add to exclude; keep workspace globs specific

Then verify: run the project's full test command and confirm nothing from .necklace/ appears.

2. Scanners that read committed files

Only check for tools the repo actually uses. Writing a renovate.json into a repo that has never heard of Renovate is its own kind of pollution.

Tool Present when Fix
Renovate renovate.json, .renovaterc*, or the config in package.json add .necklace/** to ignorePaths. Renovate auto-discovers manifests repo-wide, so this is the one that actually bites.
Dependabot .github/dependabot.yml usually nothing, since it is opt-in per directory. Check for a directories: glob such as **/*.
CodeQL a CodeQL workflow or config paths-ignore: [.necklace]
pre-commit .pre-commit-config.yaml top-level exclude: ^\.necklace/
linguist any repo on GitHub .necklace/** linguist-documentation=true in .gitattributes, so scratch code stops skewing language stats. Not linguist-generated, which collapses diffs.
Coverage a coverage config omit or equivalent for .necklace/*

3. What must never be committed

  • Resolved artifact directories: .venv, node_modules, target/, bin/, obj/. Gitignored is fine and often better, since re-resolving on every run fails in a network-restricted environment.
  • Lockfiles. A lockfile is an active input to Renovate and Dependabot, and the planning directory has no release and no security surface, so every alert it raises is false.

Prefer the ecosystem's single-file script mechanism so no manifest exists to scan: Python PEP 723 with uv run, Java JBang //DEPS, .NET #:package. Where none exists, a committed manifest plus exclusions is expected and fine.

4. Beads

Probe Method
installed and working bd --version exits 0. Run it; do not check PATH.
repo initialized a beads database directory is present
auto-export on bd config get export.auto is true
export staged bd config get export.git-add is true

There is no version row on purpose. bd versions that necklace cannot use are not ordered by version number, so running the commands is the only check that is right in every case.

Both export keys default to false and both are needed. Without them the bead graph lives only in the local database, and a bead ID in a CUJ document is a dangling pointer for anyone reading the repo on GitHub or reviewing a pull request.

Reporting

For each finding: what you found, how you know, and the exact change. Then ask.

Change nothing without a yes. Every fix here edits the repo's own configuration, which is a change the owner should approve. Apply what is accepted, print what you changed, and leave the rest.

If nothing is wrong, say so in one line. Do not manufacture findings to look useful.

Created: 2026-08-20 Thu 04:20