dotagents-cli 0.7.0__tar.gz → 0.7.1__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.
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/CHANGELOG.md +12 -1
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/PKG-INFO +1 -1
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/guide/commands.md +5 -1
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/guide/overlays.md +11 -2
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/AGENTS.md +9 -2
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/__init__.py +1 -1
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_context.py +47 -3
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/templates/AGENTS.md +6 -0
- dotagents_cli-0.7.1/tests/test_local_additions.py +86 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/.gitignore +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/LICENSE +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/README.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/agents.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/cli.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/commands.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/context.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/env.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/fs.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/hooks.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/merge.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/overlays.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/reference.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/resources.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/scope.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/skills.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/sources.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/api/wrappers.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/changelog.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/guide/authoring.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/guide/install.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/guide/private-sync.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/docs/index.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/install.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/mkdocs.yml +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/pyproject.toml +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/__main__.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_agents.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_env.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_fs.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_hooks.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_ignore.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_merge.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/cmds/findings.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/cmds/launch.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/hooks/preinvocation_antigravity_context.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/hooks/pretooluse_codex_env.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/hooks/sessionstart_codex_context.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/templates/PROJECT.md +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlays.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_resources.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_scope.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_skills.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_sources.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_wrappers.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/__init__.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/_common.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/about.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/build_pyz.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/context.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/env.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/init.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/overlays.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/cli/path.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/py.typed +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/_helpers.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/_shell.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/conftest.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_about.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_agents.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_api_header.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_audit_leak.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_build_pyz.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_cli_main.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_cloud_setup.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_cmds_discovery.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_context.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_env.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_env_cli_scope.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_env_format.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_env_into.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_env_regressions.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_env_safety.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_findings_cmd.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_adapters.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_cli.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_env.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_hooks.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_init.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_overlays.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_packaging.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_scope_context.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_fix_skills_adapters.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_hooks.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_ignore.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_init_base.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_last_mile.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_launch_cmd.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_mcp.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_overlay_libs.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_overlays_cli.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_overlays_command.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_path_timeout_frontmatter.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_powershell_env_hook.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_review_security.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_scope.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_sources.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_sources_uri.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_wire_hooks.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tests/test_wrappers.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tools/audit.py +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tools/cloud-setup.sh +0 -0
- {dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/tools/pyz_smoke.sh +0 -0
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.1] - 2026-10-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Your own additions to an installed overlay's file live at the same path under the
|
|
15
|
+
store root (`~/.agents/kb/RUST.md` for the rust overlay's `kb/RUST.md`, or
|
|
16
|
+
`<project>/.agents/kb/RUST.md`), where `overlays sync` never touches them. The
|
|
17
|
+
base `AGENTS.md` tells agents to read them alongside the overlay's file, and
|
|
18
|
+
`dotagents context` lists the ones it finds (JSON: `local_additions`).
|
|
19
|
+
|
|
10
20
|
## [0.7.0] - 2026-10-01
|
|
11
21
|
|
|
12
22
|
### Changed
|
|
@@ -1362,7 +1372,8 @@ Patch release: the PATH/POSIX-conversion fix above (the only change since 0.3.0)
|
|
|
1362
1372
|
affected module sources (`dotagents.cli`, `duho.presets`) to extracted temp files
|
|
1363
1373
|
before dispatch; a no-op for a plain install.
|
|
1364
1374
|
|
|
1365
|
-
[Unreleased]: https://github.com/jose-pr/dotagents/compare/v0.7.
|
|
1375
|
+
[Unreleased]: https://github.com/jose-pr/dotagents/compare/v0.7.1...HEAD
|
|
1376
|
+
[0.7.1]: https://github.com/jose-pr/dotagents/compare/v0.7.0...v0.7.1
|
|
1366
1377
|
[0.7.0]: https://github.com/jose-pr/dotagents/compare/v0.6.3...v0.7.0
|
|
1367
1378
|
[0.6.3]: https://github.com/jose-pr/dotagents/compare/v0.6.2...v0.6.3
|
|
1368
1379
|
[0.6.2]: https://github.com/jose-pr/dotagents/compare/v0.6.1...v0.6.2
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: dotagents-cli
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: The dotagents CLI: install and manage a portable ~/.agents config for AI coding agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/jose-pr/dotagents/
|
|
6
6
|
Project-URL: Repository, https://github.com/jose-pr/dotagents
|
|
@@ -216,7 +216,11 @@ Assembles the effective context an agent should load — the overlay `CONTEXT.md
|
|
|
216
216
|
and the project root's own `AGENTS.md` / `AGENTS.local.md` — minus whatever the harness already loads by itself (for Claude Code, whatever its
|
|
217
217
|
`CLAUDE.md` files really `@`-include) — and prints it to **stdout** by default
|
|
218
218
|
(POSIX convention); pass a path to write a file, or `--write-agent` to merge it into
|
|
219
|
-
each agent's own instruction file.
|
|
219
|
+
each agent's own instruction file. It ends with the skills on offer and, when there are
|
|
220
|
+
any, your **local additions to overlay files** — a store file at the same path as an
|
|
221
|
+
overlay's (`~/.agents/kb/RUST.md` for the rust overlay's `kb/RUST.md`; see
|
|
222
|
+
[Overlays](overlays.md)); `--format json` carries both as their own keys (`skills`,
|
|
223
|
+
`local_additions`).
|
|
220
224
|
|
|
221
225
|
```bash
|
|
222
226
|
dotagents context # print the active agent's context to stdout
|
|
@@ -79,8 +79,17 @@ up under `<store>/install_backup/` first. What the `.gitignore` / `.ignore` at t
|
|
|
79
79
|
overlay's root match (an ignore file in a subdirectory is just a file it ships), and
|
|
80
80
|
tool caches, belong to the install (a setup script's output, local
|
|
81
81
|
state) and are left alone; `--prune` clears them too. A `requires` added upstream is
|
|
82
|
-
installed. An installed overlay is upstream's copy, not a place for your edits
|
|
83
|
-
|
|
82
|
+
installed. An installed overlay is upstream's copy, not a place for your edits.
|
|
83
|
+
|
|
84
|
+
### Your additions to an overlay's files
|
|
85
|
+
|
|
86
|
+
Put your own text for an overlay file at the **same path under the store root**: an
|
|
87
|
+
addition to the rust overlay's `kb/RUST.md` goes in `~/.agents/kb/RUST.md` (or
|
|
88
|
+
`<project>/.agents/kb/RUST.md` for one project). `sync` never touches it, and agents
|
|
89
|
+
read it alongside the overlay's file, winning on conflict: the base `AGENTS.md` tells
|
|
90
|
+
them to, and `dotagents context` lists every addition it finds (for each `.md` an
|
|
91
|
+
overlay ships in a subdirectory other than `skills/`). Private names, local tool paths
|
|
92
|
+
and links into your own notes belong there, never in the overlay.
|
|
84
93
|
|
|
85
94
|
Removing an overlay deletes only its directory and unpublishes only the skills **it**
|
|
86
95
|
published (a copy the user edited is left alone). Its lines in `AGENTS.md`'s managed
|
|
@@ -433,7 +433,8 @@ API:
|
|
|
433
433
|
`Overlay.sort_key`, then contract-A `AGENTS.md` (every store and the project root)
|
|
434
434
|
and `AGENTS.local.md` (project store and project root), each prefixed
|
|
435
435
|
`<!-- Source: <path> -->`. Then a skills listing (`- **name** (`<SKILL.md>`):
|
|
436
|
-
description`, from each skill's leading frontmatter; a project skill wins)
|
|
436
|
+
description`, from each skill's leading frontmatter; a project skill wins), then
|
|
437
|
+
a "Local additions to overlay files" section when `local_additions` finds any.
|
|
437
438
|
`<PROJECT_ROOT>` and `<NAME_OVERLAY_ROOT>` placeholders expand; with
|
|
438
439
|
`expand_vars` so do `$NAME_OVERLAY_ROOT` / `${NAME_OVERLAY_ROOT}`. `inline`
|
|
439
440
|
appends the on-demand `.md` files the sources reference, each resolved against
|
|
@@ -441,7 +442,13 @@ API:
|
|
|
441
442
|
system source never into the project).
|
|
442
443
|
- `assemble_context_data(agent, scope, *, inline=False, expand_vars=True) -> dict`
|
|
443
444
|
— `{"agent", "harness", "sources", "context", "skills": [{"name",
|
|
444
|
-
"description", "path"}]
|
|
445
|
+
"description", "path"}], "local_additions": [{"overlay_file", "local": [...]}]}`;
|
|
446
|
+
`context` without the skills and local-additions listings.
|
|
447
|
+
- `local_additions(scope) -> list[tuple[Path, list[Path]]]` — the user's own
|
|
448
|
+
additions to installed overlay files: for each `.md` an overlay in `scope.overlays`
|
|
449
|
+
ships in a subdirectory other than `skills/`, every store's file at the same
|
|
450
|
+
relative path (`<store>/kb/RUST.md` for the overlay's `kb/RUST.md`), in
|
|
451
|
+
`scope.stores` order. A store's root files never match.
|
|
445
452
|
|
|
446
453
|
## `dotagents._agents`
|
|
447
454
|
|
|
@@ -309,6 +309,44 @@ def _get_skills_listing(scope: _scope.Scope) -> str:
|
|
|
309
309
|
return "\n\n## Available Skills (Opt-in)\n" + "\n".join(lines) + "\n"
|
|
310
310
|
|
|
311
311
|
|
|
312
|
+
def local_additions(scope: _scope.Scope) -> "list[tuple[Path, list[Path]]]":
|
|
313
|
+
"""The user's own additions to installed overlay files: for each ``.md``
|
|
314
|
+
an overlay ships in a subdirectory (``kb/``, ``flows/``, ``rules/`` ... --
|
|
315
|
+
not ``skills/``, whose published copies sit at the same path in a store),
|
|
316
|
+
every store's file at the same relative path (``~/.agents/kb/RUST.md`` for
|
|
317
|
+
an overlay's ``kb/RUST.md``), in store order. An overlay file is upstream's
|
|
318
|
+
copy, replaced by ``overlays sync``; the addition is where the user's own
|
|
319
|
+
text lives. A store's root files (``AGENTS.md``, ``env.py``) never match:
|
|
320
|
+
only a file in a subdirectory counts."""
|
|
321
|
+
stores = list(scope.stores)
|
|
322
|
+
out: "list[tuple[Path, list[Path]]]" = []
|
|
323
|
+
for overlay in scope.overlays:
|
|
324
|
+
for path in overlay.files():
|
|
325
|
+
rel = path.relative_to(overlay.path)
|
|
326
|
+
if path.suffix.lower() != ".md" or len(rel.parts) < 2 or rel.parts[0] == "skills":
|
|
327
|
+
continue
|
|
328
|
+
found = [store / rel for store in stores if (store / rel).is_file()]
|
|
329
|
+
if found:
|
|
330
|
+
out.append((path, found))
|
|
331
|
+
return out
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _get_local_additions_listing(scope: _scope.Scope) -> str:
|
|
335
|
+
"""The local additions (:func:`local_additions`) as a markdown section, or ''."""
|
|
336
|
+
additions = local_additions(scope)
|
|
337
|
+
if not additions:
|
|
338
|
+
return ""
|
|
339
|
+
lines = [
|
|
340
|
+
"- `%s` -- also read %s" % (path, ", ".join("`%s`" % p for p in found))
|
|
341
|
+
for path, found in additions
|
|
342
|
+
]
|
|
343
|
+
return (
|
|
344
|
+
"\n\n## Local additions to overlay files\n"
|
|
345
|
+
"The user's own additions: read each with the overlay file it extends; it wins on conflict.\n"
|
|
346
|
+
+ "\n".join(lines) + "\n"
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
|
|
312
350
|
def _resolve_and_filter_sources(
|
|
313
351
|
agent: _agents.Agent, scope: _scope.Scope
|
|
314
352
|
) -> "tuple[list[tuple[str, Path, Path | None]], list[Path]]":
|
|
@@ -424,6 +462,7 @@ def assemble_context(
|
|
|
424
462
|
if not source_paths:
|
|
425
463
|
return ""
|
|
426
464
|
text += _get_skills_listing(scope)
|
|
465
|
+
text += _get_local_additions_listing(scope)
|
|
427
466
|
return text
|
|
428
467
|
|
|
429
468
|
|
|
@@ -440,11 +479,12 @@ def assemble_context_data(
|
|
|
440
479
|
"sources": [<absolute source path>, ...], # after harness subtraction
|
|
441
480
|
"context": <assembled markdown text, minus the skills listing>,
|
|
442
481
|
"skills": [{"name": ..., "description": ..., "path": <SKILL.md>}, ...],
|
|
482
|
+
"local_additions": [{"overlay_file": ..., "local": [<path>, ...]}, ...],
|
|
443
483
|
}
|
|
444
484
|
``context`` is the same assembled(+inlined, with ``inline=True``) text the
|
|
445
|
-
markdown format emits, but WITHOUT the skills
|
|
446
|
-
their own structured
|
|
447
|
-
|
|
485
|
+
markdown format emits, but WITHOUT the skills and local-additions listings
|
|
486
|
+
appended -- both are their own structured fields so a consumer can render
|
|
487
|
+
them separately."""
|
|
448
488
|
text, source_paths = _assemble(agent, scope, inline, expand_vars)
|
|
449
489
|
|
|
450
490
|
skills = [
|
|
@@ -457,4 +497,8 @@ def assemble_context_data(
|
|
|
457
497
|
"sources": source_paths,
|
|
458
498
|
"context": text,
|
|
459
499
|
"skills": skills,
|
|
500
|
+
"local_additions": [
|
|
501
|
+
{"overlay_file": str(path), "local": [str(p) for p in found]}
|
|
502
|
+
for path, found in local_additions(scope)
|
|
503
|
+
],
|
|
460
504
|
}
|
{dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/templates/AGENTS.md
RENAMED
|
@@ -16,6 +16,12 @@ Startup: annotate that you read `{{AGENTS_MD}}`.
|
|
|
16
16
|
config). These files say what lives there and how to work in it, so reading them
|
|
17
17
|
first is cheaper than rediscovering it from the source. How `.agents/` is
|
|
18
18
|
populated — real directory, symlink, committed or not — is yours to decide.
|
|
19
|
+
- **Local additions to overlay files**: an overlay file (`$<NAME>_OVERLAY_ROOT/<path>`)
|
|
20
|
+
is upstream's copy, and `dotagents overlays sync` replaces it. The user's own
|
|
21
|
+
additions live at the same `<path>` under this config directory and the project's
|
|
22
|
+
`.agents/`: when you read an overlay file, read those too — they extend it and win on
|
|
23
|
+
conflict (`dotagents context` lists the ones it finds). Never write user-specific text
|
|
24
|
+
into an overlay file; put it there.
|
|
19
25
|
- **Global-config misses**: if these instructions caused a mistake or rework, or you
|
|
20
26
|
have an improvement idea, record it and move on — don't edit the config:
|
|
21
27
|
`dotagents findings add -g "<one line>" -b "<what happened, evidence>"`. Read the
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""The user's own additions to installed overlay files: a store file at the
|
|
2
|
+
same relative path as an overlay's (``~/.agents/kb/RUST.md`` for the rust
|
|
3
|
+
overlay's ``kb/RUST.md``). `overlays sync` replaces the overlay's copy, so this
|
|
4
|
+
is where the user's text lives; `dotagents context` lists what it finds, and
|
|
5
|
+
the base AGENTS.md tells every agent to read them."""
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from dotagents import _agents, _context
|
|
9
|
+
from dotagents._resources import BASE_PROJECT_TEMPLATE, BASE_ROOT, base_agents_text
|
|
10
|
+
from dotagents._scope import Scope
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _write(path, text="x\n"):
|
|
14
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
15
|
+
path.write_text(text, encoding="utf-8")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _world(tmp_path):
|
|
19
|
+
user = tmp_path / "user"
|
|
20
|
+
project = tmp_path / "proj"
|
|
21
|
+
rust = user / "overlays" / "rust"
|
|
22
|
+
_write(rust / "overlay.toml", 'name = "rust"\n')
|
|
23
|
+
_write(rust / "CONTEXT.md", "RUST-CONTEXT\n")
|
|
24
|
+
_write(rust / "kb" / "RUST.md", "upstream rust\n")
|
|
25
|
+
_write(rust / "kb" / "NOTES.md", "no addition for this one\n")
|
|
26
|
+
_write(rust / "flows" / "deep" / "STEP.md", "upstream step\n")
|
|
27
|
+
_write(rust / "skills" / "rs" / "SKILL.md", "---\nname: rs\ndescription: d\n---\n")
|
|
28
|
+
_write(rust / "kb" / "data.json", "{}\n")
|
|
29
|
+
_write(rust / "AGENTS.md", "an overlay-root file\n")
|
|
30
|
+
_write(user / "AGENTS.md", "# user\n")
|
|
31
|
+
_write(user / "kb" / "RUST.md", "my own note\n")
|
|
32
|
+
_write(user / "flows" / "deep" / "STEP.md", "my step\n")
|
|
33
|
+
_write(user / "skills" / "rs" / "SKILL.md", "---\nname: rs\ndescription: d\n---\n") # a published copy
|
|
34
|
+
_write(user / "kb" / "data.json", "{}\n")
|
|
35
|
+
_write(project / ".agents" / "kb" / "RUST.md", "a project note\n")
|
|
36
|
+
return user, project
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _scope(user, project, global_scope=False):
|
|
40
|
+
return Scope.of(agents_dir=user, project_root=project, global_scope=global_scope)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_additions_are_matched_by_relative_path_in_every_store(tmp_path):
|
|
44
|
+
user, project = _world(tmp_path)
|
|
45
|
+
found = {p.relative_to(user / "overlays" / "rust").as_posix(): [q for q in qs]
|
|
46
|
+
for p, qs in _context.local_additions(_scope(user, project))}
|
|
47
|
+
assert sorted(found) == ["flows/deep/STEP.md", "kb/RUST.md"], (
|
|
48
|
+
"only .md files in a subdirectory, never skills/ (published copies) or the root"
|
|
49
|
+
)
|
|
50
|
+
assert found["kb/RUST.md"] == [user / "kb" / "RUST.md", project / ".agents" / "kb" / "RUST.md"]
|
|
51
|
+
user_only = {p.name for p, _ in _context.local_additions(_scope(user, project, True))}
|
|
52
|
+
assert user_only == {"RUST.md", "STEP.md"}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_context_lists_them_and_json_carries_them(tmp_path):
|
|
56
|
+
user, project = _world(tmp_path)
|
|
57
|
+
codex = _agents.CodexAgent()
|
|
58
|
+
text = _context.assemble_context(codex, _scope(user, project))
|
|
59
|
+
assert "## Local additions to overlay files" in text
|
|
60
|
+
assert str(user / "kb" / "RUST.md") in text and str(project / ".agents" / "kb" / "RUST.md") in text
|
|
61
|
+
assert "my own note" not in text, "listed, not inlined"
|
|
62
|
+
data = _context.assemble_context_data(codex, _scope(user, project))
|
|
63
|
+
assert "Local additions" not in data["context"]
|
|
64
|
+
entries = {e["overlay_file"]: e["local"] for e in data["local_additions"]}
|
|
65
|
+
assert entries[str(user / "overlays" / "rust" / "kb" / "RUST.md")] == [
|
|
66
|
+
str(user / "kb" / "RUST.md"), str(project / ".agents" / "kb" / "RUST.md"),
|
|
67
|
+
]
|
|
68
|
+
json.dumps(data)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_no_section_without_additions(tmp_path):
|
|
72
|
+
user = tmp_path / "user"
|
|
73
|
+
_write(user / "overlays" / "rust" / "overlay.toml", 'name = "rust"\n')
|
|
74
|
+
_write(user / "overlays" / "rust" / "CONTEXT.md", "RUST-CONTEXT\n")
|
|
75
|
+
_write(user / "overlays" / "rust" / "kb" / "RUST.md", "upstream\n")
|
|
76
|
+
_write(user / "AGENTS.md", "# user\n")
|
|
77
|
+
text = _context.assemble_context(_agents.CodexAgent(), Scope.of(agents_dir=user, global_scope=True))
|
|
78
|
+
assert "RUST-CONTEXT" in text and "Local additions" not in text
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_the_base_rule_is_in_the_user_block_only(tmp_path):
|
|
82
|
+
user_block = base_agents_text(BASE_ROOT, tmp_path)
|
|
83
|
+
assert "**Local additions to overlay files**" in user_block
|
|
84
|
+
assert "`dotagents context` lists the ones it finds" in user_block
|
|
85
|
+
project = (BASE_ROOT / BASE_PROJECT_TEMPLATE).read_text(encoding="utf-8")
|
|
86
|
+
assert "Local additions" not in project, "a project session reads the user block too"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/cmds/findings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dotagents_cli-0.7.0 → dotagents_cli-0.7.1}/src/dotagents/_overlay/dotagents/templates/PROJECT.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|