From 618a61e4df69420092ef2e8867bc60251634206a Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 23 Oct 2026 16:32:37 +0200 Subject: [PATCH 1/4] fix(repo): inspect records a nested .cursor/rules/*.mdc; two stale comments Leftovers from the reviews of #66 and #109: - `detect_instructions` matched `.cursor/rules/` only at the repository root, so `web/.cursor/rules/style.mdc` gave no instruction record (raised by xaleryb on #66). A nested rule file is now `path-specific`, with the directory above `.cursor` as its `directory` and activation `unknown`, as for the root rule. - The `ci_local.py` docstring named `static` as the only job whose steps run under `!cancelled()`; the deptry step of `typecheck` does too. - The `TRACKED_DEPS` comment called every entry a direct dependency: `ragas` is in the `ragas` extra and `anthropic` comes with its `langchain-anthropic`. The instruction-rule table test moves from test_repo_environment.py, which is over the test length limit and may only shrink, to its own test_repo_instructions.py with the new case; the baseline drops to 1337. Signed-off-by: Anton Volkov --- ...3_150000_antonwolfy_nested-cursor-rules.md | 7 +++ dokimi/docs/repo-evaluation-contract.md | 8 +-- .../dokimi/repos/environment/instructions.py | 8 +++ dokimi/dokimi/runner/manifest.py | 3 +- dokimi/scripts/ci_local.py | 6 +-- dokimi/scripts/growth_baseline.json | 2 +- dokimi/tests/test_repo_environment.py | 36 -------------- dokimi/tests/test_repo_instructions.py | 49 +++++++++++++++++++ 8 files changed, 74 insertions(+), 45 deletions(-) create mode 100644 dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md create mode 100644 dokimi/tests/test_repo_instructions.py diff --git a/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md b/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md new file mode 100644 index 00000000..b5537f4e --- /dev/null +++ b/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md @@ -0,0 +1,7 @@ +### Fixed + +- **`repo inspect` records a nested `.cursor/rules/*.mdc`** — a rule file + under a subdirectory, such as `web/.cursor/rules/style.mdc`, was not + listed in `instructions`, while Cursor applies it to the files under that + directory. It is now a `path-specific` record whose `directory` is `web`; + its activation stays `unknown`, since the rule's frontmatter sets it. diff --git a/dokimi/docs/repo-evaluation-contract.md b/dokimi/docs/repo-evaluation-contract.md index 00aec556..b6265f64 100644 --- a/dokimi/docs/repo-evaluation-contract.md +++ b/dokimi/docs/repo-evaluation-contract.md @@ -877,10 +877,10 @@ not measured effects. The report keeps observations apart from findings: - `instructions`: one record per instruction file and per harness rule it - matches (a root `AGENTS.md`, a nested `CLAUDE.md`, `.cursor/rules/*.mdc`, - `.github/instructions/*.instructions.md`, …), with its `scope` - (`root`, `path-specific`, `mode-specific`, `local-private`, `legacy`, - `capability`, `unknown`), `activation`, the `directory` it applies to and + matches (a root `AGENTS.md`, a nested `CLAUDE.md`, `.cursor/rules/*.mdc` at + the root or in a subdirectory, `.github/instructions/*.instructions.md`, …), + with its `scope` (`root`, `path-specific`, `mode-specific`, `local-private`, + `legacy`, `capability`, `unknown`), `activation`, the `directory` it applies to and its size (for a link, the size of the file it names). This is what each harness documents; which files a given harness version loads is measured by the reach probe (§7). diff --git a/dokimi/dokimi/repos/environment/instructions.py b/dokimi/dokimi/repos/environment/instructions.py index d645a7a4..84fc6ec9 100644 --- a/dokimi/dokimi/repos/environment/instructions.py +++ b/dokimi/dokimi/repos/environment/instructions.py @@ -74,6 +74,11 @@ def _parent(p: str) -> str: return posixpath.dirname(p) or "." +def _cursor_dir(p: str) -> str: + """The directory a nested ``/.cursor/rules/*.mdc`` applies to: ````.""" + return p.split("/.cursor/rules/", 1)[0] + + def _roo_mode(p: str) -> str | None: if p.startswith(".roo/rules-"): return p.split("/")[1].removeprefix("rules-") @@ -104,6 +109,9 @@ def _roo_mode(p: str) -> str | None: directory=_parent), Rule(_under(".cursor/rules/", r"\.mdc$"), ("cursor",), "unknown", "unknown", notes=("activation depends on the rule's frontmatter",)), + Rule(lambda p: re.match(r"^.+/\.cursor/rules/.+\.mdc$", p) is not None, ("cursor",), "path-specific", + "unknown", directory=_cursor_dir, + notes=("applies to files under its directory; activation depends on the rule's frontmatter",)), Rule(_named(".cursorrules"), ("cursor", "cline"), "legacy", "always", legacy=True), Rule(_named("GEMINI.md"), ("gemini", "github-copilot"), "root", "always"), Rule(_nested("GEMINI.md"), ("gemini",), "path-specific", "path-scoped", directory=_parent), diff --git a/dokimi/dokimi/runner/manifest.py b/dokimi/dokimi/runner/manifest.py index 3fb1207c..4a6cf9e6 100644 --- a/dokimi/dokimi/runner/manifest.py +++ b/dokimi/dokimi/runner/manifest.py @@ -19,7 +19,8 @@ from dokimi import __version__, process -# Direct dependencies whose versions materially affect results. +# Dependencies whose versions materially affect results. ``ragas`` comes with the ``ragas`` +# extra and ``anthropic`` with that extra's ``langchain-anthropic``; one not installed is None. TRACKED_DEPS = ( "litellm", "openai", "anthropic", "ragas", "datasets", "jsonschema", "numpy", "PyYAML", "httpx", diff --git a/dokimi/scripts/ci_local.py b/dokimi/scripts/ci_local.py index 5e12ac02..c0ea3b83 100755 --- a/dokimi/scripts/ci_local.py +++ b/dokimi/scripts/ci_local.py @@ -20,9 +20,9 @@ windows-smoke, conda-forge-deps) run in a throwaway venv on a copy of the tracked tree instead, so the dev venv stays as CI's. - Every step runs even when an earlier one fails, so one failure does not hide - the next (CI stops a job's checks at its first failing step, except - `static`, whose steps after the install all run under - `if: ${{ !cancelled() }}`). + the next (CI stops a job's checks at its first failing step, except for + steps under `if: ${{ !cancelled() }}`: every step of `static` after the + install, and the deptry step of `typecheck`). - A matrix runs one leg: the dev venv's Python, standing in for the coverage leg too (`matrix.coverage` is true), so the changed-lines gate runs here. A notice says so when that is not the Python CI's single-version jobs use. diff --git a/dokimi/scripts/growth_baseline.json b/dokimi/scripts/growth_baseline.json index 0c237b9f..8d585f33 100644 --- a/dokimi/scripts/growth_baseline.json +++ b/dokimi/scripts/growth_baseline.json @@ -11,7 +11,7 @@ "tests/test_judge_reliability.py": {"lines": 1695, "rationale": "grew on main in #73 (judge-validity --context stored), 1505 -> 1695, before the ratchet landed; split it in its own PR"}, "tests/test_judge_validity.py": {"lines": 2235, "rationale": "grew on main in #73 (judge-validity --context stored), 1423 -> 2235, before the ratchet landed; split it in its own PR"}, "tests/test_pipeline_question_set.py": {"lines": 1223}, - "tests/test_repo_environment.py": {"lines": 1373, "rationale": "grew on main in #147 before the ratchet landed; +2 for the instructions assert of two crash tests (#103 review); split it in its own PR"}, + "tests/test_repo_environment.py": {"lines": 1337, "rationale": "grew on main in #147 before the ratchet landed; +2 for the instructions assert of two crash tests (#103 review); split it in its own PR"}, "tests/test_subjects.py": {"lines": 1064}, "tests/test_task_formats.py": {"lines": 1003} }, diff --git a/dokimi/tests/test_repo_environment.py b/dokimi/tests/test_repo_environment.py index 649080cd..3838f1ec 100644 --- a/dokimi/tests/test_repo_environment.py +++ b/dokimi/tests/test_repo_environment.py @@ -877,42 +877,6 @@ def test_autotools_names_the_makefile_that_declares_tests(tmp_path): "tests/Makefile.am"] -INSTRUCTION_TABLE = [ - (".claude/CLAUDE.md", ('claude-code',), "root", "always", False), - (".claude/rules/a.md", ('claude-code',), "unknown", "unknown", False), - (".claude/skills/x/SKILL.md", ('claude-code',), "capability", "on-demand", False), - (".clinerules", ('cline',), "legacy", "always", True), - (".clinerules/a.md", ('cline',), "root", "unknown", False), - (".cursor/rules/a.mdc", ('cursor',), "unknown", "unknown", False), - (".cursorrules", ('cursor', 'cline'), "legacy", "always", True), - (".github/agents/a.agent.md", ('github-copilot',), "capability", "manual", False), - (".github/copilot-instructions.md", ('github-copilot',), "root", "always", False), - (".github/instructions/a.instructions.md", ('github-copilot',), "path-specific", "path-scoped", False), - (".roo/rules-code/a.md", ('roo-code',), "mode-specific", "mode-scoped", False), - (".roo/rules/a.md", ('roo-code',), "root", "always", False), - (".roomodes", ('roo-code',), "mode-specific", "mode-scoped", False), - (".roorules", ('roo-code',), "legacy", "always", True), - (".roorules-code", ('roo-code',), "mode-specific", "mode-scoped", True), - (".windsurf/rules/a.md", ('windsurf',), "unknown", "unknown", False), - (".windsurfrules", ('windsurf', 'cline'), "legacy", "always", True), - ("AGENTS.md", ('codex', 'github-copilot', 'cursor', 'windsurf', 'cline', 'generic'), "root", "always", False), - ("AGENTS.override.md", ('codex',), "root", "always", False), - ("CLAUDE.local.md", ('claude-code',), "local-private", "always", False), - ("CLAUDE.md", ('claude-code', 'github-copilot'), "root", "always", False), - ("GEMINI.md", ('gemini', 'github-copilot'), "root", "always", False), - ("sub/AGENTS.md", ('codex', 'github-copilot', 'cursor', 'windsurf', 'cline', 'generic'), "path-specific", "path-scoped", False), - ("sub/AGENTS.override.md", ('codex',), "path-specific", "path-scoped", False), - ("sub/CLAUDE.md", ('claude-code',), "path-specific", "path-scoped", False), - ("sub/GEMINI.md", ('gemini',), "path-specific", "path-scoped", False), -] - - -def test_instruction_rule_table(): - got = [(i.path, tuple(i.harnesses), i.scope, i.activation, i.legacy) - for i in detect_instructions([row[0] for row in INSTRUCTION_TABLE])] - assert got == INSTRUCTION_TABLE - - @pytest.mark.parametrize("command, flagged", [ # wrappers with options that take a value, and a wrapper named by path ("sudo -u nobody npm ci", True), ("nice -n 10 npm ci", True), ("timeout -s KILL 30 npm ci", True), diff --git a/dokimi/tests/test_repo_instructions.py b/dokimi/tests/test_repo_instructions.py new file mode 100644 index 00000000..25abbe18 --- /dev/null +++ b/dokimi/tests/test_repo_instructions.py @@ -0,0 +1,49 @@ +# Copyright (C) 2026 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +"""The instruction-file rules of ``repo inspect``: which harness reads each file, and where it applies.""" + +from __future__ import annotations + +from dokimi.repos.environment.instructions import detect_instructions + +INSTRUCTION_TABLE = [ + (".claude/CLAUDE.md", ('claude-code',), "root", "always", False), + (".claude/rules/a.md", ('claude-code',), "unknown", "unknown", False), + (".claude/skills/x/SKILL.md", ('claude-code',), "capability", "on-demand", False), + (".clinerules", ('cline',), "legacy", "always", True), + (".clinerules/a.md", ('cline',), "root", "unknown", False), + (".cursor/rules/a.mdc", ('cursor',), "unknown", "unknown", False), + (".cursorrules", ('cursor', 'cline'), "legacy", "always", True), + (".github/agents/a.agent.md", ('github-copilot',), "capability", "manual", False), + (".github/copilot-instructions.md", ('github-copilot',), "root", "always", False), + (".github/instructions/a.instructions.md", ('github-copilot',), "path-specific", "path-scoped", False), + (".roo/rules-code/a.md", ('roo-code',), "mode-specific", "mode-scoped", False), + (".roo/rules/a.md", ('roo-code',), "root", "always", False), + (".roomodes", ('roo-code',), "mode-specific", "mode-scoped", False), + (".roorules", ('roo-code',), "legacy", "always", True), + (".roorules-code", ('roo-code',), "mode-specific", "mode-scoped", True), + (".windsurf/rules/a.md", ('windsurf',), "unknown", "unknown", False), + (".windsurfrules", ('windsurf', 'cline'), "legacy", "always", True), + ("AGENTS.md", ('codex', 'github-copilot', 'cursor', 'windsurf', 'cline', 'generic'), "root", "always", False), + ("AGENTS.override.md", ('codex',), "root", "always", False), + ("CLAUDE.local.md", ('claude-code',), "local-private", "always", False), + ("CLAUDE.md", ('claude-code', 'github-copilot'), "root", "always", False), + ("GEMINI.md", ('gemini', 'github-copilot'), "root", "always", False), + ("sub/.cursor/rules/a.mdc", ('cursor',), "path-specific", "unknown", False), + ("sub/AGENTS.md", ('codex', 'github-copilot', 'cursor', 'windsurf', 'cline', 'generic'), "path-specific", "path-scoped", False), + ("sub/AGENTS.override.md", ('codex',), "path-specific", "path-scoped", False), + ("sub/CLAUDE.md", ('claude-code',), "path-specific", "path-scoped", False), + ("sub/GEMINI.md", ('gemini',), "path-specific", "path-scoped", False), +] + + +def test_instruction_rule_table(): + got = [(i.path, tuple(i.harnesses), i.scope, i.activation, i.legacy) + for i in detect_instructions([row[0] for row in INSTRUCTION_TABLE])] + assert got == INSTRUCTION_TABLE + + +def test_a_nested_cursor_rule_applies_to_its_directory(): + (rule,) = detect_instructions(["pkg/web/.cursor/rules/style.mdc", "pkg/web/.cursor/notes.md"]) + assert (rule.path, rule.scope, rule.directory) == ("pkg/web/.cursor/rules/style.mdc", "path-specific", "pkg/web") From 94a88a16cee5fcf184c7b3a58547b2e2498e4147 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 23 Oct 2026 18:48:52 +0200 Subject: [PATCH 2/4] fix(repo): a .cursor/rules below the root is listed with scope unknown Review of #200 (vchamarthi): Cursor's rules docs (cursor.com/docs/context/rules, read 2026-10-23) cover rule subfolders inside the root `.cursor/rules` and nested `AGENTS.md`, but not a `.cursor/rules` directory below the root. Recording one as `path-specific` claimed what no doc backs, against the table's rule of listing what each harness documents. It stays listed, with its `directory`, but scope and activation are `unknown` and its note says why; the changelog no longer says Cursor applies it. Signed-off-by: Anton Volkov --- .../20261023_150000_antonwolfy_nested-cursor-rules.md | 11 ++++++----- dokimi/dokimi/repos/environment/instructions.py | 9 ++++++--- dokimi/tests/test_repo_instructions.py | 7 ++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md b/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md index b5537f4e..d316eaf4 100644 --- a/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md +++ b/dokimi/changelog.d/20261023_150000_antonwolfy_nested-cursor-rules.md @@ -1,7 +1,8 @@ ### Fixed -- **`repo inspect` records a nested `.cursor/rules/*.mdc`** — a rule file - under a subdirectory, such as `web/.cursor/rules/style.mdc`, was not - listed in `instructions`, while Cursor applies it to the files under that - directory. It is now a `path-specific` record whose `directory` is `web`; - its activation stays `unknown`, since the rule's frontmatter sets it. +- **`repo inspect` lists a `.cursor/rules/*.mdc` below the root** — a rule + file such as `web/.cursor/rules/style.mdc` was not listed in + `instructions`. It is now a record with `directory` `web`, and with scope + and activation `unknown`: Cursor's rules docs cover only the root + `.cursor/rules` (and nested `AGENTS.md`), so whether Cursor reads it is not + known from the docs. Its note says so. diff --git a/dokimi/dokimi/repos/environment/instructions.py b/dokimi/dokimi/repos/environment/instructions.py index 84fc6ec9..5d1a4737 100644 --- a/dokimi/dokimi/repos/environment/instructions.py +++ b/dokimi/dokimi/repos/environment/instructions.py @@ -75,7 +75,7 @@ def _parent(p: str) -> str: def _cursor_dir(p: str) -> str: - """The directory a nested ``/.cursor/rules/*.mdc`` applies to: ````.""" + """The directory a nested ``/.cursor/rules/*.mdc`` would apply to: ````.""" return p.split("/.cursor/rules/", 1)[0] @@ -109,9 +109,12 @@ def _roo_mode(p: str) -> str | None: directory=_parent), Rule(_under(".cursor/rules/", r"\.mdc$"), ("cursor",), "unknown", "unknown", notes=("activation depends on the rule's frontmatter",)), - Rule(lambda p: re.match(r"^.+/\.cursor/rules/.+\.mdc$", p) is not None, ("cursor",), "path-specific", + # Cursor's rules docs (cursor.com/docs/context/rules, read 2026-10-23) place rules in the root + # .cursor/rules only, and nested AGENTS.md: one below the root is listed, its scope not known. + Rule(lambda p: re.match(r"^.+/\.cursor/rules/.+\.mdc$", p) is not None, ("cursor",), "unknown", "unknown", directory=_cursor_dir, - notes=("applies to files under its directory; activation depends on the rule's frontmatter",)), + notes=("below the root: Cursor documents only the root .cursor/rules, so whether it reads this " + "one is not known",)), Rule(_named(".cursorrules"), ("cursor", "cline"), "legacy", "always", legacy=True), Rule(_named("GEMINI.md"), ("gemini", "github-copilot"), "root", "always"), Rule(_nested("GEMINI.md"), ("gemini",), "path-specific", "path-scoped", directory=_parent), diff --git a/dokimi/tests/test_repo_instructions.py b/dokimi/tests/test_repo_instructions.py index 25abbe18..04df1531 100644 --- a/dokimi/tests/test_repo_instructions.py +++ b/dokimi/tests/test_repo_instructions.py @@ -30,7 +30,7 @@ ("CLAUDE.local.md", ('claude-code',), "local-private", "always", False), ("CLAUDE.md", ('claude-code', 'github-copilot'), "root", "always", False), ("GEMINI.md", ('gemini', 'github-copilot'), "root", "always", False), - ("sub/.cursor/rules/a.mdc", ('cursor',), "path-specific", "unknown", False), + ("sub/.cursor/rules/a.mdc", ('cursor',), "unknown", "unknown", False), ("sub/AGENTS.md", ('codex', 'github-copilot', 'cursor', 'windsurf', 'cline', 'generic'), "path-specific", "path-scoped", False), ("sub/AGENTS.override.md", ('codex',), "path-specific", "path-scoped", False), ("sub/CLAUDE.md", ('claude-code',), "path-specific", "path-scoped", False), @@ -44,6 +44,7 @@ def test_instruction_rule_table(): assert got == INSTRUCTION_TABLE -def test_a_nested_cursor_rule_applies_to_its_directory(): +def test_a_nested_cursor_rule_is_listed_with_its_directory_and_no_known_scope(): (rule,) = detect_instructions(["pkg/web/.cursor/rules/style.mdc", "pkg/web/.cursor/notes.md"]) - assert (rule.path, rule.scope, rule.directory) == ("pkg/web/.cursor/rules/style.mdc", "path-specific", "pkg/web") + assert (rule.path, rule.scope, rule.directory) == ("pkg/web/.cursor/rules/style.mdc", "unknown", "pkg/web") + assert any("Cursor documents only the root .cursor/rules" in note for note in rule.notes) From fb445e07b80e28174b580ad68d1619b6a8194545 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 23 Oct 2026 20:41:38 +0200 Subject: [PATCH 3/4] fix(repo): a path under the root .cursor/rules gets one record; nested ones the closest dir Review of #200 (exai-bot): the nested-rule pattern also matched `.cursor/rules/sub/.cursor/rules/b.mdc`, which the root rule already covers, so the file got two records; and `_cursor_dir` split at the first `/.cursor/rules/`, so `a/.cursor/rules/b/.cursor/rules/c.mdc` got `a`. The nested rule now skips paths under the root `.cursor/rules/`, and the directory is the one above the closest `.cursor/rules/`. Signed-off-by: Anton Volkov --- dokimi/dokimi/repos/environment/instructions.py | 12 ++++++++---- dokimi/tests/test_repo_instructions.py | 8 ++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dokimi/dokimi/repos/environment/instructions.py b/dokimi/dokimi/repos/environment/instructions.py index 5d1a4737..ed1c56d3 100644 --- a/dokimi/dokimi/repos/environment/instructions.py +++ b/dokimi/dokimi/repos/environment/instructions.py @@ -74,9 +74,14 @@ def _parent(p: str) -> str: return posixpath.dirname(p) or "." +def _nested_cursor_rule(p: str) -> bool: + """A ``/.cursor/rules/*.mdc`` below the root; one under the root ``.cursor/rules/`` is the root rule's.""" + return not p.startswith(".cursor/rules/") and re.match(r"^.+/\.cursor/rules/.+\.mdc$", p) is not None + + def _cursor_dir(p: str) -> str: - """The directory a nested ``/.cursor/rules/*.mdc`` would apply to: ````.""" - return p.split("/.cursor/rules/", 1)[0] + """The directory a nested ``/.cursor/rules/*.mdc`` would apply to: ````, the closest one.""" + return p.rsplit("/.cursor/rules/", 1)[0] def _roo_mode(p: str) -> str | None: @@ -111,8 +116,7 @@ def _roo_mode(p: str) -> str | None: notes=("activation depends on the rule's frontmatter",)), # Cursor's rules docs (cursor.com/docs/context/rules, read 2026-10-23) place rules in the root # .cursor/rules only, and nested AGENTS.md: one below the root is listed, its scope not known. - Rule(lambda p: re.match(r"^.+/\.cursor/rules/.+\.mdc$", p) is not None, ("cursor",), "unknown", - "unknown", directory=_cursor_dir, + Rule(_nested_cursor_rule, ("cursor",), "unknown", "unknown", directory=_cursor_dir, notes=("below the root: Cursor documents only the root .cursor/rules, so whether it reads this " "one is not known",)), Rule(_named(".cursorrules"), ("cursor", "cline"), "legacy", "always", legacy=True), diff --git a/dokimi/tests/test_repo_instructions.py b/dokimi/tests/test_repo_instructions.py index 04df1531..b4a0eb4e 100644 --- a/dokimi/tests/test_repo_instructions.py +++ b/dokimi/tests/test_repo_instructions.py @@ -48,3 +48,11 @@ def test_a_nested_cursor_rule_is_listed_with_its_directory_and_no_known_scope(): (rule,) = detect_instructions(["pkg/web/.cursor/rules/style.mdc", "pkg/web/.cursor/notes.md"]) assert (rule.path, rule.scope, rule.directory) == ("pkg/web/.cursor/rules/style.mdc", "unknown", "pkg/web") assert any("Cursor documents only the root .cursor/rules" in note for note in rule.notes) + + +def test_a_cursor_rules_path_gets_one_record_and_the_closest_directory(): + paths = [".cursor/rules/sub/.cursor/rules/b.mdc", "a/.cursor/rules/b/.cursor/rules/c.mdc"] + got = sorted((i.path, i.directory) for i in detect_instructions(paths)) + # under the root .cursor/rules: the root rule's only; nested twice: the inner .cursor's directory + assert got == [(".cursor/rules/sub/.cursor/rules/b.mdc", None), + ("a/.cursor/rules/b/.cursor/rules/c.mdc", "a/.cursor/rules/b")] From 95ed6776c1ae86d2df95a5c6b3a50d33140cdce9 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 23 Oct 2026 20:41:38 +0200 Subject: [PATCH 4/4] docs(repo): what `directory` means for an instruction record of unknown scope Review of #200 (exai-bot): the contract defines an instruction record's `directory` as the one the file applies to, while a nested `.cursor/rules` record's note says Cursor may not read the file at all. For a record whose scope is `unknown`, it is the directory the file would apply to. Signed-off-by: Anton Volkov --- dokimi/docs/repo-evaluation-contract.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dokimi/docs/repo-evaluation-contract.md b/dokimi/docs/repo-evaluation-contract.md index b6265f64..a5304e97 100644 --- a/dokimi/docs/repo-evaluation-contract.md +++ b/dokimi/docs/repo-evaluation-contract.md @@ -880,8 +880,9 @@ The report keeps observations apart from findings: matches (a root `AGENTS.md`, a nested `CLAUDE.md`, `.cursor/rules/*.mdc` at the root or in a subdirectory, `.github/instructions/*.instructions.md`, …), with its `scope` (`root`, `path-specific`, `mode-specific`, `local-private`, - `legacy`, `capability`, `unknown`), `activation`, the `directory` it applies to and - its size (for a link, the size of the file it names). This is what each + `legacy`, `capability`, `unknown`), `activation`, the `directory` it applies to + (for a record whose scope is `unknown`, the one it would apply to) and its size + (for a link, the size of the file it names). This is what each harness documents; which files a given harness version loads is measured by the reach probe (§7). - `checks`: ways to build, test, lint and type-check, per project root (the