Skip to content

Commit 86cef74

Browse files
committed
Improve rules tests
1 parent c6b82a5 commit 86cef74

6 files changed

Lines changed: 185 additions & 162 deletions

File tree

docs/config/rules.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ Rules let you influence how the model behaves without changing an agent prompt.
88

99
A rule is a Markdown file. By default, rule content is rendered into the system prompt for every chat where the rule matches. Add YAML frontmatter when a rule should apply only to specific agents, models, or paths.
1010

11+
## Rules vs Skills
12+
13+
- Use rules to make ECA automatically follow project conventions, safety constraints, or guidance for matching paths.
14+
- Use [skills](./skills.md) to teach ECA reusable workflows, tools, or domain knowledge it can load on demand for specific tasks.
15+
1116
## Rule locations
1217

1318
ECA loads rules from 3 sources:

integration-test/integration/chat/commands_test.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
{:name "config" :arguments []}
3636
{:name "doctor" :arguments []}
3737
{:name "repo-map-show" :arguments []}
38+
{:name "rules" :arguments []}
3839
{:name "prompt-show" :arguments [{:name "optional-prompt"}]}
3940
{:name "subagents" :arguments []}
4041
{:name "plugins" :arguments []}

resources/META-INF/native-image/eca/eca/native-image.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Args=-J-Dborkdude.dynaload.aot=true \
3939
-H:IncludeResources=prompts/tools/skill.md \
4040
-H:IncludeResources=prompts/tools/spawn_agent.md \
4141
-H:IncludeResources=prompts/tools/write_file.md \
42+
-H:IncludeResources=prompts/tools/fetch_rule.md \
4243
-H:IncludeResources=webpages/oauth.html \
4344
-H:IncludeResources=logo.svg \
4445
-H:IncludeResources=tls/local-eca-dev-fullchain.pem \

test/eca/features/rules_test.clj

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -430,12 +430,12 @@
430430

431431
(deftest matching-path-scoped-rules-test
432432
(testing "returns every matching path-scoped rule with match details"
433-
(with-redefs [f.rules/path-scoped-rules (constantly [{:id "/workspace-a/.eca/rules/format.md"
433+
(with-redefs [f.rules/path-scoped-rules (constantly [{:id (h/file-path "/workspace-a/.eca/rules/format.md")
434434
:name "format.md"
435435
:scope :project
436436
:workspace-root (h/file-path "/workspace-a")
437437
:paths ["src/**.clj"]}
438-
{:id "/workspace-a/.eca/rules/notes.md"
438+
{:id (h/file-path "/workspace-a/.eca/rules/notes.md")
439439
:name "notes.md"
440440
:scope :project
441441
:workspace-root (h/file-path "/workspace-a")
@@ -563,26 +563,27 @@
563563
(fs/create-dirs (fs/parent target-file))
564564
(spit rule-file "---\nagent: code\nmodel: \"openai/.*\"\npaths: \"src/**/*.clj\"\nenforce:\n - read\n - modify\n---\n\nUse project Clojure style.")
565565
(spit target-file "(ns foo)")
566-
(let [workspace-root (shared/normalize-path tmp-dir)
567-
roots [{:uri (shared/filename->uri (str tmp-dir))}]
568-
rules (f.rules/path-scoped-rules {} roots "code" "openai/gpt-5.2")
569-
rule (first rules)]
570-
(is (= 1 (count rules)))
571-
(is (match? {:name "clojure.md"
572-
:scope :project
573-
:workspace-root workspace-root
574-
:content "Use project Clojure style."
575-
:agents ["code"]
576-
:models ["openai/.*"]
577-
:paths ["src/**/*.clj"]
578-
:enforce ["read" "modify"]}
579-
rule))
580-
(is (match? {:match? true
581-
:reason nil
582-
:workspace-root workspace-root
583-
:relative-path (str (fs/path "src" "nested" "foo.clj"))
584-
:matched-pattern "src/**/*.clj"}
585-
(f.rules/match-path-scoped-rule rule roots (str target-file)))))
566+
(with-redefs [config/get-env (constantly (str (fs/path tmp-dir "no-global-config")))]
567+
(let [workspace-root (shared/normalize-path tmp-dir)
568+
roots [{:uri (shared/filename->uri (str tmp-dir))}]
569+
rules (f.rules/path-scoped-rules {} roots "code" "openai/gpt-5.2")
570+
rule (first rules)]
571+
(is (= 1 (count rules)))
572+
(is (match? {:name "clojure.md"
573+
:scope :project
574+
:workspace-root workspace-root
575+
:content "Use project Clojure style."
576+
:agents ["code"]
577+
:models ["openai/.*"]
578+
:paths ["src/**/*.clj"]
579+
:enforce ["read" "modify"]}
580+
rule))
581+
(is (match? {:match? true
582+
:reason nil
583+
:workspace-root workspace-root
584+
:relative-path (str (fs/path "src" "nested" "foo.clj"))
585+
:matched-pattern "src/**/*.clj"}
586+
(f.rules/match-path-scoped-rule rule roots (str target-file))))))
586587
(finally
587588
(fs/delete-tree tmp-dir))))))
588589

0 commit comments

Comments
 (0)