agentltl-coding 0.2.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. agentltl_coding-0.2.4/LICENSE +21 -0
  2. agentltl_coding-0.2.4/PKG-INFO +129 -0
  3. agentltl_coding-0.2.4/README.md +111 -0
  4. agentltl_coding-0.2.4/pyproject.toml +39 -0
  5. agentltl_coding-0.2.4/setup.cfg +4 -0
  6. agentltl_coding-0.2.4/src/agentltl_coding/__init__.py +21 -0
  7. agentltl_coding-0.2.4/src/agentltl_coding/cli.py +482 -0
  8. agentltl_coding-0.2.4/src/agentltl_coding/edit.py +67 -0
  9. agentltl_coding-0.2.4/src/agentltl_coding/guard.py +461 -0
  10. agentltl_coding-0.2.4/src/agentltl_coding/harness.py +110 -0
  11. agentltl_coding-0.2.4/src/agentltl_coding/library/ask-before-creating-credentials.yaml +9 -0
  12. agentltl_coding-0.2.4/src/agentltl_coding/library/ask-before-discarding-work.yaml +12 -0
  13. agentltl_coding-0.2.4/src/agentltl_coding/library/ask-before-infra-changes.yaml +9 -0
  14. agentltl_coding-0.2.4/src/agentltl_coding/library/ask-before-installing.yaml +12 -0
  15. agentltl_coding-0.2.4/src/agentltl_coding/library/ask-before-reading-secret-stores.yaml +35 -0
  16. agentltl_coding-0.2.4/src/agentltl_coding/library/ask-before-recursive-delete.yaml +7 -0
  17. agentltl_coding-0.2.4/src/agentltl_coding/library/devops-secrets.yaml +10 -0
  18. agentltl_coding-0.2.4/src/agentltl_coding/library/no-claude-coauthor.yaml +11 -0
  19. agentltl_coding-0.2.4/src/agentltl_coding/library/no-codex-coauthor.yaml +11 -0
  20. agentltl_coding-0.2.4/src/agentltl_coding/library/no-copilot-coauthor.yaml +11 -0
  21. agentltl_coding-0.2.4/src/agentltl_coding/library/no-env-dumps.yaml +18 -0
  22. agentltl_coding-0.2.4/src/agentltl_coding/library/no-force-push.yaml +7 -0
  23. agentltl_coding-0.2.4/src/agentltl_coding/library/no-leaky-debug.yaml +13 -0
  24. agentltl_coding-0.2.4/src/agentltl_coding/library/no-push-to-main.yaml +7 -0
  25. agentltl_coding-0.2.4/src/agentltl_coding/library/no-secrets-in-commands.yaml +21 -0
  26. agentltl_coding-0.2.4/src/agentltl_coding/library/no-skipping-secret-scans.yaml +9 -0
  27. agentltl_coding-0.2.4/src/agentltl_coding/library/no-vibe-coauthor.yaml +11 -0
  28. agentltl_coding-0.2.4/src/agentltl_coding/library/protect-env-files.yaml +9 -0
  29. agentltl_coding-0.2.4/src/agentltl_coding/library/protect-secret-files.yaml +53 -0
  30. agentltl_coding-0.2.4/src/agentltl_coding/library/read-before-overwrite.yaml +11 -0
  31. agentltl_coding-0.2.4/src/agentltl_coding/library/subagents-on-sonnet.yaml +12 -0
  32. agentltl_coding-0.2.4/src/agentltl_coding/library/tests-before-finishing.yaml +13 -0
  33. agentltl_coding-0.2.4/src/agentltl_coding/library/tests-before-push.yaml +14 -0
  34. agentltl_coding-0.2.4/src/agentltl_coding/memory.py +390 -0
  35. agentltl_coding-0.2.4/src/agentltl_coding/pattern.py +291 -0
  36. agentltl_coding-0.2.4/src/agentltl_coding/rules.py +920 -0
  37. agentltl_coding-0.2.4/src/agentltl_coding/scan.py +54 -0
  38. agentltl_coding-0.2.4/src/agentltl_coding/session.py +149 -0
  39. agentltl_coding-0.2.4/src/agentltl_coding/store.py +123 -0
  40. agentltl_coding-0.2.4/src/agentltl_coding.egg-info/PKG-INFO +129 -0
  41. agentltl_coding-0.2.4/src/agentltl_coding.egg-info/SOURCES.txt +52 -0
  42. agentltl_coding-0.2.4/src/agentltl_coding.egg-info/dependency_links.txt +1 -0
  43. agentltl_coding-0.2.4/src/agentltl_coding.egg-info/entry_points.txt +2 -0
  44. agentltl_coding-0.2.4/src/agentltl_coding.egg-info/requires.txt +7 -0
  45. agentltl_coding-0.2.4/src/agentltl_coding.egg-info/top_level.txt +1 -0
  46. agentltl_coding-0.2.4/tests/test_finish.py +74 -0
  47. agentltl_coding-0.2.4/tests/test_golden.py +102 -0
  48. agentltl_coding-0.2.4/tests/test_guard.py +293 -0
  49. agentltl_coding-0.2.4/tests/test_harness.py +148 -0
  50. agentltl_coding-0.2.4/tests/test_library.py +189 -0
  51. agentltl_coding-0.2.4/tests/test_rules.py +241 -0
  52. agentltl_coding-0.2.4/tests/test_scan.py +27 -0
  53. agentltl_coding-0.2.4/tests/test_scripted_model.py +115 -0
  54. agentltl_coding-0.2.4/tests/test_session.py +96 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Laïla Elkoussy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentltl-coding
