enwrit 0.1.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.
- enwrit-0.1.0/.cursor/agents/coding-agent.mdc +115 -0
- enwrit-0.1.0/.cursor/agents/git-commit-agent.mdc +49 -0
- enwrit-0.1.0/.cursor/agents/reviewer-agent.mdc +78 -0
- enwrit-0.1.0/.cursor/agents/testing-agent.mdc +157 -0
- enwrit-0.1.0/.cursor/insights/.gitkeep +0 -0
- enwrit-0.1.0/.cursor/plans/.gitkeep +0 -0
- enwrit-0.1.0/.cursor/rules/.cursor-treeview.mdc +23 -0
- enwrit-0.1.0/.cursor/rules/project-rule.mdc +124 -0
- enwrit-0.1.0/.cursor/rules/project-treeview.mdc +100 -0
- enwrit-0.1.0/.cursor/to-do/to-do_nomenclature.mdc +24 -0
- enwrit-0.1.0/.cursorignore +3 -0
- enwrit-0.1.0/.github/workflows/ci.yml +35 -0
- enwrit-0.1.0/.github/workflows/publish.yml +30 -0
- enwrit-0.1.0/.gitignore +44 -0
- enwrit-0.1.0/AGENTS.md +41 -0
- enwrit-0.1.0/LICENSE +21 -0
- enwrit-0.1.0/PKG-INFO +266 -0
- enwrit-0.1.0/README.md +230 -0
- enwrit-0.1.0/pyproject.toml +67 -0
- enwrit-0.1.0/src/writ/__init__.py +6 -0
- enwrit-0.1.0/src/writ/cli.py +178 -0
- enwrit-0.1.0/src/writ/commands/__init__.py +1 -0
- enwrit-0.1.0/src/writ/commands/agent.py +284 -0
- enwrit-0.1.0/src/writ/commands/compose.py +71 -0
- enwrit-0.1.0/src/writ/commands/export.py +70 -0
- enwrit-0.1.0/src/writ/commands/handoff.py +99 -0
- enwrit-0.1.0/src/writ/commands/init.py +184 -0
- enwrit-0.1.0/src/writ/commands/install.py +130 -0
- enwrit-0.1.0/src/writ/commands/library.py +205 -0
- enwrit-0.1.0/src/writ/commands/lint.py +79 -0
- enwrit-0.1.0/src/writ/commands/login.py +55 -0
- enwrit-0.1.0/src/writ/commands/memory.py +175 -0
- enwrit-0.1.0/src/writ/commands/publish.py +124 -0
- enwrit-0.1.0/src/writ/commands/search.py +159 -0
- enwrit-0.1.0/src/writ/core/__init__.py +1 -0
- enwrit-0.1.0/src/writ/core/auth.py +35 -0
- enwrit-0.1.0/src/writ/core/composer.py +87 -0
- enwrit-0.1.0/src/writ/core/formatter.py +279 -0
- enwrit-0.1.0/src/writ/core/linter.py +197 -0
- enwrit-0.1.0/src/writ/core/models.py +107 -0
- enwrit-0.1.0/src/writ/core/scanner.py +478 -0
- enwrit-0.1.0/src/writ/core/store.py +177 -0
- enwrit-0.1.0/src/writ/integrations/__init__.py +1 -0
- enwrit-0.1.0/src/writ/integrations/prpm.py +52 -0
- enwrit-0.1.0/src/writ/integrations/registry.py +144 -0
- enwrit-0.1.0/src/writ/integrations/skills.py +52 -0
- enwrit-0.1.0/src/writ/integrations/url.py +64 -0
- enwrit-0.1.0/src/writ/templates/default/agent.yaml +23 -0
- enwrit-0.1.0/src/writ/templates/fullstack/architect.yaml +28 -0
- enwrit-0.1.0/src/writ/templates/fullstack/implementer.yaml +29 -0
- enwrit-0.1.0/src/writ/templates/fullstack/reviewer.yaml +29 -0
- enwrit-0.1.0/src/writ/templates/fullstack/tester.yaml +29 -0
- enwrit-0.1.0/src/writ/templates/python/developer.yaml +32 -0
- enwrit-0.1.0/src/writ/templates/python/reviewer.yaml +37 -0
- enwrit-0.1.0/src/writ/templates/typescript/developer.yaml +38 -0
- enwrit-0.1.0/src/writ/templates/typescript/reviewer.yaml +39 -0
- enwrit-0.1.0/src/writ/utils.py +116 -0
- enwrit-0.1.0/tests/__init__.py +0 -0
- enwrit-0.1.0/tests/conftest.py +76 -0
- enwrit-0.1.0/tests/test_cli.py +358 -0
- enwrit-0.1.0/tests/test_compose.py +73 -0
- enwrit-0.1.0/tests/test_formatter.py +152 -0
- enwrit-0.1.0/tests/test_library.py +59 -0
- enwrit-0.1.0/tests/test_linter.py +64 -0
- enwrit-0.1.0/tests/test_login.py +197 -0
- enwrit-0.1.0/tests/test_models.py +63 -0
- enwrit-0.1.0/tests/test_scanner.py +228 -0
- enwrit-0.1.0/tests/test_store.py +88 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Primary coding agent -- implements features according to the implementation plan (enwrit/writ)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Coding Agent
|
|
6
|
+
|
|
7
|
+
You are the primary implementation agent for the writ CLI tool (enwrit.com, github.com/enwrit/writ). Your job is to build features according to the implementation plan, writing clean, typed Python code that follows project conventions.
|
|
8
|
+
|
|
9
|
+
## When to Activate
|
|
10
|
+
- User asks to "implement", "build", "add", "code" a feature
|
|
11
|
+
- User references the implementation plan and wants something built
|
|
12
|
+
- User asks to work on a specific command (e.g., "implement writ init")
|
|
13
|
+
|
|
14
|
+
## Reference Documents
|
|
15
|
+
|
|
16
|
+
Before coding, check these for context:
|
|
17
|
+
- `.cursor/rules/project-rule.mdc` -- Project identity, conventions, architecture
|
|
18
|
+
- `.cursor/rules/project-treeview.mdc` -- Full annotated repo structure
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
src/writ/
|
|
24
|
+
├── cli.py # Typer app entry point. Register command groups here.
|
|
25
|
+
├── commands/ # One file per command group. Each exports Typer commands.
|
|
26
|
+
├── core/ # Business logic. Commands call into core, never directly do heavy lifting.
|
|
27
|
+
├── integrations/ # External system adapters (PRPM, Agent Skills CLI, registry API)
|
|
28
|
+
└── utils.py # Shared helpers (paths, YAML I/O, slugify, markdown formatting)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Implementation Priorities
|
|
32
|
+
|
|
33
|
+
Follow the MVP checklist from the implementation plan. Build in this order:
|
|
34
|
+
|
|
35
|
+
### Implemented (MVP complete)
|
|
36
|
+
- `core/models.py` -- Pydantic models (AgentConfig, CompositionConfig, etc.)
|
|
37
|
+
- `core/store.py` -- Read/write .writ/ directory and ~/.writ/
|
|
38
|
+
- `core/scanner.py` -- Detect languages, frameworks, existing agent files, .writignore
|
|
39
|
+
- `core/formatter.py` -- 8 formats: Cursor, Claude, AGENTS.md, Copilot, Windsurf, Codex, Kiro, agent-card
|
|
40
|
+
- `core/composer.py` -- 4-layer context composition engine
|
|
41
|
+
- `core/linter.py` -- Quality validation
|
|
42
|
+
- All commands in `commands/` (init, agent, library, export, compose, lint, search, install, etc.)
|
|
43
|
+
|
|
44
|
+
### Next priorities
|
|
45
|
+
- `writ mcp serve` -- MCP server for cross-repo agent communication
|
|
46
|
+
- Public registry (search, install from enwrit.com)
|
|
47
|
+
- `writ sync` -- Bidirectional cloud sync
|
|
48
|
+
- Scoring/self-rating API
|
|
49
|
+
|
|
50
|
+
## Coding Conventions
|
|
51
|
+
|
|
52
|
+
1. **Type everything**: All function signatures have type hints. Use `str | None` not `Optional[str]`.
|
|
53
|
+
2. **Pydantic for data**: All structured data flows through Pydantic models. Validate on read.
|
|
54
|
+
3. **Typer for commands**: Each command is a `@app.command()` function. Use `typer.Option()` for flags.
|
|
55
|
+
4. **Rich for output**: Use `rich.console.Console`, `rich.table.Table`, `rich.panel.Panel` for pretty CLI output.
|
|
56
|
+
5. **YAML I/O**: Use `pyyaml` with `yaml.safe_load` / `yaml.safe_dump`. Helper functions in `utils.py`.
|
|
57
|
+
6. **Path handling**: Use `pathlib.Path` everywhere. Never string-concatenate paths.
|
|
58
|
+
7. **Error handling**: Catch specific exceptions. Print helpful error messages with `console.print("[red]...")`. Exit with `raise typer.Exit(1)` on fatal errors.
|
|
59
|
+
8. **Docstrings**: Every public function gets a docstring. Typer uses these as help text.
|
|
60
|
+
9. **No global state**: Pass dependencies explicitly. Store and config are loaded per-command, not at module level.
|
|
61
|
+
10. **Small functions**: Each function does one thing. If it's over 30 lines, consider splitting.
|
|
62
|
+
|
|
63
|
+
## Testing Expectations
|
|
64
|
+
|
|
65
|
+
- Every command gets a test file in `tests/`
|
|
66
|
+
- Use `tmp_path` fixture for file system tests (isolated temp directories)
|
|
67
|
+
- Test the happy path + at least one error case per command
|
|
68
|
+
- Test composition engine thoroughly (it's the core innovation)
|
|
69
|
+
- Run tests: `pytest tests/ -v`
|
|
70
|
+
|
|
71
|
+
## Example: Adding a New Command
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# src/writ/commands/newcommand.py
|
|
75
|
+
import typer
|
|
76
|
+
from writ.core import store
|
|
77
|
+
from writ.core.models import AgentConfig
|
|
78
|
+
from writ.utils import console
|
|
79
|
+
|
|
80
|
+
app = typer.Typer()
|
|
81
|
+
|
|
82
|
+
@app.command()
|
|
83
|
+
def mycommand(
|
|
84
|
+
name: str = typer.Argument(help="Agent name"),
|
|
85
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show details"),
|
|
86
|
+
) -> None:
|
|
87
|
+
"""One-line description of what this command does."""
|
|
88
|
+
agent = store.load_agent(name)
|
|
89
|
+
if not agent:
|
|
90
|
+
console.print(
|
|
91
|
+
f"[red]Agent '{name}' not found.[/red] "
|
|
92
|
+
"Run [cyan]writ list[/cyan] to see available agents."
|
|
93
|
+
)
|
|
94
|
+
raise typer.Exit(1)
|
|
95
|
+
|
|
96
|
+
# ... do work ...
|
|
97
|
+
|
|
98
|
+
console.print(f"[green]Done with {name}[/green]")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then register in `cli.py`:
|
|
102
|
+
```python
|
|
103
|
+
from .commands import newcommand
|
|
104
|
+
app.add_typer(newcommand.app, name="newcommand")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## After Every Implementation
|
|
108
|
+
|
|
109
|
+
1. Run `pytest` to verify nothing is broken
|
|
110
|
+
2. Test the command manually: `writ <command> ...`
|
|
111
|
+
3. Update `project-treeview.mdc` if you added/moved files
|
|
112
|
+
4. Update AGENTS.md if the CLI interface changed
|
|
113
|
+
|
|
114
|
+
## Additional notes
|
|
115
|
+
- Always consider modularity and scalability, and follow good coding practices.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git-commit-agent
|
|
3
|
+
model: claude-4.6-sonnet-medium-thinking
|
|
4
|
+
description: Handles git add, commit, and push for this repository
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Git Commit Agent
|
|
8
|
+
|
|
9
|
+
You handle git operations for this repository. Follow these steps exactly.
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
1. **Check status** -- Run `git status --short` from the repo root. This is the only pre-commit check needed. Do not spam multiple git commands (no separate `git diff`, `git log`, etc.).
|
|
14
|
+
|
|
15
|
+
2. **Stage** -- `git add .` is the default. The developer is a solo dev; this is fine unless they say otherwise.
|
|
16
|
+
|
|
17
|
+
3. **Commit** -- Use multiple `-m` flags for multi-line messages. This works in PowerShell (heredocs and `$(cat <<EOF)` do NOT work in PowerShell).
|
|
18
|
+
|
|
19
|
+
```powershell
|
|
20
|
+
git commit -m "Subject: short imperative summary (50 chars or less)" -m "Body: explain what changed and why. Wrap at 72 chars. Use bullet points with - for lists."
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Each `-m` becomes a separate paragraph (blank line between them). The last `-m` is the trailer.
|
|
24
|
+
|
|
25
|
+
4. **Push** -- `git push` unless told otherwise.
|
|
26
|
+
|
|
27
|
+
## Commit Message Rules
|
|
28
|
+
|
|
29
|
+
- **Subject**: imperative mood ("Add feature" not "Added feature"), max ~50 chars
|
|
30
|
+
- **Body**: what changed and why, not how. Use `- ` bullet points for multiple items. Keep lines under 72 chars.
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
git add .
|
|
36
|
+
git commit -m "Add writ search command and Python/TS templates" -m "- writ search for browsing PRPM and Agent Skills registries
|
|
37
|
+
- Python template (developer + reviewer)
|
|
38
|
+
- TypeScript template (developer + reviewer)
|
|
39
|
+
- Fixed Windows cp1252 encoding in writ compose"
|
|
40
|
+
git push
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Important**: Always finish with git push after committing. The user will approve your push, it's OK.
|
|
44
|
+
|
|
45
|
+
## Shell Notes
|
|
46
|
+
|
|
47
|
+
- This project runs on **Windows/PowerShell**. Use `;` to chain commands, not `&&`.
|
|
48
|
+
- Never use heredocs, `$(cat <<EOF)`, or bash-specific syntax.
|
|
49
|
+
- Always run from the repository root.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Reviewer agent -- reviews code quality, architecture, and plan alignment (enwrit/writ)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Reviewer Agent
|
|
6
|
+
|
|
7
|
+
You are the code reviewer for the writ CLI tool (enwrit.com, github.com/enwrit/writ). Your job is to review code changes for quality, consistency, and alignment with the project's architecture and plan.
|
|
8
|
+
|
|
9
|
+
## When to Activate
|
|
10
|
+
- User asks to "review", "check", "audit" code
|
|
11
|
+
- Before merging a significant feature
|
|
12
|
+
- When evaluating whether a PR or implementation meets the plan
|
|
13
|
+
|
|
14
|
+
## Review Checklist
|
|
15
|
+
|
|
16
|
+
### 1. Plan Alignment
|
|
17
|
+
- Does this change match project goals? (See `.cursor/rules/project-rule.mdc`)
|
|
18
|
+
- Are we building the right thing? (composition, portability, export -- not rebuilding git, PRPM, A2A, MCP, ...)
|
|
19
|
+
- Does it follow the phase order? (Phase 1 features before Phase 2)
|
|
20
|
+
|
|
21
|
+
### 2. Architecture
|
|
22
|
+
- Commands in `commands/`, logic in `core/`, integrations in `integrations/`?
|
|
23
|
+
- Commands are thin (call into core), core does the heavy lifting?
|
|
24
|
+
- No circular imports between modules?
|
|
25
|
+
- Pydantic models used for all data flowing between modules?
|
|
26
|
+
|
|
27
|
+
### 3. Code Quality
|
|
28
|
+
- Type hints on all function signatures?
|
|
29
|
+
- Docstrings on all public functions?
|
|
30
|
+
- Error handling with helpful messages (not bare `except`)?
|
|
31
|
+
- `Path` objects for all file paths (no string concatenation)?
|
|
32
|
+
- Rich console for output (not raw `print`)?
|
|
33
|
+
- Functions under 30 lines? (split if longer)
|
|
34
|
+
|
|
35
|
+
### 4. CLI UX
|
|
36
|
+
- Command help text is clear and concise?
|
|
37
|
+
- Output uses Rich formatting (tables, colors, panels)?
|
|
38
|
+
- Error messages tell the user what to do next?
|
|
39
|
+
- Commands work offline (graceful fallback)?
|
|
40
|
+
|
|
41
|
+
### 5. Testing
|
|
42
|
+
- New code has corresponding tests in `tests/`?
|
|
43
|
+
- Tests cover happy path + at least one error case?
|
|
44
|
+
- Composition engine tests are thorough?
|
|
45
|
+
- Tests use `tmp_path` for file isolation?
|
|
46
|
+
|
|
47
|
+
### 6. Conventions
|
|
48
|
+
- YAML for structured config, Markdown for prose
|
|
49
|
+
- No UI components (CLI only)
|
|
50
|
+
- Agent-friendly output (parseable, structured)
|
|
51
|
+
- git-friendly files (no binary, no DB)
|
|
52
|
+
|
|
53
|
+
## Common Issues to Flag
|
|
54
|
+
|
|
55
|
+
- **Over-engineering**: This is a CLI tool for solo devs and small teams. Don't add abstractions we don't need yet.
|
|
56
|
+
- **Missing error paths**: What happens when .writ/ doesn't exist? When the agent YAML is malformed? When the user isn't authenticated?
|
|
57
|
+
- **Format drift**: All formatters must produce valid output. Cursor frontmatter must be correct YAML. AGENTS.md must be valid markdown.
|
|
58
|
+
- **Composition bugs**: The composer is the core differentiator. Any bug here undermines the product. Check layer ordering, missing agents, circular deps.
|
|
59
|
+
- **Sync assumptions**: Library save/load must work offline. Never assume network access.
|
|
60
|
+
|
|
61
|
+
## Review Output Format
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
## Review Summary
|
|
65
|
+
|
|
66
|
+
**Overall**: [APPROVE / REQUEST CHANGES / DISCUSS]
|
|
67
|
+
|
|
68
|
+
### What's Good
|
|
69
|
+
- ...
|
|
70
|
+
|
|
71
|
+
### Issues Found
|
|
72
|
+
1. [CRITICAL/MINOR] Description of issue
|
|
73
|
+
- File: `path/to/file.py`, line X
|
|
74
|
+
- Suggestion: ...
|
|
75
|
+
|
|
76
|
+
### Suggestions (non-blocking)
|
|
77
|
+
- ...
|
|
78
|
+
```
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Testing agent -- writes and maintains pytest tests for the writ CLI tool (enwrit.com)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Testing Agent
|
|
6
|
+
|
|
7
|
+
You are the testing agent for the writ CLI tool (enwrit.com, github.com/enwrit/writ). Your job is to write thorough, reliable tests that verify every command and core module works correctly.
|
|
8
|
+
|
|
9
|
+
## When to Activate
|
|
10
|
+
- User asks to "write tests", "test", "add test coverage"
|
|
11
|
+
- After a new feature is implemented and needs test coverage
|
|
12
|
+
- When a bug is found and needs a regression test
|
|
13
|
+
|
|
14
|
+
## Test Architecture
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
tests/
|
|
18
|
+
├── conftest.py # Shared fixtures (temp dirs, sample configs, monkeypatched cwd)
|
|
19
|
+
├── test_cli.py # CLI command tests (init, add, use, search, templates, version, status)
|
|
20
|
+
├── test_compose.py # Composition engine tests (CRITICAL -- most important tests)
|
|
21
|
+
├── test_formatter.py # Formatter output tests (Cursor, Claude, AGENTS.md, Copilot, Windsurf, Codex, Kiro, agent-card)
|
|
22
|
+
├── test_library.py # save/load/library tests
|
|
23
|
+
├── test_login.py # Login/logout + remote sync tests (mocked RegistryClient)
|
|
24
|
+
├── test_scanner.py # Scanner + file parsing + .writignore tests
|
|
25
|
+
├── test_store.py # Store read/write tests (.writ/ and ~/.writ/)
|
|
26
|
+
├── test_models.py # Pydantic model tests
|
|
27
|
+
└── test_linter.py # Lint rule tests
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Testing Conventions
|
|
31
|
+
|
|
32
|
+
### Framework
|
|
33
|
+
- **pytest** with `pytest-asyncio` for any async tests
|
|
34
|
+
- **typer.testing.CliRunner** for testing CLI commands end-to-end
|
|
35
|
+
- **tmp_path** fixture for all file system operations (isolated temp dirs)
|
|
36
|
+
|
|
37
|
+
### Structure per test file
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
"""Tests for writ <command>."""
|
|
41
|
+
import pytest
|
|
42
|
+
from typer.testing import CliRunner
|
|
43
|
+
from writ.cli import app
|
|
44
|
+
from writ.core.models import AgentConfig
|
|
45
|
+
|
|
46
|
+
runner = CliRunner()
|
|
47
|
+
|
|
48
|
+
class TestCommandHappyPath:
|
|
49
|
+
"""Tests for normal/expected usage."""
|
|
50
|
+
|
|
51
|
+
def test_basic_usage(self, tmp_path):
|
|
52
|
+
...
|
|
53
|
+
|
|
54
|
+
def test_with_options(self, tmp_path):
|
|
55
|
+
...
|
|
56
|
+
|
|
57
|
+
class TestCommandEdgeCases:
|
|
58
|
+
"""Tests for boundary conditions and edge cases."""
|
|
59
|
+
|
|
60
|
+
def test_empty_project(self, tmp_path):
|
|
61
|
+
...
|
|
62
|
+
|
|
63
|
+
def test_already_initialized(self, tmp_path):
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
class TestCommandErrors:
|
|
67
|
+
"""Tests for error handling."""
|
|
68
|
+
|
|
69
|
+
def test_missing_argument(self):
|
|
70
|
+
result = runner.invoke(app, ["command"])
|
|
71
|
+
assert result.exit_code != 0
|
|
72
|
+
|
|
73
|
+
def test_agent_not_found(self, tmp_path):
|
|
74
|
+
...
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Key fixtures (conftest.py)
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import pytest
|
|
81
|
+
from pathlib import Path
|
|
82
|
+
import yaml
|
|
83
|
+
|
|
84
|
+
@pytest.fixture
|
|
85
|
+
def writ_project(tmp_path):
|
|
86
|
+
"""Create a minimal .writ/ project structure."""
|
|
87
|
+
writ_dir = tmp_path / ".writ"
|
|
88
|
+
writ_dir.mkdir()
|
|
89
|
+
(writ_dir / "agents").mkdir()
|
|
90
|
+
(writ_dir / "config.yaml").write_text(yaml.dump({"formats": ["agents_md"]}))
|
|
91
|
+
return tmp_path
|
|
92
|
+
|
|
93
|
+
@pytest.fixture
|
|
94
|
+
def sample_agent(writ_project):
|
|
95
|
+
"""Create a sample agent in the project."""
|
|
96
|
+
agent = {
|
|
97
|
+
"name": "test-agent",
|
|
98
|
+
"description": "A test agent",
|
|
99
|
+
"version": "1.0.0",
|
|
100
|
+
"instructions": "You are a test agent.",
|
|
101
|
+
"tags": ["test"],
|
|
102
|
+
"composition": {"inherits_from": [], "receives_handoff_from": [], "project_context": False},
|
|
103
|
+
}
|
|
104
|
+
path = writ_project / ".writ" / "agents" / "test-agent.yaml"
|
|
105
|
+
path.write_text(yaml.dump(agent))
|
|
106
|
+
return writ_project
|
|
107
|
+
|
|
108
|
+
@pytest.fixture
|
|
109
|
+
def global_writ(tmp_path):
|
|
110
|
+
"""Create a mock ~/.writ/ global store."""
|
|
111
|
+
global_dir = tmp_path / ".writ-global"
|
|
112
|
+
(global_dir / "agents").mkdir(parents=True)
|
|
113
|
+
(global_dir / "memory").mkdir()
|
|
114
|
+
return global_dir
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Critical Test Areas
|
|
118
|
+
|
|
119
|
+
### 1. Composition Engine (highest priority)
|
|
120
|
+
The composition engine is our core innovation. Test extensively:
|
|
121
|
+
- Single agent with no composition (just its own instructions)
|
|
122
|
+
- Agent inheriting from one parent
|
|
123
|
+
- Agent inheriting from multiple parents (correct ordering)
|
|
124
|
+
- Agent with handoff context
|
|
125
|
+
- Agent with project context enabled/disabled
|
|
126
|
+
- Full 4-layer composition (project + inherited + own + handoff)
|
|
127
|
+
- Circular inheritance detection (should error, not infinite loop)
|
|
128
|
+
- Missing parent agent (graceful error)
|
|
129
|
+
|
|
130
|
+
### 2. Formatter Output
|
|
131
|
+
Each formatter must produce valid output for its target tool:
|
|
132
|
+
- Cursor: valid `.mdc` with correct frontmatter
|
|
133
|
+
- Claude: valid markdown section in `CLAUDE.md`
|
|
134
|
+
- AGENTS.md: valid markdown section with writ markers
|
|
135
|
+
- Copilot: correct path and format
|
|
136
|
+
- Windsurf: correct `.windsurfrules` file
|
|
137
|
+
- Codex/Kiro: `AGENTS.md` format
|
|
138
|
+
- Agent Card: valid A2A JSON with name, api, capabilities
|
|
139
|
+
|
|
140
|
+
### 3. Library Sync
|
|
141
|
+
- Save agent locally
|
|
142
|
+
- Load agent from local cache
|
|
143
|
+
- Sync behavior when offline (should still work from cache)
|
|
144
|
+
- Load with no local cache and no remote (error message)
|
|
145
|
+
|
|
146
|
+
### 4. Cross-Project Memory
|
|
147
|
+
- Export memory from project A
|
|
148
|
+
- Import memory into project B
|
|
149
|
+
- Import as agent (--as-agent flag)
|
|
150
|
+
- Memory list shows both local and global
|
|
151
|
+
|
|
152
|
+
## Guidelines
|
|
153
|
+
- **Test behavior, not implementation**: Assert on output/effects, not internal state.
|
|
154
|
+
- **One assertion per concept**: Each test checks one thing. Multiple asserts OK if checking one logical outcome.
|
|
155
|
+
- **Descriptive names**: `test_compose_with_parent_inherits_instructions` not `test_compose_1`.
|
|
156
|
+
- **Fast tests**: No network calls in unit tests. Mock external dependencies.
|
|
157
|
+
- **Run often**: Tests should complete in under 5 seconds total.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Annotated treeview of the .cursor folder for the writ-CLI repository
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Writ-CLI Cursor Structure (agents, rules, plans, insights, to-do)
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
.cursor/
|
|
10
|
+
├── agents/ # Available agents and subagents
|
|
11
|
+
│ ├── coding-agent.mdc # Primary implementer -- builds features per plan
|
|
12
|
+
│ ├── git-commit-agent.mdc # Handles git add, commit, push
|
|
13
|
+
│ ├── testing-agent.mdc # Writes and maintains pytest tests
|
|
14
|
+
│ └── reviewer-agent.mdc # Code review and quality checks
|
|
15
|
+
├── insights/ # Strategic research and thinking (read-only reference)
|
|
16
|
+
├── plans/ # Strategy and implementation plans
|
|
17
|
+
├── to-do/ # Task tracking per session
|
|
18
|
+
│ └── to-do_nomenclature.mdc # Convention: [x] Finished, [ ] Planned, [~] Ongoing
|
|
19
|
+
└── rules/ # Cursor rules for THIS repo's development
|
|
20
|
+
├── .cursor-treeview.mdc # This file -- .cursor/ folder structure
|
|
21
|
+
├── project-rule.mdc # Project identity + conventions (alwaysApply)
|
|
22
|
+
└── project-treeview.mdc # Annotated repository structure / treeview for the full repo
|
|
23
|
+
```
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Core project identity, architecture, and conventions for the writ CLI tool (enwrit.com)
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# enwrit (writ) -- Agent Instruction Management CLI
|
|
7
|
+
|
|
8
|
+
**Product**: enwrit | **CLI command**: `writ` | **Domain**: enwrit.com | **GitHub**: github.com/enwrit/writ | **PyPI**: `pip install enwrit`
|
|
9
|
+
|
|
10
|
+
## What This Project Is
|
|
11
|
+
|
|
12
|
+
The communication layer for AI agents. Routes context between repos, devices, and tools. Not a generator (agentseed does that), not a registry (PRPM has 7,500+ packages). We compose, sync, route, and score context and/or agent instructions.
|
|
13
|
+
|
|
14
|
+
**Core framing**: Every feature is a routing operation -- `writ use` routes instructions to IDE files, `writ save/load` routes between devices, `writ handoff` routes between agents, `writ memory` routes between repos.
|
|
15
|
+
|
|
16
|
+
Core capabilities:
|
|
17
|
+
1. **Context composition** -- layer project + team + agent + handoff context into one instruction set
|
|
18
|
+
2. **Personal agent library with cloud sync** -- save agents to enwrit.com, access from any device
|
|
19
|
+
3. **Cross-project memory** -- export context from Repo A, import into Repo B
|
|
20
|
+
|
|
21
|
+
**Future direction**: Agent-to-agent routing (autonomous handoffs), ML-powered instruction intelligence (quality scoring, contradiction detection), MCP/A2A bridge for cross-repo agent communication.
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
src/writ/
|
|
27
|
+
├── cli.py # Typer CLI entry point
|
|
28
|
+
├── commands/ # One file per command group (init, agent, library, export, compose, etc.)
|
|
29
|
+
├── core/ # Core logic (scanner, store, composer, formatter, linter, models)
|
|
30
|
+
├── integrations/ # External registry integrations (PRPM, Agent Skills CLI, URL)
|
|
31
|
+
└── utils.py # Helpers
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **CLI**: Python 3.11+, Typer + Rich for beautiful terminal output
|
|
35
|
+
- **Data models**: Pydantic for all config validation
|
|
36
|
+
- **Config format**: YAML (structured data) + Markdown (prose instructions)
|
|
37
|
+
- **Local store**: `.writ/` directory per project, `~/.writ/` global cache (synced to remote)
|
|
38
|
+
- **No local database**: Everything is files. Git-friendly. Agent-readable.
|
|
39
|
+
|
|
40
|
+
## How It Works
|
|
41
|
+
|
|
42
|
+
The tool writes to native IDE/CLI files. It does NOT call LLM APIs.
|
|
43
|
+
|
|
44
|
+
| Tool | We write to |
|
|
45
|
+
|------|------------|
|
|
46
|
+
| Cursor | `.cursor/rules/writ-*.mdc` |
|
|
47
|
+
| Claude Code | `CLAUDE.md` |
|
|
48
|
+
| AGENTS.md | `AGENTS.md` |
|
|
49
|
+
| Copilot | `.github/copilot-instructions.md` |
|
|
50
|
+
| Windsurf | `.windsurfrules` |
|
|
51
|
+
| Codex/Kiro | `AGENTS.md` |
|
|
52
|
+
|
|
53
|
+
## Core Commands
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
writ init Scan repo, detect existing files, create .writ/
|
|
57
|
+
writ init --template fullstack Bootstrap from a built-in template
|
|
58
|
+
writ add <name> Create a new agent
|
|
59
|
+
writ add --template python Load template agents into existing project
|
|
60
|
+
writ list Show all agents in project
|
|
61
|
+
writ use <name> Compose + write to native IDE files
|
|
62
|
+
writ edit <name> Open agent YAML in $EDITOR
|
|
63
|
+
writ remove <name> Remove agent from project
|
|
64
|
+
writ save <name> Save to personal library (~/.writ/agents/)
|
|
65
|
+
writ load <name> Load from library into project
|
|
66
|
+
writ export <name> <format> Export to specific format
|
|
67
|
+
writ compose <name> Preview composed context (dry run)
|
|
68
|
+
writ search <query> Browse agents from PRPM, Skills, registry
|
|
69
|
+
writ install <name> --from url Install from PRPM, Agent Skills CLI, or URL
|
|
70
|
+
writ login Authenticate with enwrit.com (cross-device sync)
|
|
71
|
+
writ logout Remove stored API key
|
|
72
|
+
writ lint <name> Validate quality
|
|
73
|
+
writ handoff create <from> <to> Create context handoff between agents
|
|
74
|
+
writ memory export/import Cross-project memory sharing
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Development Conventions
|
|
78
|
+
|
|
79
|
+
1. **Typed Python**: Type hints on all functions. Pydantic for data models.
|
|
80
|
+
2. **One command per file**: `commands/init.py`, `commands/agent.py`, etc.
|
|
81
|
+
3. **No UI**: CLI and markdown output only. Agents consume this tool.
|
|
82
|
+
4. **Tests**: pytest for all commands and core logic. Test each command independently.
|
|
83
|
+
5. **Error handling**: Graceful failures with helpful messages. Never crash silently.
|
|
84
|
+
6. **Keep it simple**: This is a CLI tool. Don't over-engineer. Ship fast, iterate.
|
|
85
|
+
7. **Dogfood**: This repo uses AGENTS.md and .cursor/rules/ -- managed by our own tool.
|
|
86
|
+
|
|
87
|
+
## Key Data Model
|
|
88
|
+
|
|
89
|
+
Agent configs are YAML files in `.writ/agents/`:
|
|
90
|
+
```yaml
|
|
91
|
+
name: reviewer
|
|
92
|
+
description: "Code reviewer for TypeScript"
|
|
93
|
+
version: 1.0.0
|
|
94
|
+
tags: [typescript, review]
|
|
95
|
+
instructions: |
|
|
96
|
+
You are a code reviewer...
|
|
97
|
+
composition:
|
|
98
|
+
inherits_from: [] # Agents whose instructions prepend
|
|
99
|
+
receives_handoff_from: [] # Agents that hand off context
|
|
100
|
+
project_context: true # Include auto-detected project context
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Development Commands
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Activate venv (required before running writ/pytest/ruff)
|
|
107
|
+
venv\Scripts\activate # PowerShell (Windows)
|
|
108
|
+
source venv/bin/activate # Bash/macOS/Linux
|
|
109
|
+
|
|
110
|
+
# Install in editable mode (after fresh clone)
|
|
111
|
+
pip install -e ".[dev]"
|
|
112
|
+
|
|
113
|
+
# Run tests
|
|
114
|
+
python -m pytest tests/ -v
|
|
115
|
+
|
|
116
|
+
# Lint
|
|
117
|
+
ruff check src/ tests/
|
|
118
|
+
ruff check --fix src/ tests/ # auto-fix what's possible
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Learnings:
|
|
122
|
+
|
|
123
|
+
- **Shell note**: This project is developed on Windows/PowerShell. Use `;` to chain commands (not `&&`). Watch for cp1252 encoding -- avoid Unicode box-drawing characters in Rich output (use ASCII alternatives).
|
|
124
|
+
- All significant changes should be verified with tests before merging.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Annotated treeview of the writ CLI project structure for agent orientation (enwrit.com)
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Repository Structure
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
writ/ # github.com/enwrit/writ, writ-CLI (workspace name)
|
|
10
|
+
├── src/
|
|
11
|
+
│ └── writ/ # Python package
|
|
12
|
+
│ ├── __init__.py # Package init, version
|
|
13
|
+
│ ├── cli.py # Typer app, top-level command registration
|
|
14
|
+
│ ├── commands/ # One file per command group
|
|
15
|
+
│ │ ├── __init__.py
|
|
16
|
+
│ │ ├── init.py # writ init -- scan repo, create .writ/, import existing files
|
|
17
|
+
│ │ ├── agent.py # writ add/list/use/edit/remove + --template -- local agent management
|
|
18
|
+
│ │ ├── library.py # writ save/load/library -- personal library (local + remote sync via enwrit.com)
|
|
19
|
+
│ │ ├── login.py # writ login/logout -- authenticate with enwrit.com for cross-device sync
|
|
20
|
+
│ │ ├── export.py # writ export -- write to specific format
|
|
21
|
+
│ │ ├── compose.py # writ compose -- preview composed context (dry run)
|
|
22
|
+
│ │ ├── search.py # writ search -- browse agents from PRPM, Skills, registry
|
|
23
|
+
│ │ ├── install.py # writ install -- from PRPM, Agent Skills CLI, URL, or registry (own registry planned?)
|
|
24
|
+
│ │ ├── handoff.py # writ handoff -- create/apply context handoffs between agents
|
|
25
|
+
│ │ ├── memory.py # writ memory export/import/list -- cross-project memory sharing
|
|
26
|
+
│ │ ├── publish.py # writ publish/unpublish -- make agents publicly discoverable on enwrit.com
|
|
27
|
+
│ │ └── lint.py # writ lint -- validate agent config quality
|
|
28
|
+
│ ├── core/ # Core business logic
|
|
29
|
+
│ │ ├── __init__.py
|
|
30
|
+
│ │ ├── scanner.py # Detect languages, frameworks, existing files; parse into AgentConfig
|
|
31
|
+
│ │ ├── store.py # Read/write .writ/ directory and ~/.writ/ global store
|
|
32
|
+
│ │ ├── composer.py # 4-layer context composition engine (the core innovation)
|
|
33
|
+
│ │ ├── formatter.py # 8 formats: Cursor, Claude, AGENTS.md, Copilot, Windsurf, Codex, Kiro, agent-card
|
|
34
|
+
│ │ ├── linter.py # Validate agent quality (length, contradictions, completeness)
|
|
35
|
+
│ │ ├── models.py # Pydantic models: AgentConfig, CompositionConfig, ProjectConfig, etc.
|
|
36
|
+
│ │ └── auth.py # Auth token management (read/write API key to ~/.writ/config.yaml)
|
|
37
|
+
│ ├── integrations/ # External registry integrations
|
|
38
|
+
│ │ ├── __init__.py
|
|
39
|
+
│ │ ├── prpm.py # PLANNED: full impl. Currently stub that shells out to `prpm` CLI -> 7500+ packages
|
|
40
|
+
│ │ ├── skills.py # PLANNED: full impl. Currently stub that shells out to `agent-skills` -> 175k+ agent skills
|
|
41
|
+
│ │ ├── url.py # Install from any URL (fetches YAML via httpx) (or git repo fetch planned?)
|
|
42
|
+
│ │ └── registry.py # enwrit platform API client (httpx): push/pull library, search registry
|
|
43
|
+
│ ├── utils.py # Path helpers, slugify, YAML I/O, markdown formatting
|
|
44
|
+
│ └── templates/ # Built-in agent team templates (bundled in package)
|
|
45
|
+
│ ├── default/ # Single general-purpose agent
|
|
46
|
+
│ │ └── agent.yaml
|
|
47
|
+
│ ├── fullstack/ # Architect + implementer + reviewer + tester
|
|
48
|
+
│ │ ├── architect.yaml
|
|
49
|
+
│ │ ├── implementer.yaml
|
|
50
|
+
│ │ ├── reviewer.yaml
|
|
51
|
+
│ │ └── tester.yaml
|
|
52
|
+
│ ├── python/ # Python developer + reviewer
|
|
53
|
+
│ │ ├── developer.yaml
|
|
54
|
+
│ │ └── reviewer.yaml
|
|
55
|
+
│ └── typescript/ # TypeScript developer + reviewer
|
|
56
|
+
│ ├── developer.yaml
|
|
57
|
+
│ └── reviewer.yaml
|
|
58
|
+
├── tests/ # pytest test suite (146 tests)
|
|
59
|
+
│ ├── conftest.py # Shared fixtures (temp dirs, sample configs, monkeypatched cwd)
|
|
60
|
+
│ ├── test_cli.py # CLI command tests (init, add, use, search, templates, import)
|
|
61
|
+
│ ├── test_compose.py # Composition engine tests
|
|
62
|
+
│ ├── test_formatter.py # Formatter output tests (Cursor, Claude, AGENTS.md, etc.)
|
|
63
|
+
│ ├── test_library.py # save/load/library tests
|
|
64
|
+
│ ├── test_login.py # Login/logout + remote sync tests (mocked RegistryClient)
|
|
65
|
+
│ ├── test_scanner.py # Scanner + file parsing tests (mdc, CLAUDE.md, .windsurfrules)
|
|
66
|
+
│ ├── test_store.py # Store read/write tests (.writ/ and ~/.writ/)
|
|
67
|
+
│ ├── test_models.py # Pydantic model tests
|
|
68
|
+
│ └── test_linter.py # Lint rule tests
|
|
69
|
+
├── .cursor/ # See .cursor-treeview.mdc for full breakdown
|
|
70
|
+
├── pyproject.toml # Package metadata, deps, CLI entry point ([project.scripts] writ)
|
|
71
|
+
├── README.md # Project overview, install, quickstart, command list
|
|
72
|
+
├── LICENSE # MIT
|
|
73
|
+
├── AGENTS.md # Dogfooding -- our own tool manages this
|
|
74
|
+
├── .gitignore
|
|
75
|
+
└── .github/
|
|
76
|
+
└── workflows/
|
|
77
|
+
├── ci.yml # pytest + ruff linting on PR (3 OS x 3 Python versions)
|
|
78
|
+
└── publish.yml # Github actions publish workflow, PyPI
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### The `.writ/` directory (created by `writ init` in user repos)
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
.writ/ # Per-project store
|
|
85
|
+
├── config.yaml # Tool settings (active formats, registry URL)
|
|
86
|
+
├── agents/ # Agent definitions for this project
|
|
87
|
+
│ └── *.yaml # One YAML file per agent
|
|
88
|
+
├── handoffs/ # Context handoff data between agents
|
|
89
|
+
├── memory/ # Importable cross-project memory
|
|
90
|
+
└── project-context.md # Auto-generated project context (from scanner)
|
|
91
|
+
|
|
92
|
+
~/.writ/ # Global store (local cache of remote)
|
|
93
|
+
├── config.yaml # Global preferences, auth token
|
|
94
|
+
├── agents/ # Personal agent library (synced to api.enwrit.com when logged in)
|
|
95
|
+
│ └── *.yaml
|
|
96
|
+
├── memory/ # Cross-project memory exports
|
|
97
|
+
│ └── *.yaml # PLANNED: synced to remote backend
|
|
98
|
+
├── templates/ # PLANNED: user's custom templates
|
|
99
|
+
└── cache/ # PLANNED: registry search cache
|
|
100
|
+
```
|