dotai-cli 0.6.0__tar.gz → 0.7.0__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.
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/.gitignore +3 -0
- dotai_cli-0.7.0/CHANGELOG.md +65 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/PKG-INFO +43 -11
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/README.md +41 -9
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/pyproject.toml +1 -1
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/__init__.py +1 -1
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/agents.py +4 -0
- dotai_cli-0.7.0/src/dotai/catalog.py +67 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/agents_cmd.py +2 -1
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/rules_cmd.py +8 -3
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/sync_cmd.py +25 -26
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/context.py +82 -61
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/insights.py +17 -19
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/maintenance.py +8 -6
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/models.py +25 -8
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/rules.py +5 -19
- dotai_cli-0.7.0/src/dotai/scope.py +91 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/skills.py +10 -11
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/sync.py +27 -80
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_agents.py +15 -0
- dotai_cli-0.7.0/tests/test_catalog.py +288 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_context.py +87 -3
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_insights.py +22 -1
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_skills.py +50 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_sync.py +19 -2
- dotai_cli-0.6.0/CHANGELOG.md +0 -34
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/.github/workflows/ci.yml +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/.github/workflows/publish.yml +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/LICENSE +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/PRODUCT.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/rdc.yaml +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/__main__.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/__init__.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/__main__.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/insights_cmd.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/prefs_cmd.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/roles_cmd.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/cli/skills_cmd.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/converter.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/import_agent.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/preferences.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/roles.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/architect.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/debugger.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/founder.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/mentor.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/product-manager.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/qa.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/reviewer.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/security.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/ship.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/roles/writer.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/careful.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/commit-helper.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/compress.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/context-dump.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/investigate.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/learn.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/parallel-work.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/plan.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/review.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/scaffold.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/ship.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/techdebt.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/seed/skills/verify.md +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/store.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/tools/__init__.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/tools/base.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/tools/registry.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/utils.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/src/dotai/vet.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/__init__.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/conftest.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_converter.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_import_agent.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_maintenance.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_models.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_preferences.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_roles.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_rules.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_store.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_utils.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/tests/test_vet.py +0 -0
- {dotai_cli-0.6.0 → dotai_cli-0.7.0}/uv.lock +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.7.0 — 2026-11-04
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Share project discovery and override handling between context resolution and
|
|
10
|
+
primers, including nested directories, custom knowledge paths, and disabled
|
|
11
|
+
local overrides. Unrelated registered projects are excluded.
|
|
12
|
+
- Deliver full universal rule bodies and freeform conventions in resolved
|
|
13
|
+
context. Compact primers replace individual scoped-rule listings with a count
|
|
14
|
+
and resolver pointer.
|
|
15
|
+
- Load active general preferences by default, advertise other active domains,
|
|
16
|
+
and honor explicitly requested packs independently of domain selection.
|
|
17
|
+
- Preserve complete bodies when loading existing dotai skills while retaining
|
|
18
|
+
structured Python fields and identifying the source directory.
|
|
19
|
+
- Report file-scope facts separately from resolution status; missing files keep
|
|
20
|
+
a resolution provisional whenever scoped rules exist.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Match inherited rule globs from nested working directories and preserve hidden
|
|
25
|
+
and symlinked file names during matching.
|
|
26
|
+
- Avoid receipt temporary-file collisions and tolerate concurrent history
|
|
27
|
+
pruning at the retention limit.
|
|
28
|
+
- Pluralize the compact primer's file-scoped rule count.
|
|
29
|
+
- Treat a rule as universal only when every glob is a catch-all, so one
|
|
30
|
+
specific glob keeps the rule file-scoped.
|
|
31
|
+
- Search, `rules`, project audits, scoped insights, and project skill sync
|
|
32
|
+
read the same ancestor catalog as context. Unrelated projects stay out.
|
|
33
|
+
|
|
34
|
+
## 0.6.0 — 2026-07-17
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- `dotai learn --directive` for proactive engineering standards, taste, and
|
|
39
|
+
guardrails without requiring a prior mistake.
|
|
40
|
+
- `dotai insights` for deterministic local delivery evidence: resolution health,
|
|
41
|
+
selection counts, last use, rule-summary exposure, and unused knowledge.
|
|
42
|
+
- Bounded metadata-only receipt history, retaining the latest 500 resolutions
|
|
43
|
+
per agent.
|
|
44
|
+
- `PRODUCT.md` defining dotai as portable engineering judgment for coding agents.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- Repositioned the CLI and documentation around developer-controlled engineering
|
|
49
|
+
judgment rather than universal context.
|
|
50
|
+
- `dotai sync` now has one repository-safe behavior: local context outside the
|
|
51
|
+
worktree.
|
|
52
|
+
- `dotai primer` now always emits the compact bootstrap.
|
|
53
|
+
- `dotai search` reads live knowledge instead of a cached index.
|
|
54
|
+
- `dotai install` is the single entry point for supported external skill formats.
|
|
55
|
+
|
|
56
|
+
### Removed
|
|
57
|
+
|
|
58
|
+
- Commands: `watch`, `detach`, `index`, `tree`, `prompt`, `role`, `convert`, and
|
|
59
|
+
`import-plugin`.
|
|
60
|
+
- Shared/full/agent-specific sync controls and primer session overlays.
|
|
61
|
+
- Freeform `dotai learn --append-md` capture.
|
|
62
|
+
- The cached knowledge-tree model and `watchdog` dependency.
|
|
63
|
+
|
|
64
|
+
This release intentionally breaks pre-1.0 CLI compatibility to keep one clear,
|
|
65
|
+
local-first product path.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: dotai-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Portable engineering judgment for coding agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/dawalama/dotai
|
|
6
6
|
Project-URL: Repository, https://github.com/dawalama/dotai
|
|
@@ -150,7 +150,7 @@ dotai sync
|
|
|
150
150
|
|
|
151
151
|
Local context storage does not, by itself, make an agent load the context. Until an agent adapter is configured, use `dotai primer --path .` to print a compact bootstrap for pasting or piping into your agent.
|
|
152
152
|
|
|
153
|
-
dotai uses progressive disclosure to keep prompts small.
|
|
153
|
+
dotai uses progressive disclosure to keep prompts small. Compact primers include complete universal directives, a count of file-scoped rules, and role/skill catalogs. Unrelated scoped rules are not listed individually. Expand what a task needs:
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
156
|
# Expand rules matching the affected files
|
|
@@ -165,6 +165,26 @@ dotai context --path . --skill run_review
|
|
|
165
165
|
|
|
166
166
|
Selection is deterministic: file globs, explicit context tags, active preference domains, and named skills or roles. dotai does not guess from semantic similarity. Every expanded item includes the reason it was selected.
|
|
167
167
|
|
|
168
|
+
`context` and `primer` share the same scoped catalog. Within a Git worktree,
|
|
169
|
+
dotai loads global knowledge and applicable ancestor knowledge directories down
|
|
170
|
+
to the invocation directory, honoring registered custom `ai_dir` paths. Outside
|
|
171
|
+
Git, discovery stops at the nearest registered project, or uses only the supplied
|
|
172
|
+
directory when it is unregistered. Unrelated registered projects are not read.
|
|
173
|
+
Local definitions override inherited items with the same ID; a disabled local
|
|
174
|
+
rule masks the inherited definition. A project's `disabled_rules` list excludes
|
|
175
|
+
global definitions while allowing explicit local replacements.
|
|
176
|
+
|
|
177
|
+
Affected files are relative to `--path` (absolute paths also work). Project rule
|
|
178
|
+
globs are relative to the directory owning that project's knowledge; global
|
|
179
|
+
globs use the repository or project root. Matching uses logical file paths,
|
|
180
|
+
including symlink names. The host remains responsible for filesystem permissions.
|
|
181
|
+
|
|
182
|
+
The resolver includes complete universal rule bodies and applicable `rules.md`
|
|
183
|
+
notes. Active `general` preference packs load by default. Other active domains
|
|
184
|
+
are listed without their bodies; select one with `--domain cli`, or load a named
|
|
185
|
+
pack directly with `--with-prefs <id>` regardless of its domain. Explicit packs
|
|
186
|
+
remain subject to scope and enabled state.
|
|
187
|
+
|
|
168
188
|
### Automatic delivery with Claude Code
|
|
169
189
|
|
|
170
190
|
The resolver is infrastructure; you should not have to type `dotai context`
|
|
@@ -190,11 +210,11 @@ dotai context for substantial development work, after affected files are known,
|
|
|
190
210
|
and to avoid repeated calls when the task has not changed. Repository and
|
|
191
211
|
organization instructions remain authoritative.
|
|
192
212
|
|
|
193
|
-
|
|
194
|
-
maintenance, and release work, a resolution without `--files` is explicitly
|
|
213
|
+
When file-scoped rules exist, or a selected workflow requires files, a resolution without `--files` is explicitly
|
|
195
214
|
marked provisional. Claude must resolve again after discovering the affected
|
|
196
215
|
files. `dotai agent last claude` reports whether the latest resolution is
|
|
197
|
-
`provisional` or `
|
|
216
|
+
`provisional` or `resolved`, and whether file scope was provided or remains
|
|
217
|
+
unknown. Supplied files do not prove that every affected file was discovered.
|
|
198
218
|
|
|
199
219
|
The adapter does not modify repositories, install a persistent process, or use
|
|
200
220
|
MCP. Existing personal Claude instructions are preserved. To remove only
|
|
@@ -225,7 +245,7 @@ dotai insights --json
|
|
|
225
245
|
```
|
|
226
246
|
|
|
227
247
|
The report shows complete versus provisional resolutions, selection counts,
|
|
228
|
-
last-selected timestamps, universal
|
|
248
|
+
last-selected timestamps, universal-rule exposure, and enabled items
|
|
229
249
|
that have never been selected in the current window. Selection proves delivery,
|
|
230
250
|
not compliance: dotai cannot claim that an agent followed an instruction merely
|
|
231
251
|
because it received it.
|
|
@@ -448,6 +468,10 @@ Hard rules always take precedence if they conflict.
|
|
|
448
468
|
|
|
449
469
|
### Searching your knowledge
|
|
450
470
|
|
|
471
|
+
Search reads the same scoped catalog as `dotai context`. From a project, it
|
|
472
|
+
includes global knowledge and applicable ancestor directories, and it skips
|
|
473
|
+
unrelated registered projects. Pass `--path` to search another directory.
|
|
474
|
+
|
|
451
475
|
```bash
|
|
452
476
|
# Search by keyword
|
|
453
477
|
dotai search "useEffect"
|
|
@@ -590,9 +614,16 @@ Analyze the current branch's diff for issues that tests don't catch.
|
|
|
590
614
|
4. Generate a structured report with file:line references
|
|
591
615
|
```
|
|
592
616
|
|
|
617
|
+
When loading existing dotai skill files, dotai preserves the complete Markdown
|
|
618
|
+
body for execution, including custom sections, nested steps, and code blocks.
|
|
619
|
+
Extracted fields remain available to Python consumers; rendering uses the
|
|
620
|
+
preserved body and identifies the source directory for relative resources.
|
|
621
|
+
Native-format import still uses the existing converter; migration to native
|
|
622
|
+
`SKILL.md` packages and preservation of host-specific metadata are separate work.
|
|
623
|
+
|
|
593
624
|
### Gotchas
|
|
594
625
|
|
|
595
|
-
Skills should document **common failure points** — things that push the agent out of its normal way of thinking. Gotchas
|
|
626
|
+
Skills should document **common failure points** — things that push the agent out of its normal way of thinking. Gotchas in the Markdown body remain verbatim. Frontmatter gotchas and programmatically constructed gotcha fields are rendered with warning markers.
|
|
596
627
|
|
|
597
628
|
### Conditional Contexts
|
|
598
629
|
|
|
@@ -712,13 +743,14 @@ dotai toggle no-useeffect --off --project my-legacy-app
|
|
|
712
743
|
dotai toggle no-useeffect --on
|
|
713
744
|
```
|
|
714
745
|
|
|
715
|
-
Synced local context contains a compact bootstrap: universal rule
|
|
746
|
+
Synced local context contains a compact bootstrap: full universal directives, a scoped-rule count, and preference, role, and skill catalogs. Use `dotai context` to expand relevant material on demand.
|
|
716
747
|
|
|
717
748
|
## Agent Sync
|
|
718
749
|
|
|
719
750
|
`dotai sync` prepares repository-safe local context with:
|
|
720
751
|
|
|
721
|
-
- **
|
|
752
|
+
- **Complete universal structured directives** (always visible)
|
|
753
|
+
- **A count and resolver pointer for file-scoped rules**
|
|
722
754
|
- **Pointers to freeform `rules.md` conventions**
|
|
723
755
|
- **Role and skill catalogs** (names, triggers, categories — not full workflows)
|
|
724
756
|
Context is always written outside the worktree. Team instructions take precedence over personal dotai rules and preferences. dotai does not attempt unreliable keyword-based conflict resolution; the generated context tells the agent to ignore conflicting personal guidance and ask when a disagreement is ambiguous.
|
|
@@ -855,7 +887,7 @@ dotai install <source> [-s skill] # Install skills from git repo or local p
|
|
|
855
887
|
dotai install --update [-s skill] [--skip-vet] # Vetted refresh from recorded sources
|
|
856
888
|
dotai remove <skill> [-p project] # Remove an installed skill
|
|
857
889
|
dotai new-skill <name> [-t trigger] # Create a new skill from template
|
|
858
|
-
dotai search "query" [--type t] [--tag] # Search
|
|
890
|
+
dotai search "query" [--type t] [--tag] [--path .] # Search knowledge for a directory
|
|
859
891
|
```
|
|
860
892
|
|
|
861
893
|
## Philosophy
|
|
@@ -122,7 +122,7 @@ dotai sync
|
|
|
122
122
|
|
|
123
123
|
Local context storage does not, by itself, make an agent load the context. Until an agent adapter is configured, use `dotai primer --path .` to print a compact bootstrap for pasting or piping into your agent.
|
|
124
124
|
|
|
125
|
-
dotai uses progressive disclosure to keep prompts small.
|
|
125
|
+
dotai uses progressive disclosure to keep prompts small. Compact primers include complete universal directives, a count of file-scoped rules, and role/skill catalogs. Unrelated scoped rules are not listed individually. Expand what a task needs:
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
128
|
# Expand rules matching the affected files
|
|
@@ -137,6 +137,26 @@ dotai context --path . --skill run_review
|
|
|
137
137
|
|
|
138
138
|
Selection is deterministic: file globs, explicit context tags, active preference domains, and named skills or roles. dotai does not guess from semantic similarity. Every expanded item includes the reason it was selected.
|
|
139
139
|
|
|
140
|
+
`context` and `primer` share the same scoped catalog. Within a Git worktree,
|
|
141
|
+
dotai loads global knowledge and applicable ancestor knowledge directories down
|
|
142
|
+
to the invocation directory, honoring registered custom `ai_dir` paths. Outside
|
|
143
|
+
Git, discovery stops at the nearest registered project, or uses only the supplied
|
|
144
|
+
directory when it is unregistered. Unrelated registered projects are not read.
|
|
145
|
+
Local definitions override inherited items with the same ID; a disabled local
|
|
146
|
+
rule masks the inherited definition. A project's `disabled_rules` list excludes
|
|
147
|
+
global definitions while allowing explicit local replacements.
|
|
148
|
+
|
|
149
|
+
Affected files are relative to `--path` (absolute paths also work). Project rule
|
|
150
|
+
globs are relative to the directory owning that project's knowledge; global
|
|
151
|
+
globs use the repository or project root. Matching uses logical file paths,
|
|
152
|
+
including symlink names. The host remains responsible for filesystem permissions.
|
|
153
|
+
|
|
154
|
+
The resolver includes complete universal rule bodies and applicable `rules.md`
|
|
155
|
+
notes. Active `general` preference packs load by default. Other active domains
|
|
156
|
+
are listed without their bodies; select one with `--domain cli`, or load a named
|
|
157
|
+
pack directly with `--with-prefs <id>` regardless of its domain. Explicit packs
|
|
158
|
+
remain subject to scope and enabled state.
|
|
159
|
+
|
|
140
160
|
### Automatic delivery with Claude Code
|
|
141
161
|
|
|
142
162
|
The resolver is infrastructure; you should not have to type `dotai context`
|
|
@@ -162,11 +182,11 @@ dotai context for substantial development work, after affected files are known,
|
|
|
162
182
|
and to avoid repeated calls when the task has not changed. Repository and
|
|
163
183
|
organization instructions remain authoritative.
|
|
164
184
|
|
|
165
|
-
|
|
166
|
-
maintenance, and release work, a resolution without `--files` is explicitly
|
|
185
|
+
When file-scoped rules exist, or a selected workflow requires files, a resolution without `--files` is explicitly
|
|
167
186
|
marked provisional. Claude must resolve again after discovering the affected
|
|
168
187
|
files. `dotai agent last claude` reports whether the latest resolution is
|
|
169
|
-
`provisional` or `
|
|
188
|
+
`provisional` or `resolved`, and whether file scope was provided or remains
|
|
189
|
+
unknown. Supplied files do not prove that every affected file was discovered.
|
|
170
190
|
|
|
171
191
|
The adapter does not modify repositories, install a persistent process, or use
|
|
172
192
|
MCP. Existing personal Claude instructions are preserved. To remove only
|
|
@@ -197,7 +217,7 @@ dotai insights --json
|
|
|
197
217
|
```
|
|
198
218
|
|
|
199
219
|
The report shows complete versus provisional resolutions, selection counts,
|
|
200
|
-
last-selected timestamps, universal
|
|
220
|
+
last-selected timestamps, universal-rule exposure, and enabled items
|
|
201
221
|
that have never been selected in the current window. Selection proves delivery,
|
|
202
222
|
not compliance: dotai cannot claim that an agent followed an instruction merely
|
|
203
223
|
because it received it.
|
|
@@ -420,6 +440,10 @@ Hard rules always take precedence if they conflict.
|
|
|
420
440
|
|
|
421
441
|
### Searching your knowledge
|
|
422
442
|
|
|
443
|
+
Search reads the same scoped catalog as `dotai context`. From a project, it
|
|
444
|
+
includes global knowledge and applicable ancestor directories, and it skips
|
|
445
|
+
unrelated registered projects. Pass `--path` to search another directory.
|
|
446
|
+
|
|
423
447
|
```bash
|
|
424
448
|
# Search by keyword
|
|
425
449
|
dotai search "useEffect"
|
|
@@ -562,9 +586,16 @@ Analyze the current branch's diff for issues that tests don't catch.
|
|
|
562
586
|
4. Generate a structured report with file:line references
|
|
563
587
|
```
|
|
564
588
|
|
|
589
|
+
When loading existing dotai skill files, dotai preserves the complete Markdown
|
|
590
|
+
body for execution, including custom sections, nested steps, and code blocks.
|
|
591
|
+
Extracted fields remain available to Python consumers; rendering uses the
|
|
592
|
+
preserved body and identifies the source directory for relative resources.
|
|
593
|
+
Native-format import still uses the existing converter; migration to native
|
|
594
|
+
`SKILL.md` packages and preservation of host-specific metadata are separate work.
|
|
595
|
+
|
|
565
596
|
### Gotchas
|
|
566
597
|
|
|
567
|
-
Skills should document **common failure points** — things that push the agent out of its normal way of thinking. Gotchas
|
|
598
|
+
Skills should document **common failure points** — things that push the agent out of its normal way of thinking. Gotchas in the Markdown body remain verbatim. Frontmatter gotchas and programmatically constructed gotcha fields are rendered with warning markers.
|
|
568
599
|
|
|
569
600
|
### Conditional Contexts
|
|
570
601
|
|
|
@@ -684,13 +715,14 @@ dotai toggle no-useeffect --off --project my-legacy-app
|
|
|
684
715
|
dotai toggle no-useeffect --on
|
|
685
716
|
```
|
|
686
717
|
|
|
687
|
-
Synced local context contains a compact bootstrap: universal rule
|
|
718
|
+
Synced local context contains a compact bootstrap: full universal directives, a scoped-rule count, and preference, role, and skill catalogs. Use `dotai context` to expand relevant material on demand.
|
|
688
719
|
|
|
689
720
|
## Agent Sync
|
|
690
721
|
|
|
691
722
|
`dotai sync` prepares repository-safe local context with:
|
|
692
723
|
|
|
693
|
-
- **
|
|
724
|
+
- **Complete universal structured directives** (always visible)
|
|
725
|
+
- **A count and resolver pointer for file-scoped rules**
|
|
694
726
|
- **Pointers to freeform `rules.md` conventions**
|
|
695
727
|
- **Role and skill catalogs** (names, triggers, categories — not full workflows)
|
|
696
728
|
Context is always written outside the worktree. Team instructions take precedence over personal dotai rules and preferences. dotai does not attempt unreliable keyword-based conflict resolution; the generated context tells the agent to ignore conflicting personal guidance and ask when a disagreement is ambiguous.
|
|
@@ -827,7 +859,7 @@ dotai install <source> [-s skill] # Install skills from git repo or local p
|
|
|
827
859
|
dotai install --update [-s skill] [--skip-vet] # Vetted refresh from recorded sources
|
|
828
860
|
dotai remove <skill> [-p project] # Remove an installed skill
|
|
829
861
|
dotai new-skill <name> [-t trigger] # Create a new skill from template
|
|
830
|
-
dotai search "query" [--type t] [--tag] # Search
|
|
862
|
+
dotai search "query" [--type t] [--tag] [--path .] # Search knowledge for a directory
|
|
831
863
|
```
|
|
832
864
|
|
|
833
865
|
## Philosophy
|
|
@@ -30,6 +30,10 @@ resolution replaces the provisional one and loads file-scoped rules. Do not call
|
|
|
30
30
|
dotai for casual conversation, simple factual questions, or repeatedly after a
|
|
31
31
|
complete file-aware resolution unless the task or affected files materially change.
|
|
32
32
|
|
|
33
|
+
The result lists active preference domains that were not loaded. Add
|
|
34
|
+
`--domain <relevant domain>` when one applies, or `--with-prefs <id>` when the user
|
|
35
|
+
requests a specific pack. Active general preferences load by default.
|
|
36
|
+
|
|
33
37
|
When the user explicitly invokes a dotai workflow such as `/run_review`, load it
|
|
34
38
|
with `{command} context --agent claude --path . --skill run_review`. Treat dotai preferences as soft
|
|
35
39
|
taste only; team rules, security constraints, and user instructions take precedence.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""One scoped view of knowledge for context resolution and exports."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .models import GlobalConfig, PreferencePack, Role, Rule, Skill
|
|
7
|
+
from .preferences import load_active_pack_ids, load_preferences_from_dir
|
|
8
|
+
from .roles import load_roles_from_dir
|
|
9
|
+
from .rules import load_rules_from_dir, load_rules_md
|
|
10
|
+
from .scope import KnowledgeScope, resolve_scope
|
|
11
|
+
from .skills import load_skills_from_dir
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class FreeformNote:
|
|
16
|
+
scope: str
|
|
17
|
+
path: Path
|
|
18
|
+
body: str
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class KnowledgeCatalog:
|
|
23
|
+
scope: KnowledgeScope
|
|
24
|
+
rules: list[Rule]
|
|
25
|
+
skills: list[Skill]
|
|
26
|
+
roles: list[Role]
|
|
27
|
+
preferences: list[PreferencePack]
|
|
28
|
+
notes: list[FreeformNote]
|
|
29
|
+
rule_roots: dict[str, Path | None]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def load_catalog(
|
|
33
|
+
config: GlobalConfig,
|
|
34
|
+
project_name: str | None = None,
|
|
35
|
+
project_path: Path | None = None,
|
|
36
|
+
extra_prefs: list[str] | None = None,
|
|
37
|
+
) -> KnowledgeCatalog:
|
|
38
|
+
scope = resolve_scope(config, project_name, project_path)
|
|
39
|
+
rules: dict[str, Rule] = {}
|
|
40
|
+
skills: dict[str, Skill] = {}
|
|
41
|
+
roles: dict[str, Role] = {}
|
|
42
|
+
preferences: dict[str, PreferencePack] = {}
|
|
43
|
+
notes: list[FreeformNote] = []
|
|
44
|
+
rule_roots: dict[str, Path | None] = {}
|
|
45
|
+
for entry in scope.directories:
|
|
46
|
+
label, directory = entry.scope, entry.path
|
|
47
|
+
for rule in load_rules_from_dir(directory / "rules", label):
|
|
48
|
+
if directory != scope.directories[0].path or rule.id not in scope.disabled_rules:
|
|
49
|
+
rules[rule.id] = rule
|
|
50
|
+
rule_roots[rule.id] = entry.root_path
|
|
51
|
+
skills.update((s.id, s) for s in load_skills_from_dir(directory / "skills", label))
|
|
52
|
+
roles.update((r.id, r) for r in load_roles_from_dir(directory / "roles", label))
|
|
53
|
+
preferences.update((p.id, p) for p in load_preferences_from_dir(directory / "preferences", label))
|
|
54
|
+
body = load_rules_md(directory)
|
|
55
|
+
if body:
|
|
56
|
+
notes.append(FreeformNote(label, directory / "rules.md", body))
|
|
57
|
+
|
|
58
|
+
active = list(extra_prefs or [])
|
|
59
|
+
for entry in reversed(scope.directories):
|
|
60
|
+
active.extend(load_active_pack_ids(entry.path))
|
|
61
|
+
active = list(dict.fromkeys(active))
|
|
62
|
+
return KnowledgeCatalog(
|
|
63
|
+
scope, [r for r in rules.values() if r.enabled], list(skills.values()),
|
|
64
|
+
list(roles.values()),
|
|
65
|
+
[preferences[i] for i in active if i in preferences and preferences[i].enabled],
|
|
66
|
+
notes, rule_roots,
|
|
67
|
+
)
|
|
@@ -53,8 +53,9 @@ def agent(
|
|
|
53
53
|
console.print(f" Project: {receipt.get('project_path', 'unknown')}")
|
|
54
54
|
console.print(f" Task: {receipt.get('task') or 'not provided'}")
|
|
55
55
|
provisional = bool(receipt.get("provisional"))
|
|
56
|
-
console.print(f" Resolution: {'provisional' if provisional else '
|
|
56
|
+
console.print(f" Resolution: {'provisional' if provisional else 'resolved'}")
|
|
57
57
|
files = receipt.get("files") or []
|
|
58
|
+
console.print(f" File scope: {'provided' if files else 'unknown'}")
|
|
58
59
|
console.print(f" Files: {', '.join(files) if files else 'not known'}")
|
|
59
60
|
console.print(f" Skill: {receipt.get('skill') or 'none'}")
|
|
60
61
|
console.print(f" Role: {receipt.get('role') or 'none'}")
|
|
@@ -270,14 +270,19 @@ def rules(
|
|
|
270
270
|
all: bool = typer.Option(False, "--all", "-a", help="Show all rules including disabled"),
|
|
271
271
|
check: bool = typer.Option(False, "--check", help="Scan for duplicates, empty bodies, weak descriptions"),
|
|
272
272
|
):
|
|
273
|
-
"""List rules. Shows
|
|
273
|
+
"""List rules. Shows the active rules for this directory by default.
|
|
274
274
|
|
|
275
|
-
Use --
|
|
275
|
+
Use --project to resolve a registered project, or --all for every rule in
|
|
276
|
+
the library. Use --check to audit rule quality (duplicates, empty bodies).
|
|
276
277
|
"""
|
|
278
|
+
from ..catalog import load_catalog
|
|
277
279
|
from ..store import load_config
|
|
278
280
|
from ..rules import load_all_rules, resolve_rules_for_project, check_rule_quality
|
|
279
281
|
|
|
280
282
|
config = load_config()
|
|
283
|
+
if project and not config.get_project(project):
|
|
284
|
+
console.print(f"[red]Project '{project}' not found[/red]")
|
|
285
|
+
raise typer.Exit(2)
|
|
281
286
|
|
|
282
287
|
if check:
|
|
283
288
|
findings = check_rule_quality(config)
|
|
@@ -303,7 +308,7 @@ def rules(
|
|
|
303
308
|
elif project:
|
|
304
309
|
rule_list = resolve_rules_for_project(config, project)
|
|
305
310
|
else:
|
|
306
|
-
rule_list =
|
|
311
|
+
rule_list = load_catalog(config, project_path=Path.cwd()).rules
|
|
307
312
|
|
|
308
313
|
if not rule_list:
|
|
309
314
|
console.print("[dim]No rules found. Use `dotai learn` to add rules.[/dim]")
|
|
@@ -22,10 +22,6 @@ def sync(
|
|
|
22
22
|
config = load_config()
|
|
23
23
|
project_path = Path(path).expanduser().resolve()
|
|
24
24
|
|
|
25
|
-
# Find project name
|
|
26
|
-
project_config = next((p for p in config.projects if p.path == project_path), None)
|
|
27
|
-
project_name = project_config.name if project_config else None
|
|
28
|
-
|
|
29
25
|
plan = plan_sync(project_path, get_config_dir())
|
|
30
26
|
|
|
31
27
|
console.print(f"Mode: [bold]{plan.mode}[/bold]")
|
|
@@ -36,7 +32,7 @@ def sync(
|
|
|
36
32
|
if check:
|
|
37
33
|
return
|
|
38
34
|
|
|
39
|
-
written = sync_local_context(plan, config
|
|
35
|
+
written = sync_local_context(plan, config)
|
|
40
36
|
|
|
41
37
|
for f in written:
|
|
42
38
|
console.print(f" [green]Synced[/green] {f}")
|
|
@@ -53,14 +49,13 @@ def primer(
|
|
|
53
49
|
|
|
54
50
|
config = load_config()
|
|
55
51
|
project_path = Path(path).expanduser().resolve() if path else None
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
))
|
|
52
|
+
try:
|
|
53
|
+
typer.echo(generate_primer(
|
|
54
|
+
config, project, project_path=project_path, compact=True,
|
|
55
|
+
))
|
|
56
|
+
except ValueError as error:
|
|
57
|
+
console.print(f"[red]{error}[/red]")
|
|
58
|
+
raise typer.Exit(2) from error
|
|
64
59
|
|
|
65
60
|
|
|
66
61
|
@app.command("context")
|
|
@@ -88,13 +83,10 @@ def resolve_task_context(
|
|
|
88
83
|
|
|
89
84
|
config = load_config()
|
|
90
85
|
project_path = Path(path).expanduser().resolve()
|
|
91
|
-
matched = next((p for p in config.projects if p.path == project_path), None)
|
|
92
|
-
project_name = matched.name if matched else None
|
|
93
86
|
try:
|
|
94
87
|
resolved = resolve_context(
|
|
95
88
|
config,
|
|
96
89
|
project_path,
|
|
97
|
-
project_name,
|
|
98
90
|
task=task,
|
|
99
91
|
files=split(files),
|
|
100
92
|
contexts=split(contexts),
|
|
@@ -130,19 +122,21 @@ def search(
|
|
|
130
122
|
query: str = typer.Argument("", help="Search keyword (optional if using --tag)"),
|
|
131
123
|
type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by rule, preference, role, or skill"),
|
|
132
124
|
tag: Optional[str] = typer.Option(None, "--tag", help="Filter by tag"),
|
|
125
|
+
path: str = typer.Option(".", "--path", help="Search the knowledge that applies to this directory"),
|
|
133
126
|
):
|
|
134
|
-
"""Search
|
|
127
|
+
"""Search the knowledge that applies to a directory.
|
|
128
|
+
|
|
129
|
+
Uses the same ancestor catalog as context and primer. Unrelated registered
|
|
130
|
+
projects are not read. Active preference packs are included; inactive packs
|
|
131
|
+
stay out.
|
|
135
132
|
|
|
136
133
|
Examples:
|
|
137
134
|
dotai search "useEffect"
|
|
138
135
|
dotai search "review" --type skill
|
|
139
136
|
dotai search --tag security
|
|
140
|
-
dotai search "auth" --type rule --tag react
|
|
137
|
+
dotai search "auth" --type rule --tag react --path .
|
|
141
138
|
"""
|
|
142
|
-
from ..
|
|
143
|
-
from ..roles import load_all_roles
|
|
144
|
-
from ..rules import load_all_rules
|
|
145
|
-
from ..skills import load_all_skills
|
|
139
|
+
from ..catalog import load_catalog
|
|
146
140
|
from ..store import load_config
|
|
147
141
|
|
|
148
142
|
valid_types = {"rule", "preference", "role", "skill"}
|
|
@@ -153,11 +147,16 @@ def search(
|
|
|
153
147
|
raise typer.Exit(1)
|
|
154
148
|
|
|
155
149
|
config = load_config()
|
|
150
|
+
try:
|
|
151
|
+
catalog = load_catalog(config, project_path=Path(path).expanduser().resolve())
|
|
152
|
+
except ValueError as error:
|
|
153
|
+
console.print(f"[red]{error}[/red]")
|
|
154
|
+
raise typer.Exit(2) from error
|
|
156
155
|
items = []
|
|
157
|
-
items.extend(("rule", item.id, item.description, item.tags, item.file_path) for item in
|
|
158
|
-
items.extend(("preference", item.id, item.description, item.tags, item.file_path) for item in
|
|
159
|
-
items.extend(("role", item.id, item.description, item.tags, item.file_path) for item in
|
|
160
|
-
items.extend(("skill", item.id, item.description, item.tags, item.file_path) for item in
|
|
156
|
+
items.extend(("rule", item.id, item.description, item.tags, item.file_path) for item in catalog.rules)
|
|
157
|
+
items.extend(("preference", item.id, item.description, item.tags, item.file_path) for item in catalog.preferences)
|
|
158
|
+
items.extend(("role", item.id, item.description, item.tags, item.file_path) for item in catalog.roles)
|
|
159
|
+
items.extend(("skill", item.id, item.description, item.tags, item.file_path) for item in catalog.skills)
|
|
161
160
|
|
|
162
161
|
query_lower = query.strip().lower()
|
|
163
162
|
tag_lower = tag.strip().lower() if tag else None
|