3
+ Version: 0.2.4
4
+ Summary: AgentLTL rules for coding agents: the AGENTLTL.yaml language, a rule library, and a guard any harness can call.
5
+ License: MIT
6
+ Project-URL: Homepage, https://agentltl.github.io
7
+ Project-URL: Source, https://github.com/AgentLTL/agentltl-coding
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: agentltl>=0.2
12
+ Requires-Dist: cli-to-tools>=0.2
13
+ Requires-Dist: pyyaml>=6.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest>=7.0; extra == "dev"
16
+ Requires-Dist: ruff>=0.4; extra == "dev"
17
+ Dynamic: license-file
18
+
19
+ # agentltl-coding
20
+
21
+ AgentLTL rules for coding agents, whatever the harness: the `AGENTLTL.yaml` rule language, a
22
+ library of tested rules, and a guard that decides each tool call before it runs.
23
+
24
+ - **Rules** in plain YAML, compiled to [AgentLTL](https://github.com/AgentLTL/AgentLTL)
25
+ formulas over the calls made so far:
26
+
27
+ ```yaml
28
+ rules:
29
+ - id: tests-before-push
30
+ before: {first: pytest, then: git_push, since: [Edit, Write]}
31
+ why: CI is slow; run the tests locally first.
32
+ mode: warn
33
+ use: [no-force-push, protect-secret-files] # from the library
34
+ ```
35
+
36
+ - **Shell commands** are checked as the structured calls of their command line
37
+ ([cli-to-tools](https://github.com/AgentLTL/cli-to-tools)): `git add . && git push -f` is
38
+ `git_add`, then `git_push {force: true}`, checked all or nothing, with redirections,
39
+ paths after `cd`, and files only known at run time accounted for.
40
+ - **Modes** map one to one onto AgentLTL severities: `block`, `warn` (the agent may insist),
41
+ `ask` (you decide), `retry` (then you decide), `stop`, `log`.
42
+ - **Memory:** each rule reads the calls of this session, or of the project across sessions.
43
+
44
+ Four harnesses are built on it: the
45
+ [Claude Code plugin](https://github.com/AgentLTL/agentltl-claude-code), the
46
+ [GitHub Copilot CLI plugin](https://github.com/AgentLTL/agentltl-copilot-cli), the
47
+ [Mistral Vibe plugin](https://github.com/AgentLTL/agentltl-mistral-vibe) and the
48
+ [Codex plugin](https://github.com/AgentLTL/agentltl-codex). The full rule
49
+ reference is on [agentltl.github.io](https://agentltl.github.io/rules/).
50
+
51
+ ## Installation
52
+
53
+ Most people want a plugin for their agent, not this library: paste the prompt from the
54
+ plugin's README into your agent ([Claude Code](https://github.com/AgentLTL/agentltl-claude-code#installation),
55
+ [Codex](https://github.com/AgentLTL/agentltl-codex#installation),
56
+ [Copilot CLI](https://github.com/AgentLTL/agentltl-copilot-cli#installation),
57
+ [Mistral Vibe](https://github.com/AgentLTL/agentltl-mistral-vibe#installation)). To build a
58
+ harness for another agent, paste this into your coding agent:
59
+
60
+ ```
61
+ Install agentltl-coding (pip install "git+https://github.com/AgentLTL/agentltl-coding.git" in a virtual environment) and read its README at https://github.com/AgentLTL/agentltl-coding, then help me write a harness for my agent.
62
+ ```
63
+
64
+ ## A harness in a few lines
65
+
66
+ ```python
67
+ from agentltl_coding import Harness, Session, configure
68
+
69
+ configure(Harness(name="my-agent", agent="the agent", user_dir="~/.my-agent",
70
+ shell_tools={"Bash": "command"},
71
+ tool_aliases={"shell": ("Bash", {"cmd": "command"}),
72
+ "write_file": ("Write", {"path": "file_path"})}))
73
+
74
+ s = Session(cwd, project_root, session_id) # one per hook call; state is on disk
75
+ if s.files: # an AGENTLTL.yaml applies here
76
+ verdict = s.pre("shell", {"cmd": "git push --force"}) # before the call
77
+ # verdict.action: "none" | "deny" | "ask" | "stop"; verdict.reason: the message
78
+ ...
79
+ s.post("shell", {"cmd": "pytest"}, call_id, output, status=0) # after it ran
80
+ s.finish() # the agent wants to stop: "block" while a `finally` rule is unmet
81
+ s.prompt() # the user wrote: lift a `stop`
82
+ ```
83
+
84
+ `Harness` says what differs between agents:
85
+
86
+ - the agent's name in messages, and where the user's `AGENTLTL.yaml` lives;
87
+ - `tool_aliases`: its tool names mapped onto the canonical ones rules use (Claude Code's
88
+ `Bash`, `Write`, `Edit`, `Read`...), so the library works unchanged (Copilot's
89
+ `create {path, file_text}` is `Write {file_path, content}`);
90
+ - which tools take shell command lines, and the permission modes in which nobody answers a
91
+ prompt;
92
+ - built-in rules of its own (`memory-first`), and where its memory lives, for
93
+ `agentltl memory scan` (`agentltl_coding.memory`).
94
+
95
+ `Session` is what the hooks do: it keeps the session and project traces on disk, holds a
96
+ `stop` until the user replies, logs interventions, and scans call output for credentials.
97
+ `Guard` underneath decides one call. `agentltl_coding.cli.main(argv, extend=...)` is the
98
+ `agentltl` command (validate, check, translate, tools, library, use, memory...), to which a
99
+ harness can add commands. A library entry with `harnesses: [claude-code]` is for that agent
100
+ only; elsewhere `use:` of it switches nothing on, so one project file serves every agent.
101
+
102
+ ## Testing a harness end to end
103
+
104
+ `e2e/` lets a plugin test itself in the real agent, without a model or an account:
105
+
106
+ - `e2e/scripted_model.py SCRIPT.json` serves the OpenAI chat-completions, OpenAI responses
107
+ and Anthropic messages formats (Mistral Vibe, Copilot CLI with a custom provider, Codex with
108
+ `wire_api = "responses"`, Claude Code with `ANTHROPIC_BASE_URL`) and answers each request with the next step of a script: tool calls,
109
+ then a final text.
110
+ - `e2e/check.py TRACE EXPECTED` checks that `agentltl trace` shows the expected refusals, in
111
+ order.
112
+ - `.github/workflows/agent-e2e.yml` is a reusable workflow: it runs the plugin's
113
+ `docker/e2e.sh` and, when that fails on a pull request (such as Dependabot's update of the
114
+ agent's version), says so on the pull request and mentions who to notify.
115
+
116
+ Each plugin pins the agent version it tests in `docker/` (a `package.json` or a
117
+ `requirements.txt`), so Dependabot proposes every new release as a pull request.
118
+
119
+ ## Develop
120
+
121
+ ```bash
122
+ pip install -e ".[dev]" "agentltl @ git+https://github.com/AgentLTL/AgentLTL.git" \
123
+ "cli-to-tools @ git+https://github.com/AgentLTL/cli-to-tools.git"
124
+ pytest -q
125
+ ```
126
+
127
+ `tests/golden/verdicts.json` records what every packaged rule, example file and formula
128
+ rule decides, step by step; a change that alters a verdict regenerates it
129
+ (`AGENTLTL_GOLDEN_UPDATE=1 pytest tests/test_golden.py`) and shows up as a reviewed diff.
@@ -0,0 +1,111 @@
1
+ # agentltl-coding
2
+
3
+ AgentLTL rules for coding agents, whatever the harness: the `AGENTLTL.yaml` rule language, a
4
+ library of tested rules, and a guard that decides each tool call before it runs.
5
+
6
+ - **Rules** in plain YAML, compiled to [AgentLTL](https://github.com/AgentLTL/AgentLTL)
7
+ formulas over the calls made so far:
8
+
9
+ ```yaml
10
+ rules:
11
+ - id: tests-before-push
12
+ before: {first: pytest, then: git_push, since: [Edit, Write]}
13
+ why: CI is slow; run the tests locally first.
14
+ mode: warn
15
+ use: [no-force-push, protect-secret-files] # from the library
16
+ ```
17
+
18
+ - **Shell commands** are checked as the structured calls of their command line
19
+ ([cli-to-tools](https://github.com/AgentLTL/cli-to-tools)): `git add . && git push -f` is
20
+ `git_add`, then `git_push {force: true}`, checked all or nothing, with redirections,
21
+ paths after `cd`, and files only known at run time accounted for.
22
+ - **Modes** map one to one onto AgentLTL severities: `block`, `warn` (the agent may insist),
23
+ `ask` (you decide), `retry` (then you decide), `stop`, `log`.
24
+ - **Memory:** each rule reads the calls of this session, or of the project across sessions.
25
+
26
+ Four harnesses are built on it: the
27
+ [Claude Code plugin](https://github.com/AgentLTL/agentltl-claude-code), the
28
+ [GitHub Copilot CLI plugin](https://github.com/AgentLTL/agentltl-copilot-cli), the
29
+ [Mistral Vibe plugin](https://github.com/AgentLTL/agentltl-mistral-vibe) and the
30
+ [Codex plugin](https://github.com/AgentLTL/agentltl-codex). The full rule
31
+ reference is on [agentltl.github.io](https://agentltl.github.io/rules/).
32
+
33
+ ## Installation
34
+
35
+ Most people want a plugin for their agent, not this library: paste the prompt from the
36
+ plugin's README into your agent ([Claude Code](https://github.com/AgentLTL/agentltl-claude-code#installation),
37
+ [Codex](https://github.com/AgentLTL/agentltl-codex#installation),
38
+ [Copilot CLI](https://github.com/AgentLTL/agentltl-copilot-cli#installation),
39
+ [Mistral Vibe](https://github.com/AgentLTL/agentltl-mistral-vibe#installation)). To build a
40
+ harness for another agent, paste this into your coding agent:
41
+
42
+ ```
43
+ Install agentltl-coding (pip install "git+https://github.com/AgentLTL/agentltl-coding.git" in a virtual environment) and read its README at https://github.com/AgentLTL/agentltl-coding, then help me write a harness for my agent.
44
+ ```
45
+
46
+ ## A harness in a few lines
47
+
48
+ ```python
49
+ from agentltl_coding import Harness, Session, configure
50
+
51
+ configure(Harness(name="my-agent", agent="the agent", user_dir="~/.my-agent",
52
+ shell_tools={"Bash": "command"},
53
+ tool_aliases={"shell": ("Bash", {"cmd": "command"}),
54
+ "write_file": ("Write", {"path": "file_path"})}))
55
+
56
+ s = Session(cwd, project_root, session_id) # one per hook call; state is on disk
57
+ if s.files: # an AGENTLTL.yaml applies here
58
+ verdict = s.pre("shell", {"cmd": "git push --force"}) # before the call
59
+ # verdict.action: "none" | "deny" | "ask" | "stop"; verdict.reason: the message
60
+ ...
61
+ s.post("shell", {"cmd": "pytest"}, call_id, output, status=0) # after it ran
62
+ s.finish() # the agent wants to stop: "block" while a `finally` rule is unmet
63
+ s.prompt() # the user wrote: lift a `stop`
64
+ ```
65
+
66
+ `Harness` says what differs between agents:
67
+
68
+ - the agent's name in messages, and where the user's `AGENTLTL.yaml` lives;
69
+ - `tool_aliases`: its tool names mapped onto the canonical ones rules use (Claude Code's
70
+ `Bash`, `Write`, `Edit`, `Read`...), so the library works unchanged (Copilot's
71
+ `create {path, file_text}` is `Write {file_path, content}`);
72
+ - which tools take shell command lines, and the permission modes in which nobody answers a
73
+ prompt;
74
+ - built-in rules of its own (`memory-first`), and where its memory lives, for
75
+ `agentltl memory scan` (`agentltl_coding.memory`).
76
+
77
+ `Session` is what the hooks do: it keeps the session and project traces on disk, holds a
78
+ `stop` until the user replies, logs interventions, and scans call output for credentials.
79
+ `Guard` underneath decides one call. `agentltl_coding.cli.main(argv, extend=...)` is the
80
+ `agentltl` command (validate, check, translate, tools, library, use, memory...), to which a
81
+ harness can add commands. A library entry with `harnesses: [claude-code]` is for that agent
82
+ only; elsewhere `use:` of it switches nothing on, so one project file serves every agent.
83
+
84
+ ## Testing a harness end to end
85
+
86
+ `e2e/` lets a plugin test itself in the real agent, without a model or an account:
87
+
88
+ - `e2e/scripted_model.py SCRIPT.json` serves the OpenAI chat-completions, OpenAI responses
89
+ and Anthropic messages formats (Mistral Vibe, Copilot CLI with a custom provider, Codex with
90
+ `wire_api = "responses"`, Claude Code with `ANTHROPIC_BASE_URL`) and answers each request with the next step of a script: tool calls,
91
+ then a final text.
92
+ - `e2e/check.py TRACE EXPECTED` checks that `agentltl trace` shows the expected refusals, in
93
+ order.
94
+ - `.github/workflows/agent-e2e.yml` is a reusable workflow: it runs the plugin's
95
+ `docker/e2e.sh` and, when that fails on a pull request (such as Dependabot's update of the
96
+ agent's version), says so on the pull request and mentions who to notify.
97
+
98
+ Each plugin pins the agent version it tests in `docker/` (a `package.json` or a
99
+ `requirements.txt`), so Dependabot proposes every new release as a pull request.
100
+
101
+ ## Develop
102
+
103
+ ```bash
104
+ pip install -e ".[dev]" "agentltl @ git+https://github.com/AgentLTL/AgentLTL.git" \
105
+ "cli-to-tools @ git+https://github.com/AgentLTL/cli-to-tools.git"
106
+ pytest -q
107
+ ```
108
+
109
+ `tests/golden/verdicts.json` records what every packaged rule, example file and formula
110
+ rule decides, step by step; a change that alters a verdict regenerates it
111
+ (`AGENTLTL_GOLDEN_UPDATE=1 pytest tests/test_golden.py`) and shows up as a reviewed diff.
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "agentltl-coding"
7
+ version = "0.2.4"
8
+ description = "AgentLTL rules for coding agents: the AGENTLTL.yaml language, a rule library, and a guard any harness can call."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ dependencies = [
13
+ "agentltl>=0.2",
14
+ "cli-to-tools>=0.2",
15
+ "pyyaml>=6.0",
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ dev = ["pytest>=7.0", "ruff>=0.4"]
20
+
21
+ [project.scripts]
22
+ agentltl = "agentltl_coding.cli:main"
23
+
24
+ [project.urls]
25
+ Homepage = "https://agentltl.github.io"
26
+ Source = "https://github.com/AgentLTL/agentltl-coding"
27
+
28
+ [tool.setuptools.packages.find]
29
+ where = ["src"]
30
+
31
+ [tool.setuptools.package-data]
32
+ agentltl_coding = ["library/*.yaml"]
33
+
34
+ [tool.pytest.ini_options]
35
+ testpaths = ["tests"]
36
+
37
+ [tool.ruff]
38
+ line-length = 100
39
+ target-version = "py310"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ """
2
+ agentltl_coding – AgentLTL rules for coding agents, whatever the harness.
3
+
4
+ The rule language of AGENTLTL.yaml (never / before / require / at_most / ltl / formula),
5
+ the library of packaged rules, the guard that decides each tool call (shell command lines
6
+ checked as their structured calls), its per-session and per-project state, and the
7
+ ``agentltl`` command, and what hooks do (:class:`Session`). A harness (the Claude Code
8
+ plugin, the GitHub Copilot CLI plugin, ...) supplies its hook I/O and a :class:`Harness`
9
+ description.
10
+ """
11
+
12
+ from .guard import Guard, Verdict, lint, translator_for
13
+ from .harness import Harness, configure, current
14
+ from .pattern import Paths
15
+ from .rules import RuleFileError, RuleSet, library, load, loads, rule_files
16
+ from .session import Session
17
+
18
+ __version__ = "0.2.4"
19
+
20
+ __all__ = ["Guard", "Harness", "Paths", "RuleFileError", "RuleSet", "Session", "Verdict", "configure",
21
+ "current", "library", "lint", "load", "loads", "rule_files", "translator_for"]