agentme 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/.xdrs/agentme/edrs/application/003-javascript-project-tooling.md +41 -5
  2. package/.xdrs/agentme/edrs/application/010-golang-project-tooling.md +39 -15
  3. package/.xdrs/agentme/edrs/application/014-python-project-tooling.md +63 -5
  4. package/.xdrs/agentme/edrs/application/015-cli-tool-standards.md +25 -24
  5. package/.xdrs/agentme/edrs/application/018-ai-agent-development-standards.md +29 -11
  6. package/.xdrs/agentme/edrs/application/021-pragmatic-hexagonal-architecture.md +112 -0
  7. package/.xdrs/agentme/edrs/application/skills/001-create-javascript-project/SKILL.md +26 -11
  8. package/.xdrs/agentme/edrs/application/skills/003-create-golang-project/SKILL.md +31 -14
  9. package/.xdrs/agentme/edrs/application/skills/005-create-python-project/SKILL.md +56 -23
  10. package/.xdrs/agentme/edrs/devops/005-monorepo-structure.md +1 -1
  11. package/.xdrs/agentme/edrs/devops/006-github-pipelines.md +1 -1
  12. package/.xdrs/agentme/edrs/devops/008-common-targets.md +1 -1
  13. package/.xdrs/agentme/edrs/devops/017-tool-execution-and-scripting.md +1 -1
  14. package/.xdrs/agentme/edrs/governance/013-contributing-guide-requirements.md +1 -1
  15. package/.xdrs/agentme/edrs/index.md +1 -0
  16. package/.xdrs/agentme/edrs/observability/011-service-health-check-endpoint.md +1 -1
  17. package/.xdrs/agentme/edrs/principles/002-coding-best-practices.md +1 -1
  18. package/.xdrs/agentme/edrs/principles/004-unit-test-requirements.md +1 -1
  19. package/.xdrs/agentme/edrs/principles/007-project-quality-standards.md +3 -3
  20. package/.xdrs/agentme/edrs/principles/009-error-handling.md +1 -1
  21. package/.xdrs/agentme/edrs/principles/012-continuous-xdr-enrichment.md +2 -2
  22. package/.xdrs/agentme/edrs/principles/016-cross-language-module-structure.md +1 -1
  23. package/.xdrs/agentme/edrs/principles/articles/001-continuous-xdr-improvement.md +5 -5
  24. package/package.json +1 -1
@@ -19,7 +19,7 @@ What tooling and project structure should JavaScript/TypeScript projects follow
19
19
 
20
20
  Clear, consistent tooling and layout enable fast onboarding, reliable CI pipelines, and a predictable developer experience across projects.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### Tooling
25
25
 
@@ -46,6 +46,23 @@ Use a single `lib/tsconfig.json` for both build and type-aware linting. Keep co-
46
46
 
47
47
  When `tsconfig.json` extends `@tsconfig/node24/tsconfig.json`, the default `module` is `nodenext`. `ts-jest` still runs in CommonJS mode by default, so `lib/jest.config.js` MUST configure the `ts-jest` transform with an inline `tsconfig` override that sets `module: 'commonjs'`. Do not use the deprecated `globals['ts-jest']` configuration style.
48
48
 
49
+ #### Coverage
50
+
51
+ Jest must enforce 80% line and branch coverage, following [agentme-edr-004](../principles/004-unit-test-requirements.md). Configure thresholds in `lib/jest.config.js`:
52
+
53
+ ```js
54
+ coverageThreshold: {
55
+ global: {
56
+ lines: 80,
57
+ branches: 80,
58
+ },
59
+ },
60
+ coverageProvider: 'v8',
61
+ coverageDirectory: '.cache/coverage',
62
+ ```
63
+
64
+ Builds that miss the threshold must not be merged.
65
+
49
66
  #### Project structure
50
67
 
51
68
  ```
@@ -64,8 +81,14 @@ When `tsconfig.json` extends `@tsconfig/node24/tsconfig.json`, the default `modu
64
81
  │ ├── .cache/ # eslint, jest, tsc incremental state, coverage
65
82
  │ ├── dist/ # compiled files and packed .tgz artifacts
66
83
  │ └── src/ # all TypeScript source files
67
- │ ├── index.ts # public API re-exports
68
- └── *.test.ts # test files co-located with source
84
+ │ ├── index.ts # public API re-exports from app/
85
+ ├── adapters/ # I/O boundary layer (following agentme-edr-021)
86
+ │ │ ├── cli/ # inbound: CLI bootstrap and entry point
87
+ │ │ ├── http/ # inbound: HTTP server bootstrap and handlers
88
+ │ │ └── connectors/ # outbound: one folder per external resource
89
+ │ ├── app/ # core business logic
90
+ │ │ └── *.test.ts # test files co-located with source
91
+ │ └── shared/ # infrastructure-agnostic utilities
69
92
  ├── examples/ # runnable usage examples outside the module root
70
93
  │ ├── Makefile # build + test all examples in sequence
71
94
  │ ├── usage-x/ # first example
@@ -78,9 +101,20 @@ When `tsconfig.json` extends `@tsconfig/node24/tsconfig.json`, the default `modu
78
101
 
79
102
  The root `Makefile` delegates every target to `/lib` then `/examples` in sequence. Parent Makefiles should call child Makefiles directly, and each module Makefile is responsible for running its actual tool commands through `mise exec --`.
80
103
 
104
+ Internal source code MUST be organized following [agentme-edr-021](021-pragmatic-hexagonal-architecture.md): `adapters/` (inbound and outbound I/O boundaries), `app/` (business logic), and `shared/` (infrastructure-agnostic utilities). The public API entry point (`index.ts`) re-exports from `app/`.
105
+
81
106
  When a repository contains multiple JavaScript/TypeScript packages, each package MUST live in its own module folder such as `lib/my-package/` or `services/my-service/`, each with its own `Makefile`, `README.md`, `dist/`, and `.cache/`.
82
107
 
83
- Persistent caches MUST live under `.cache/`. Recommended locations are Jest `cacheDirectory`, ESLint `--cache-location`, TypeScript `tsBuildInfoFile`, and coverage outputs.
108
+ All tool caches, incremental state files, and workspace-local config outputs MUST be written under `.cache/`. This applies to every tool without exception. Cache and state paths MUST be declared in the tool's own configuration file — never on the command line — so that the location is enforced regardless of how the tool is invoked:
109
+
110
+ | Tool | Config file | Setting | Value |
111
+ |------|------------|---------|-------|
112
+ | **Jest** | `jest.config.js` | `cacheDirectory` | `.cache/jest` |
113
+ | **ESLint** | `eslint.config.mjs` | `cache: true, cacheLocation: '.cache/eslint'` | (set in config object) |
114
+ | **TypeScript** | `tsconfig.json` | `tsBuildInfoFile` | `.cache/tsbuildinfo` |
115
+ | **Jest coverage** | `jest.config.js` | `coverageDirectory` | `.cache/coverage` |
116
+
117
+ No tool MUST write cache or state files to the project root, `src/`, or any other directory outside `.cache/`. Passing cache paths as Makefile or CLI flags instead of config-file settings is not allowed.
84
118
 
85
119
  Contributors and CI MUST invoke the commands below as `make <target>`. The Makefile recipes themselves MUST call the underlying tools through `mise exec -- <tool> ...`.
86
120
 
@@ -93,7 +127,7 @@ Contributors and CI MUST invoke the commands below as `make <target>`. The Makef
93
127
  | `build-module` | `mise exec -- pnpm exec tsc ...` only (no pack) |
94
128
  | `lint` | `mise exec -- pnpm exec eslint ./src` |
95
129
  | `lint-fix` | `mise exec -- pnpm exec eslint ./src --fix` |
96
- | `test` | `mise exec -- pnpm exec jest --verbose` |
130
+ | `test` | `mise exec -- pnpm exec jest --verbose --coverage` |
97
131
  | `test-watch` | `mise exec -- pnpm exec jest --watch` |
98
132
  | `clean` | remove `node_modules/`, `dist/`, and `.cache/` |
99
133
  | `all` | `build lint test` |
@@ -120,5 +154,7 @@ The examples folder MUST exist for any libraries and utilities that are publishe
120
154
 
121
155
  ## References
122
156
 
157
+ - [agentme-edr-004](../principles/004-unit-test-requirements.md) — Coverage and unit-test baseline
158
+ - [agentme-edr-021](021-pragmatic-hexagonal-architecture.md) — Internal adapter/application layer separation for applications
123
159
  - [001-create-javascript-project](skills/001-create-javascript-project/SKILL.md) — scaffolds a new project following this structure
124
160
 
@@ -19,7 +19,7 @@ What tooling and project structure should Go projects follow to ensure consisten
19
19
 
20
20
  A predictable layout and minimal external tooling keep Go projects approachable, fast to build, and easy to distribute as cross-platform binaries.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### Tooling
25
25
 
@@ -47,16 +47,25 @@ Direct installation of project-required Go CLIs with `go install ...@latest` as
47
47
  ├── main.go # binary entry point — argument dispatch only, no logic
48
48
  ├── .cache/ # GOCACHE, GOMODCACHE, golangci-lint cache, coverage
49
49
  ├── dist/ # built binaries and packaged outputs
50
- ├── <feature-a>/ # domain package (e.g. ownership/, changes/, utils/)
51
- │ ├── *.go # business logic
52
- │ └── *_test.go # unit tests co-located with source
53
- ├── <feature-b>/
54
- │ └── ...
55
- ├── cli/ # CLI wiring — ties flags to domain packages
56
- │ ├── <feature-a>/
50
+ ├── adapters/ # I/O boundary layer (following agentme-edr-021)
51
+ │ ├── cli/ # inbound: CLI wiring — flag parsing, output formatting
52
+ └── *.go # subfolders per feature only when complexity warrants it
53
+ ├── http/ # inbound: HTTP server bootstrap and handlers
57
54
  │ │ └── *.go
55
+ │ └── connectors/ # outbound: one folder per external resource
56
+ │ ├── postgres/
57
+ │ │ └── *.go
58
+ │ └── stripe-api/
59
+ │ └── *.go
60
+ ├── app/ # core business logic packages
61
+ │ ├── <feature-a>/
62
+ │ │ ├── *.go
63
+ │ │ └── *_test.go
58
64
  │ └── <feature-b>/
59
- └── *.go
65
+ ├── *.go
66
+ │ └── *_test.go
67
+ ├── shared/ # infrastructure-agnostic utilities shared across adapters and app
68
+ │ └── *.go
60
69
  ├── tests_integration/ # optional integration tests for this module
61
70
  ├── tests_benchmark/ # optional benchmark harnesses and datasets
62
71
  └── examples/ # optional sibling consumer examples for libraries
@@ -64,12 +73,16 @@ Direct installation of project-required Go CLIs with `go install ...@latest` as
64
73
 
65
74
  **Key layout rules:**
66
75
 
76
+ - Internal source code is organized following [agentme-edr-021](021-pragmatic-hexagonal-architecture.md): `adapters/` (inbound and outbound I/O boundaries), `app/` (business logic), and `shared/` (infrastructure-agnostic utilities).
67
77
  - One Go module per project (`go.mod` at the project root). In a monorepo, each Go project has its own `go.mod` in its subdirectory. No nested modules within a single project unless explicitly justified.
68
78
  - In a multi-module repository, each Go module MUST live in its own folder root with its own `Makefile`, `README.md`, `dist/`, and `.cache/`.
69
- - `main.go` is solely an argument dispatcher — it reads `os.Args[1]` and delegates to a `cli/<feature>/Run*()` function. No domain logic lives in `main.go`.
70
- - Business logic lives in named feature packages at the root (e.g., `ownership/`, `changes/`, `utils/`). These packages are importable and testable without any CLI concerns.
71
- - `cli/` packages own flag parsing, output formatting, and the wiring between flags and domain functions. No business logic lives in `cli/`.
79
+ - `main.go` is solely an argument dispatcher — it reads `os.Args[1]` and delegates to an `adapters/cli/<feature>/Run*()` function. No domain logic lives in `main.go`.
80
+ - Business logic lives in named feature packages under `app/` (e.g., `app/ownership/`, `app/changes/`). These packages are importable and testable without any CLI or adapter concerns.
81
+ - `adapters/cli/` packages own flag parsing, output formatting, and the wiring between flags and `app/` functions. No business logic lives in adapter packages.
82
+ - Outbound adapters live under `adapters/connectors/` with one subfolder per external resource, named descriptively (e.g., `postgres/`, `stripe-api/`, `redis-cache/`).
83
+ - `shared/` must contain only infrastructure-agnostic utilities — not business rules or domain logic.
72
84
  - Packages are flat by default; sub-packages are only introduced when a feature package itself exceeds ~400 lines or has clearly separable sub-concerns.
85
+ - Application MAY import from Adapters when it simplifies the design (pragmatic coupling per edr-021 rule 05).
73
86
  - Consumer examples for reusable libraries belong in a sibling `examples/` folder and MUST import the public module path rather than reaching into internal source paths. Because Go libraries are not typically consumed from a local packaged artifact, local example validation may use a temporary module replacement for resolution, but the import path MUST remain the public module path.
74
87
 
75
88
  #### go.mod
@@ -94,7 +107,8 @@ Direct installation of project-required Go CLIs with `go install ...@latest` as
94
107
  | `test-unit` | `mise exec -- go test -cover ./...` — alias for unit tests only (same here; integration tests get a separate tag) |
95
108
  | `coverage` | `mise exec -- go tool cover -func .cache/coverage.out` — displays coverage summary |
96
109
  | `clean` | Remove `dist/` and `.cache/` |
97
- | `start` | `mise exec -- go run ./ <default-args>` — launch the binary locally for dev use |
110
+ | `run` | `mise exec -- go run ./ <default-args>` — launch the binary locally |
111
+ | `run-http` | `mise exec -- go run ./ http` — launch the HTTP inbound adapter |
98
112
  | `publish` | Tag with `mise exec -- npx -y monotag ...`, then push tag + binaries to GitHub Releases |
99
113
 
100
114
  The required invocation pattern is:
@@ -125,7 +139,16 @@ When the project produces a CLI binary for end-users:
125
139
  - Benchmarks: keep simple `Benchmark*` functions co-located in `*_test.go`; use `tests_benchmark/` when the benchmark needs dedicated harnesses or datasets.
126
140
  - Integration or slow tests: guard with `//go:build integration` and keep them in `tests_integration/` when they are not naturally co-located with one package.
127
141
 
128
- Redirect Go tool caches into `.cache/` using `GOCACHE`, `GOMODCACHE`, and `GOLANGCI_LINT_CACHE` from the module `Makefile` so the repository does not accumulate scattered cache directories.
142
+ All tool caches, incremental state files, and build outputs MUST be written under `.cache/`. Neither `go` nor `golangci-lint` support a project-level config file for cache paths, so environment variables are the only available mechanism. These MUST be declared as top-level exports at the top of the module `Makefile` (not passed as per-recipe CLI flags or inline env overrides) so they apply to every recipe consistently:
143
+
144
+ | Tool | Mechanism | Makefile export |
145
+ |------|-----------|------------------|
146
+ | **Go build cache** | `GOCACHE` env var | `export GOCACHE := $(CURDIR)/.cache/go-build` |
147
+ | **Go module cache** | `GOMODCACHE` env var | `export GOMODCACHE := $(CURDIR)/.cache/go-mod` |
148
+ | **golangci-lint cache** | `GOLANGCI_LINT_CACHE` env var | `export GOLANGCI_LINT_CACHE := $(CURDIR)/.cache/golangci-lint` |
149
+ | **Test coverage output** | `-coverprofile` flag in `test` target | `.cache/coverage.out` |
150
+
151
+ No tool MUST write cache or state files to the project root or any directory outside `.cache/`. Passing cache paths as per-recipe environment overrides instead of top-level Makefile exports is not allowed.
129
152
 
130
153
  #### Linting
131
154
 
@@ -151,8 +174,9 @@ Use `github.com/sirupsen/logrus` for structured logging. Set the log level from
151
174
 
152
175
  #### CLI flag parsing
153
176
 
154
- Use the standard library `flag` package for CLI flags. Each `cli/<feature>` package defines its own `FlagSet`, parses it from `os.Args[2:]`, and calls the corresponding domain function.
177
+ Use the standard library `flag` package for CLI flags. Each `adapters/cli/<feature>` package defines its own `FlagSet`, parses it from `os.Args[2:]`, and calls the corresponding `app/` function.
155
178
 
156
179
  ## References
157
180
 
181
+ - [agentme-edr-021](021-pragmatic-hexagonal-architecture.md) — Defines the adapter/application separation that this layout follows
158
182
  - [003-create-golang-project](skills/003-create-golang-project/SKILL.md) — scaffolds a new Go project following this structure
@@ -19,7 +19,7 @@ What tooling and project structure should Python projects follow to ensure consi
19
19
 
20
20
  A single dependency manager, isolated package internals under `lib/`, and a standard Makefile contract keep Python projects predictable for contributors and CI while keeping the repository root clean.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### Tooling
25
25
 
@@ -40,14 +40,24 @@ The repository root MUST define a `.mise.toml` that pins Python and uv. Contribu
40
40
 
41
41
  The root `.venv/` is the canonical environment location for both the library and all examples. Subdirectory commands must set `UV_PROJECT_ENVIRONMENT` to the workspace root `.venv/` instead of creating nested virtual environments.
42
42
 
43
- Persistent caches must live under `.cache/`, preferably the module `lib/.cache/` plus a shared root `.cache/uv/` when uv cache sharing is desired.
43
+ All tool caches, incremental state files, and workspace-local outputs MUST be written under `.cache/`. Cache paths MUST be declared in the tool's own configuration file never on the command line or as Makefile CLI flags — so the location is enforced regardless of how the tool is invoked. Configure the following in `lib/pyproject.toml`:
44
+
45
+ | Tool | Config section | Setting | Value |
46
+ |------|---------------|---------|-------|
47
+ | **Ruff** | `[tool.ruff]` | `cache-dir` | `".cache/ruff"` |
48
+ | **pytest** | `[tool.pytest.ini_options]` | `cache_dir` | `".cache/pytest"` |
49
+ | **coverage** | `[tool.coverage.run]` | `data_file` | `".cache/.coverage"` |
50
+ | **coverage HTML** | `[tool.coverage.html]` | `directory` | `".cache/coverage-html"` |
51
+ | **uv** | `[tool.uv]` in `lib/pyproject.toml` | `cache-dir` | `".cache/uv"` |
52
+
53
+ No tool MUST write cache or state files to the project root, `src/`, `tests/`, or any directory outside `.cache/`. Passing cache paths as CLI flags or Makefile recipe-level env overrides instead of `pyproject.toml` settings is not allowed.
44
54
 
45
55
  #### Project structure
46
56
 
47
57
  ```text
48
58
  /
49
59
  ├── .mise.toml # required; pins Python and uv
50
- ├── .gitignore
60
+ ├── .gitignore # MUST ignore .venv/, dist/, .cache/, __pycache__/
51
61
  ├── .cache/ # optional shared uv cache at repo level
52
62
  ├── .venv/ # shared uv environment for lib/ and examples/
53
63
  ├── Makefile # root entry point; delegates to lib/ and runs examples/
@@ -61,8 +71,12 @@ Persistent caches must live under `.cache/`, preferably the module `lib/.cache/`
61
71
  │ ├── src/
62
72
  │ │ └── <package_name>/
63
73
  │ │ ├── __init__.py
64
- │ │ ├── __main__.py # when the project exposes a CLI
65
- │ │ └── ...
74
+ │ │ ├── adapters/ # I/O boundary layer (following agentme-edr-021)
75
+ │ │ │ ├── cli/ # inbound: CLI bootstrap and entry point
76
+ │ │ │ ├── http/ # inbound: HTTP server bootstrap
77
+ │ │ │ └── connectors/ # outbound: one folder per external resource
78
+ │ │ ├── app/ # core business logic
79
+ │ │ └── shared/ # infrastructure-agnostic utilities
66
80
  │ ├── tests/
67
81
  │ │ ├── conftest.py # shared fixtures when needed
68
82
  │ │ └── test_*.py
@@ -82,6 +96,8 @@ Keep the repository root clean: source code, tests, distribution artifacts, and
82
96
 
83
97
  Use the `lib/src/` layout for import safety and packaging clarity. Keep tests under `lib/tests/` and shared test setup in `lib/tests/conftest.py`. Do not introduce `requirements.txt`, `setup.py`, `setup.cfg`, `tox.ini`, `ruff.toml`, or `pyrightconfig.json` by default; keep project metadata and tool configuration in `lib/pyproject.toml`.
84
98
 
99
+ Internal source code MUST be organized following [agentme-edr-021](021-pragmatic-hexagonal-architecture.md): `adapters/` (inbound and outbound I/O boundaries), `app/` (business logic), and `shared/` (infrastructure-agnostic utilities).
100
+
85
101
  Libraries and shared utilities must include an `examples/` folder and wire example execution into the root `test` flow, following [agentme-edr-007](../principles/007-project-quality-standards.md). Each example directory is its own Python project with its own `pyproject.toml`, and examples must import the library as a consumer would rather than reaching back into `lib/src/` with relative imports. Local example verification must install the wheel built into `lib/dist/`; do not use editable or path-based dependencies back to `lib/`.
86
102
 
87
103
  Python keeps unit tests under `lib/tests/` by default because that remains the more common and maintainable convention for typed/package-based projects than co-locating tests beside every source file. Integration tests belong in `lib/tests_integration/`, and benchmark harnesses belong in `lib/tests_benchmark/` when they are more than a single micro-benchmark helper.
@@ -98,6 +114,48 @@ When Pyright runs from `lib/`, configure it to discover the shared root virtual
98
114
 
99
115
  Ruff is the default formatter and linter. Do not add Black, isort, or Flake8 unless another XDR for that repository explicitly requires them.
100
116
 
117
+ All Python projects must configure the following sections in `lib/pyproject.toml`. The cache-related settings are mandatory per the `.cache/` policy above:
118
+
119
+ ```toml
120
+ [tool.pytest.ini_options]
121
+ cache_dir = ".cache/pytest"
122
+
123
+ [tool.coverage.run]
124
+ data_file = ".cache/.coverage"
125
+
126
+ [tool.coverage.html]
127
+ directory = ".cache/coverage-html"
128
+
129
+ [tool.uv]
130
+ cache-dir = ".cache/uv"
131
+
132
+ [tool.ruff]
133
+ cache-dir = ".cache/ruff"
134
+ output-format = "grouped"
135
+ line-length = 120
136
+ target-version = "py311"
137
+ src = ["src", "tests", "tests_integration"]
138
+
139
+ [tool.ruff.format]
140
+ docstring-code-format = true
141
+ line-ending = "lf"
142
+
143
+ [tool.ruff.lint]
144
+ task-tags = ["TODO"]
145
+ select = ["ERA", "FAST", "ANN", "ASYNC", "S", "BLE", "FBT", "B", "A", "COM",
146
+ "C4", "DTZ", "T10", "DJ", "EM", "EXE", "FIX", "INT", "ISC", "ICN", "LOG", "G",
147
+ "INP", "PIE", "T20", "PYI", "PT", "Q", "RSE", "RET", "SLF", "SIM", "SLOT", "TID",
148
+ "TC", "ARG", "PTH", "FLY", "I", "C90", "NPY", "PD", "N", "PERF", "E", "W",
149
+ "D", "F", "PGH", "PL", "UP", "FURB", "RUF", "TRY"]
150
+ ignore = ["ANN002", "ANN003", "ANN401", "D100", "D101", "D102", "D103", "D104",
151
+ "D105", "D106", "D107", "COM812", "D203", "D213", "D400", "D401", "D404", "D415", "FIX002"]
152
+
153
+ [tool.ruff.lint.pycodestyle]
154
+ ignore-overlong-task-comments = true
155
+ ```
156
+
157
+ Adjust `target-version` to match the project's minimum supported Python version. The `cache-dir` keeps Ruff's cache under `.cache/ruff` alongside other tool caches. The `src` list must include every directory that contains importable Python code. The `select` list enables a broad set of rules covering style, correctness, performance, security, and documentation. The `ignore` list suppresses rules that are either too noisy or conflict with the chosen docstring style.
158
+
101
159
  Pyright must run on every lint pass. `typeCheckingMode = "standard"` is the minimum baseline; projects may raise this to `strict` when the codebase is ready.
102
160
 
103
161
  Pytest coverage must fail below 80% line and branch coverage, following [agentme-edr-004](../principles/004-unit-test-requirements.md).
@@ -19,7 +19,7 @@ What structure and interface rules should distributable CLI tools follow so they
19
19
 
20
20
  This keeps the user-facing command predictable while preserving a clean library API for embedding, testing, and automation.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### CLI command surface
25
25
 
@@ -32,34 +32,34 @@ This keeps the user-facing command predictable while preserving a clean library
32
32
  - `--verbose` on the root command and on subcommands when flags are parsed per command
33
33
  - Root `--help` output must list all available commands, key options, and usage examples. Command-specific help must describe that command's arguments and options.
34
34
 
35
- #### CLI to library separation
35
+ #### CLI to application separation
36
36
 
37
- - Structure the software as `cli -> lib`.
38
- - The CLI layer must only parse arguments, load config, call the library, and format output.
39
- - Domain logic must live in the library and be usable without CLI globals such as `argv`, `stdout`, or process exit handlers.
40
- - Every feature available through the CLI must also be available through the library API.
41
- - Organize the library by action so the mapping stays direct and obvious.
42
- - `extract` command -> `extract(...)`
43
- - `validate` command -> `validate(...)`
44
- - Avoid one generic library `run()` entry point that hides action-specific contracts behind switches or string commands.
37
+ - Structure the software as `cli -> app` — the CLI adapter delegates to the application layer, following [agentme-edr-021](021-pragmatic-hexagonal-architecture.md).
38
+ - The CLI layer must only parse arguments, load config, call the application layer, and format output.
39
+ - Domain logic must live in the application layer and be usable without CLI globals such as `argv`, `stdout`, or process exit handlers.
40
+ - Every feature available through the CLI must also be available through the application API.
41
+ - Organize the application layer by action so the mapping stays direct and obvious.
42
+ - `extract` command -> `app/extract(...)`
43
+ - `validate` command -> `app/validate(...)`
44
+ - Avoid one generic `run()` entry point that hides action-specific contracts behind switches or string commands.
45
45
 
46
- #### Library API shape
46
+ #### Application API shape
47
47
 
48
- - Each CLI action should map to a dedicated exported API with typed inputs and outputs appropriate for the language.
49
- - Library APIs should accept in-memory options objects or typed parameters, not require config files or environment variables unless library-level config-file support is an explicit requirement.
50
- - The CLI layer is responsible for translating flags, positional arguments, and config-file contents into library inputs.
51
- - The library should return explicit results and errors so the CLI can decide what to print and which exit code to use.
48
+ - Each CLI action should map to a dedicated exported application function with typed inputs and outputs appropriate for the language.
49
+ - Application APIs should accept in-memory options objects or typed parameters, not require config files or environment variables unless application-level config-file support is an explicit requirement.
50
+ - The CLI layer is responsible for translating flags, positional arguments, and config-file contents into application inputs.
51
+ - The application layer should return explicit results and errors so the CLI can decide what to print and which exit code to use.
52
52
 
53
53
  #### Configuration
54
54
 
55
55
  - Prefer flags and positional arguments for simple inputs.
56
56
  - When configuration becomes long, nested, or repetitive, support a config file instead of pushing all values into flags.
57
- - By default, config-file discovery and loading must happen in the CLI layer, not in the library layer.
57
+ - By default, config-file discovery and loading must happen in the CLI layer, not in the application layer.
58
58
  - When a config file is supported, the CLI should try to load a JSON config file from `[cwd]/.[cli-name]rc` by default.
59
59
  - The CLI should also support an explicit config path flag such as `--config`.
60
60
  - For JavaScript tools, `cosmiconfig` is an acceptable implementation. Equivalent discovery libraries are acceptable in other ecosystems.
61
- - The library must not depend on the presence of the config file; it should receive parsed configuration values from the CLI layer.
62
- - The library may load or parse config files only when that behavior is an explicit requirement of the library contract for non-CLI consumers as well.
61
+ - The application layer must not depend on the presence of the config file; it should receive parsed configuration values from the CLI layer.
62
+ - The application layer may load or parse config files only when that behavior is an explicit requirement of the application contract for non-CLI consumers as well.
63
63
 
64
64
  #### Output and progress
65
65
 
@@ -73,14 +73,14 @@ This keeps the user-facing command predictable while preserving a clean library
73
73
 
74
74
  - Exit with `0` only when the requested action completed successfully.
75
75
  - Exit with `1` when the requested action could not be completed.
76
- - The library should surface failure as return values, result objects, or language-idiomatic errors; the CLI is responsible for converting that outcome into user-facing messages and process exit codes.
76
+ - The application layer should surface failure as return values, result objects, or language-idiomatic errors; the CLI is responsible for converting that outcome into user-facing messages and process exit codes.
77
77
 
78
78
  #### Documentation
79
79
 
80
80
  - `README.md` must include at least 4 CLI usage examples.
81
- - `README.md` must include at least 2 library API examples for the same operation also available through the CLI.
81
+ - `README.md` must include at least 2 application API examples for the same operation also available through the CLI.
82
82
  - If the tool supports config files, at least 1 README example should show config-file usage.
83
- - Examples must use the public command and public library API, not internal modules or private files.
83
+ - Examples must use the public command and public application API, not internal modules or private files.
84
84
 
85
85
  #### Distribution and versioning
86
86
 
@@ -93,12 +93,13 @@ This keeps the user-facing command predictable while preserving a clean library
93
93
  ## Considered Options
94
94
 
95
95
  * (REJECTED) **Ad hoc CLIs with embedded business logic** - Keep parsing, processing, config loading, and output formatting inside a single entry point.
96
- * Reason: Makes the tool hard to test, hard to reuse as a library, and inconsistent across commands.
97
- * (CHOSEN) **Thin CLI adapter over action-oriented library APIs** - Keep the CLI responsible for user interaction and the library responsible for the actual behavior.
98
- * Reason: Preserves a clean programmatic API, keeps command behavior discoverable, and makes the CLI-to-library mapping easy to maintain.
96
+ * Reason: Makes the tool hard to test, hard to reuse programmatically, and inconsistent across commands.
97
+ * (CHOSEN) **Thin CLI adapter over action-oriented application APIs** - Keep the CLI responsible for user interaction and the application layer responsible for the actual behavior.
98
+ * Reason: Preserves a clean programmatic API, keeps command behavior discoverable, and makes the CLI-to-application mapping easy to maintain.
99
99
 
100
100
  ## References
101
101
 
102
+ - [agentme-edr-021](021-pragmatic-hexagonal-architecture.md) - Defines the adapter/application separation that the CLI layer follows
102
103
  - [agentme-edr-003](003-javascript-project-tooling.md) - JavaScript project packaging and structure
103
104
  - [agentme-edr-007](../principles/007-project-quality-standards.md) - README and examples baseline
104
105
  - [agentme-edr-008](../devops/008-common-targets.md) - Standard command names for project entry points
@@ -91,22 +91,35 @@ Agent flows MUST include at least one explicit verification node before producin
91
91
 
92
92
  #### 07-workflow-structure
93
93
 
94
- Agent logic MUST be organized as named workflows. Each workflow is an independent LangGraph `StateGraph` with a defined start node and end node, connecting agents, states, routes, and decision nodes.
94
+ Agent logic MUST be organized as named workflows following [agentme-edr-021](021-pragmatic-hexagonal-architecture.md). Each workflow is an independent LangGraph `StateGraph` with a defined start node and end node, connecting agents, states, routes, and decision nodes.
95
95
 
96
- For each workflow named `<workflow>`, create:
96
+ Workflows live inside `app/workflows/` (the application layer), while external integrations such as LLM providers, vector stores, and third-party APIs live under `adapters/connectors/` (the outbound adapter layer). Inbound interfaces (HTTP API, CLI) live under `adapters/` as inbound adapters.
97
+
98
+ For each workflow named `<workflow>`, the full project layout is:
97
99
 
98
100
  ```text
99
- lib/
100
- workflows/
101
- <workflow>/
102
- graph.py # StateGraph definition; entry point for the workflow
103
- agents.py # LangChain agent definitions used by this workflow
104
- states.py # Typed state dataclasses / TypedDicts
105
- routes.py # Conditional edge functions
101
+ lib/src/<package_name>/
102
+ adapters/
103
+ http/ # inbound: API server that triggers workflows
104
+ cli/ # inbound: CLI entry point (if applicable)
105
+ connectors/ # outbound: external resource integrations
106
+ openai/ # LLM provider connector
107
+ azure-openai/ # alternative LLM provider connector
108
+ postgres/ # database connector (if applicable)
109
+ vector-store/ # vector DB connector (if applicable)
110
+ app/
111
+ workflows/
112
+ <workflow>/
113
+ graph.py # StateGraph definition; entry point for the workflow
114
+ agents.py # LangChain agent definitions used by this workflow
115
+ states.py # Typed state dataclasses / TypedDicts
116
+ routes.py # Conditional edge functions
117
+ shared/ # infrastructure-agnostic utilities
106
118
  ```
107
119
 
108
- - `graph.py` MUST define and compile the `StateGraph` and expose a `graph` object that callers invoke.
109
- - Additional modules (tools, prompts, schemas) MAY be added inside `lib/workflows/<workflow>/` when they are specific to that workflow. Shared utilities belong in `lib/<module>/`.
120
+ - `app/workflows/<workflow>/graph.py` MUST define and compile the `StateGraph` and expose a `graph` object that callers invoke.
121
+ - Tool calls within workflow nodes that interact with external systems MUST use connectors from `adapters/connectors/`, not inline API calls.
122
+ - Additional modules (prompts, schemas) MAY be added inside `app/workflows/<workflow>/` when they are specific to that workflow. Shared utilities belong in `shared/`.
110
123
  - Each workflow MUST be documented with a Mermaid diagram in the project `README.md` following rule `05-flow-documentation`.
111
124
 
112
125
  #### 08-workflow-evals
@@ -154,3 +167,8 @@ Use deepagents whenever ANY of the following is true for a workflow or tool:
154
167
  - If the host-side code needs to pass files into the sandbox (e.g. generated config or input data), create a temporary directory with `tempfile.mkdtemp()`, write the files there, and mount it into the sandbox. Clean it up in the `finally` block.
155
168
  - Replace hand-rolled `read_file`, `search_files`, and `grep_file` tool implementations with the equivalent tools provided by deepagents.
156
169
 
170
+ ## References
171
+
172
+ - [agentme-edr-021](021-pragmatic-hexagonal-architecture.md) — Adapter/application layer separation that defines the project layout
173
+ - [agentme-edr-014](014-python-project-tooling.md) — Python project tooling and structure
174
+ - [agentme-edr-019](019-ml-dataset-structure.md) — ML dataset structure for eval datasets
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: agentme-edr-policy-021-pragmatic-hexagonal-architecture
3
+ description: Defines a pragmatic variant of Hexagonal Architecture for organizing application source code into Adapters (inbound/outbound I/O boundaries) and Application (business logic) layers, with explicit naming conventions and folder structure. Use when designing or reviewing the internal layout of application modules.
4
+ apply-to: All application projects
5
+ valid-from: 2026-05-28
6
+ ---
7
+
8
+ # agentme-edr-policy-021: Pragmatic hexagonal architecture
9
+
10
+ ## Context and Problem Statement
11
+
12
+ Applications often mix business logic with infrastructure concerns (database access, HTTP handling, environment variable reading), making code hard to test, refactor, and reuse.
13
+
14
+ How should application source code be organized to separate business logic from infrastructure while avoiding unnecessary abstraction layers?
15
+
16
+ ## Decision Outcome
17
+
18
+ **Organize application source code into three conceptual layers — External (not in codebase), Adapters (inbound/outbound I/O boundaries), and Application (business logic exposed as typed library interfaces) — following a pragmatic variant of Hexagonal Architecture that avoids unnecessary abstractions.**
19
+
20
+ ### Details
21
+
22
+ #### 01-three-layer-separation
23
+
24
+ Every application is conceptually divided into three layers:
25
+
26
+ | Layer | Description |
27
+ |-------|-------------|
28
+ | **External** | Systems outside the codebase boundary (databases, third-party APIs, message brokers, filesystems, users) |
29
+ | **Adapters** | Bridge between External and Application — translate external protocols into application calls and vice versa |
30
+ | **Application** | Business logic that delegates I/O to adapters |
31
+
32
+ #### 02-adapter-naming-conventions
33
+
34
+ **Inbound adapters** receive external requests or events and trigger application logic. Each gets a flat folder under `adapters/`:
35
+
36
+ - `cli/` — command-line interface entry point
37
+ - `http/` — HTTP/REST server
38
+ - `grpc/` — gRPC server
39
+ - `ws/` — WebSocket server
40
+ - `kafka/` — Kafka consumer
41
+ - `mqtt/` — MQTT subscriber
42
+ - Additional inbound adapters are allowed with descriptive names
43
+
44
+ **Outbound adapters** are called by the application to reach external systems. They live under `adapters/connectors/` with one subfolder per external resource, named descriptively:
45
+
46
+ - e.g.: `stripe-api/`, `config-file/`, `s3-datalake/`, `whatsapp/`, `postgres/`, `redis-cache/`
47
+
48
+ **Clarification:** "inbound" means the adapter triggers application logic in response to an external stimulus. "Outbound" means the application calls the adapter to interact with an external system.
49
+
50
+ #### 03-application-layer-rules
51
+
52
+ - Expose functionality as typed library interfaces
53
+ - All inputs must be explicitly passed as typed parameters
54
+ - No global variables, no direct environment variable access in `app/` or `shared/`
55
+ - Business logic with well-defined input/output behavior
56
+ - Group related logic into subfolders (aggregation roots)
57
+ - Environment variables must be read only in the bootstrap/entry-point layer of inbound adapters, converted into typed configuration objects, and passed explicitly to all other components
58
+
59
+ #### 04-mandatory-folder-structure
60
+
61
+ ```text
62
+ mysystem/
63
+ Makefile # targets to run different inbound interfaces (e.g. run-http, run-cli)
64
+ src/
65
+ adapters/ # mandatory
66
+ cli/ # if CLI exists — bootstrap/entry point for CLI
67
+ http/ # if HTTP server exists — bootstrap/entry point for HTTP
68
+ grpc/ # if gRPC exists
69
+ connectors/ # if external resource access exists
70
+ postgres/ # one folder per external resource
71
+ stripe-api/
72
+ app/ # mandatory — core business logic
73
+ feature1.ts
74
+ feature-group/ # optional subfolders for grouping
75
+ shared/ # utilities and functions shared among adapters and app
76
+ logging.ts
77
+ errors.ts
78
+ ```
79
+
80
+ `shared/` must contain only infrastructure-agnostic utilities — not business rules or domain logic.
81
+
82
+ #### 05-pragmatic-coupling
83
+
84
+ - Application MAY import from Adapters when it simplifies the design
85
+ - Avoid excessive abstractions, interface types, and indirection layers
86
+ - Only introduce interfaces or abstract types when building a framework where the extra complexity demonstrably pays off
87
+ - Prefer concrete implementations over abstract ports — skip the purism of classic Hexagonal Architecture in favor of practicality
88
+ - Some coupling between Application and Adapters is acceptable and expected
89
+
90
+ #### 06-bootstrap-and-entry-points
91
+
92
+ - Each inbound adapter folder (`cli/`, `http/`, `grpc/`, etc.) contains the bootstrap and entry point for that interface
93
+ - The project root Makefile must have targets to run the different inbound interfaces following [agentme-edr-008](../devops/008-common-targets.md) extension conventions (e.g. `run-http`, `run-grpc`)
94
+ - Bootstrap code lives in the adapter that receives inbound requests, not in a separate wiring layer
95
+
96
+ #### 07-minimum-complexity-threshold
97
+
98
+ - Trivial scripts and single-purpose tools (fewer than ~300 lines with a single I/O boundary) MAY skip this layering
99
+ - All other projects MUST use this structure from the start
100
+
101
+ #### 08-examples-of-data-flow
102
+
103
+ ```text
104
+ HTTP request → adapters/http/ → app/create-user → adapters/connectors/postgres/
105
+ CLI command → adapters/cli/ → app/create-dir → adapters/connectors/local-fs/
106
+ Kafka message → adapters/kafka/ → app/process-event → adapters/connectors/stripe-api/
107
+ ```
108
+
109
+ ## References
110
+
111
+ - [agentme-edr-016](../principles/016-cross-language-module-structure.md) — Defines the module-root structure (Makefile, dist/, .cache/) that wraps this internal layout
112
+ - [agentme-edr-002](../principles/002-coding-best-practices.md) — File size limits and code organization practices that complement this architecture
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: agentme-edr-skill-001-create-javascript-project
3
3
  description: >
4
- Scaffolds the initial boilerplate structure for a JavaScript/TypeScript library project following
4
+ Scaffolds the initial boilerplate structure for a JavaScript/TypeScript project following
5
5
  the standard tooling and layout defined in agentme-edr-003. Activate this skill when the user
6
- asks to create, scaffold, or initialize a new JavaScript or TypeScript library project, npm
6
+ asks to create, scaffold, or initialize a new JavaScript or TypeScript project, npm
7
7
  package, or similar project structure.
8
8
  metadata:
9
9
  author: flaviostutz
@@ -13,13 +13,14 @@ compatibility: JavaScript/TypeScript, Node.js 18+
13
13
 
14
14
  ## Overview
15
15
 
16
- Creates a complete JavaScript/TypeScript library project from scratch. The layout keeps the
17
- published package self-contained in its module root (`lib/`), places runnable consumer examples in
18
- the sibling `examples/` folder, redirects persistent caches into `.cache/`, and uses Makefiles as
19
- the only entry points. Boilerplate is derived from the [filedist](https://github.com/flaviostutz/filedist)
20
- project.
16
+ Creates a complete JavaScript/TypeScript project from scratch. The layout keeps the
17
+ package self-contained in its module root (`lib/`), organizes internal code following
18
+ [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md) (`adapters/`, `app/`, `shared/`),
19
+ places runnable consumer examples in the sibling `examples/` folder, redirects persistent caches
20
+ into `.cache/`, and uses Makefiles as the only entry points. Boilerplate is derived from the
21
+ [filedist](https://github.com/flaviostutz/filedist) project.
21
22
 
22
- Related EDRs: [agentme-edr-003](../../003-javascript-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md)
23
+ Related EDRs: [agentme-edr-003](../../003-javascript-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md), [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md)
23
24
 
24
25
  ## Instructions
25
26
 
@@ -82,7 +83,7 @@ dist/
82
83
 
83
84
  ### Phase 3: Create `lib/`
84
85
 
85
- **`lib/src/index.ts`** — public API entry point:
86
+ **`lib/src/app/hello.ts`** — business logic:
86
87
 
87
88
  ```typescript
88
89
  export const hello = (name: string): string => {
@@ -90,10 +91,10 @@ export const hello = (name: string): string => {
90
91
  };
91
92
  ```
92
93
 
93
- **`lib/src/index.test.ts`** — co-located unit test:
94
+ **`lib/src/app/hello.test.ts`** — co-located unit test:
94
95
 
95
96
  ```typescript
96
- import { hello } from './index';
97
+ import { hello } from './hello';
97
98
 
98
99
  describe('hello', () => {
99
100
  it('should return a greeting', () => {
@@ -102,6 +103,20 @@ describe('hello', () => {
102
103
  });
103
104
  ```
104
105
 
106
+ **`lib/src/index.ts`** — public API re-export from `app/`:
107
+
108
+ ```typescript
109
+ export { hello } from './app/hello';
110
+ ```
111
+
112
+ **`lib/src/adapters/`** — create empty directories for the hexagonal structure:
113
+
114
+ - `lib/src/adapters/` — inbound adapters (add `cli/`, `http/`, etc. as needed)
115
+ - `lib/src/adapters/connectors/` — outbound adapters (one folder per external resource)
116
+ - `lib/src/shared/` — infrastructure-agnostic utilities
117
+
118
+ Create a placeholder `.gitkeep` in `lib/src/adapters/` and `lib/src/shared/` so the directories are tracked.
119
+
105
120
  **`lib/Makefile`**:
106
121
 
107
122
  ```makefile
@@ -12,9 +12,9 @@ compatibility: Go 1.21+
12
12
 
13
13
  ## Overview
14
14
 
15
- Creates a complete Go CLI project from scratch, following the layout from [agentme-edr-010](../../010-golang-project-tooling.md). Business logic lives in named feature packages; CLI wiring lives in `cli/<feature>/`; `main.go` is a thin dispatcher. The module root owns its `Makefile`, `README.md`, `dist/`, and `.cache/` folders.
15
+ Creates a complete Go project from scratch, following the layout from [agentme-edr-010](../../010-golang-project-tooling.md) and [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md). Business logic lives in `app/<feature>/` packages; CLI wiring lives in `adapters/cli/`; outbound integrations live in `adapters/connectors/`; `main.go` is a thin dispatcher. The module root owns its `Makefile`, `README.md`, `dist/`, and `.cache/` folders.
16
16
 
17
- Related EDRs: [agentme-edr-010](../../010-golang-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md)
17
+ Related EDRs: [agentme-edr-010](../../010-golang-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md), [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md)
18
18
 
19
19
  ## Instructions
20
20
 
@@ -67,7 +67,7 @@ import (
67
67
  "fmt"
68
68
  "os"
69
69
 
70
- cli[Feature] "[module]/cli/[feature]"
70
+ cli "[module]/adapters/cli"
71
71
  )
72
72
 
73
73
  func main() {
@@ -78,7 +78,7 @@ func main() {
78
78
 
79
79
  switch os.Args[1] {
80
80
  case "[subcommand]":
81
- cli[Feature].Run(os.Args)
81
+ cli.Run[Feature](os.Args)
82
82
  default:
83
83
  fmt.Printf("Unknown command: %s\n", os.Args[1])
84
84
  fmt.Println("Usage: [binary] [[feature]]")
@@ -216,7 +216,7 @@ coverage.out
216
216
 
217
217
  ### Phase 3: Create the feature package
218
218
 
219
- **`[feature]/[feature].go`** (replace `[feature]`, `[Feature]`):
219
+ **`app/[feature]/[feature].go`** (replace `[feature]`, `[Feature]`):
220
220
 
221
221
  ```go
222
222
  package [feature]
@@ -246,7 +246,7 @@ func Run(opts Options) (Result, error) {
246
246
  }
247
247
  ```
248
248
 
249
- **`[feature]/[feature]_test.go`** (replace `[feature]`, `[Feature]`):
249
+ **`app/[feature]/[feature]_test.go`** (replace `[feature]`, `[Feature]`):
250
250
 
251
251
  ```go
252
252
  package [feature]
@@ -267,12 +267,12 @@ func Test[Feature]Run(t *testing.T) {
267
267
 
268
268
  ---
269
269
 
270
- ### Phase 4: Create the CLI package
270
+ ### Phase 4: Create the CLI adapter
271
271
 
272
- **`cli/[feature]/[feature].go`** (replace `[module]`, `[feature]`, `[Feature]`, `[subcommand]`):
272
+ **`adapters/cli/[feature].go`** (replace `[module]`, `[feature]`, `[Feature]`, `[subcommand]`):
273
273
 
274
274
  ```go
275
- package cli[Feature]
275
+ package cli
276
276
 
277
277
  import (
278
278
  "flag"
@@ -280,11 +280,11 @@ import (
280
280
  "os"
281
281
 
282
282
  "github.com/sirupsen/logrus"
283
- "[module]/[feature]"
283
+ "[module]/app/[feature]"
284
284
  )
285
285
 
286
- // Run parses CLI flags for the [subcommand] command and calls the domain package.
287
- func Run(args []string) {
286
+ // Run[Feature] parses CLI flags for the [subcommand] command and calls the domain package.
287
+ func Run[Feature](args []string) {
288
288
  fs := flag.NewFlagSet("[subcommand]", flag.ExitOnError)
289
289
  verbose := fs.Bool("verbose", false, "Show verbose logs during processing")
290
290
 
@@ -309,6 +309,21 @@ func Run(args []string) {
309
309
  }
310
310
  ```
311
311
 
312
+ **`shared/logging.go`** (optional, scaffold if needed):
313
+
314
+ ```go
315
+ package shared
316
+
317
+ import "github.com/sirupsen/logrus"
318
+
319
+ // SetupLogging configures the global log level.
320
+ func SetupLogging(verbose bool) {
321
+ if verbose {
322
+ logrus.SetLevel(logrus.DebugLevel)
323
+ }
324
+ }
325
+ ```
326
+
312
327
  ---
313
328
 
314
329
  ### Phase 5: Verify and run
@@ -327,8 +342,10 @@ Fix any compile or lint errors before finishing.
327
342
  ## Conventions and reminders
328
343
 
329
344
  - `main.go` dispatches only — no logic.
330
- - Business logic only in `[feature]/` packages — no flag parsing, no `fmt.Println` for diagnostics.
331
- - `cli/[feature]/` owns flags, output, and calls domain. No logic here beyond reading flags and printing results.
345
+ - Business logic only in `app/<feature>/` packages — no flag parsing, no `fmt.Println` for diagnostics.
346
+ - `adapters/cli/` owns flag parsing, output formatting, and the wiring between flags and `app/` functions. No business logic lives in adapter packages.
347
+ - Outbound adapters live under `adapters/connectors/` with one subfolder per external resource (e.g., `postgres/`, `stripe-api/`, `redis-cache/`).
348
+ - `shared/` must contain only infrastructure-agnostic utilities — not business rules or domain logic.
332
349
  - All tests co-located (`*_test.go` next to the file under test).
333
350
  - Use `tests_integration/` for integration flows and `tests_benchmark/` when benchmarks need dedicated harnesses or datasets.
334
351
  - Log with `logrus`; never use `fmt.Println` for diagnostic/debug output.
@@ -1,10 +1,9 @@
1
1
  ---
2
2
  name: agentme-edr-skill-005-create-python-project
3
3
  description: >
4
- Scaffolds the initial boilerplate structure for a Python library or CLI project following the
5
- standard tooling and layout defined in agentme-edr-014. Activate this skill when the user asks
6
- to create, scaffold, or initialize a new Python package, CLI, library, or similar project
7
- structure.
4
+ Scaffolds the initial boilerplate structure for a Python project following the standard tooling
5
+ and layout defined in agentme-edr-014. Activate this skill when the user asks to create,
6
+ scaffold, or initialize a new Python package, CLI, or similar project structure.
8
7
  metadata:
9
8
  author: flaviostutz
10
9
  version: "1.0"
@@ -14,11 +13,12 @@ compatibility: Python 3.12+
14
13
  ## Overview
15
14
 
16
15
  Creates a complete Python project from scratch using Mise, `uv`, `pyproject.toml`, Ruff,
17
- Pyright, Pytest, and Makefiles. The default layout keeps the library self-contained under `lib/`,
18
- uses a shared root `.venv/`, redirects persistent caches into `.cache/`, and places runnable
19
- consumer projects under the sibling `examples/` folder.
16
+ Pyright, Pytest, and Makefiles. The layout keeps the package self-contained under `lib/`,
17
+ organizes internal code following [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md)
18
+ (`adapters/`, `app/`, `shared/`), uses a shared root `.venv/`, redirects persistent caches into
19
+ `.cache/`, and places runnable consumer projects under the sibling `examples/` folder.
20
20
 
21
- Related EDRs: [agentme-edr-014](../../014-python-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md)
21
+ Related EDRs: [agentme-edr-014](../../014-python-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md), [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md)
22
22
 
23
23
  ## Instructions
24
24
 
@@ -30,7 +30,6 @@ Ask for or infer from context:
30
30
  - **Short description** - one sentence
31
31
  - **Author** name or GitHub username
32
32
  - **Python version** - default `3.13`
33
- - **Project kind** - `library` or `cli`
34
33
  - **Primary entry point** - first module or command name to scaffold
35
34
  - **GitHub repo URL** - optional, for project metadata
36
35
  - **Confirm target directory** - default: current workspace root
@@ -105,6 +104,7 @@ The root `Makefile` keeps the repository clean by delegating package work to `li
105
104
  .venv/
106
105
  dist/
107
106
  .cache/
107
+ __pycache__/
108
108
  ```
109
109
 
110
110
  **`./README.md`**
@@ -214,11 +214,28 @@ requires = ["hatchling>=1.27.0"]
214
214
  build-backend = "hatchling.build"
215
215
 
216
216
  [tool.ruff]
217
- line-length = 100
217
+ cache-dir = ".cache/ruff"
218
+ output-format = "grouped"
219
+ line-length = 120
218
220
  target-version = "py313"
221
+ src = ["src", "tests", "tests_integration"]
222
+
223
+ [tool.ruff.format]
224
+ docstring-code-format = true
225
+ line-ending = "lf"
219
226
 
220
227
  [tool.ruff.lint]
221
- select = ["E", "F", "I", "B", "UP"]
228
+ task-tags = ["TODO"]
229
+ select = ["ERA", "FAST", "ANN", "ASYNC", "S", "BLE", "FBT", "B", "A", "COM",
230
+ "C4", "DTZ", "T10", "DJ", "EM", "EXE", "FIX", "INT", "ISC", "ICN", "LOG", "G",
231
+ "INP", "PIE", "T20", "PYI", "PT", "Q", "RSE", "RET", "SLF", "SIM", "SLOT", "TID",
232
+ "TC", "ARG", "PTH", "FLY", "I", "C90", "NPY", "PD", "N", "PERF", "E", "W",
233
+ "D", "F", "PGH", "PL", "UP", "FURB", "RUF", "TRY"]
234
+ ignore = ["ANN002", "ANN003", "ANN401", "D100", "D101", "D102", "D103", "D104",
235
+ "D105", "D106", "D107", "COM812", "D203", "D213", "D400", "D401", "D404", "D415", "FIX002"]
236
+
237
+ [tool.ruff.lint.pycodestyle]
238
+ ignore-overlong-task-comments = true
222
239
 
223
240
  [tool.pyright]
224
241
  include = ["src", "tests"]
@@ -267,29 +284,37 @@ make test
267
284
 
268
285
  ### Phase 4: Create the package and tests inside `lib/`
269
286
 
270
- Create this baseline structure.
287
+ Create this baseline structure following [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md).
271
288
 
272
289
  **`lib/src/[package_name]/__init__.py`**
273
290
 
274
291
  ```python
275
- from .core import hello
292
+ from .app.hello import hello
276
293
 
277
294
  __all__ = ["hello"]
278
295
  ```
279
296
 
280
- **`lib/src/[package_name]/core.py`**
297
+ **`lib/src/[package_name]/app/__init__.py`**
298
+
299
+ ```python
300
+ ```
301
+
302
+ **`lib/src/[package_name]/app/hello.py`**
281
303
 
282
304
  ```python
283
305
  def hello(name: str) -> str:
284
306
  return f"Hello, {name}!"
285
307
  ```
286
308
 
287
- **`lib/src/[package_name]/__main__.py`**
309
+ **`lib/src/[package_name]/adapters/__init__.py`**
288
310
 
289
- Use this only for CLI-oriented projects.
311
+ ```python
312
+ ```
313
+
314
+ **`lib/src/[package_name]/adapters/cli/__init__.py`**
290
315
 
291
316
  ```python
292
- from .core import hello
317
+ from [package_name].app.hello import hello
293
318
 
294
319
 
295
320
  def main() -> None:
@@ -300,10 +325,17 @@ if __name__ == "__main__":
300
325
  main()
301
326
  ```
302
327
 
303
- **`lib/tests/test_core.py`**
328
+ **`lib/src/[package_name]/shared/__init__.py`**
329
+
330
+ ```python
331
+ ```
332
+
333
+ Create empty `adapters/connectors/` directory with a `.gitkeep` for outbound adapters.
334
+
335
+ **`lib/tests/test_hello.py`**
304
336
 
305
337
  ```python
306
- from [package_name].core import hello
338
+ from [package_name].app.hello import hello
307
339
 
308
340
 
309
341
  def test_hello() -> None:
@@ -314,9 +346,9 @@ If two or more test files need shared fixtures, create `lib/tests/conftest.py` a
314
346
 
315
347
  If the module needs slower end-to-end coverage, place those tests in `lib/tests_integration/`. Put dedicated benchmark harnesses in `lib/tests_benchmark/`.
316
348
 
317
- ### Phase 5: Create examples for libraries and utilities
349
+ ### Phase 5: Create examples
318
350
 
319
- If the project is a library or shared utility, add an `examples/` directory with one subdirectory per runnable consumer example. Each example must be its own Python project.
351
+ Add an `examples/` directory with one subdirectory per runnable consumer example. Each example must be its own Python project.
320
352
 
321
353
  **`examples/basic-usage/pyproject.toml`**
322
354
 
@@ -355,14 +387,15 @@ After creating the files:
355
387
 
356
388
  ## Examples
357
389
 
358
- **Input:** "Create a Python library called `event_tools`"
390
+ **Input:** "Create a Python project called `event_tools`"
359
391
  - Create `Makefile`, `README.md`, `lib/pyproject.toml`, `lib/Makefile`, `lib/src/event_tools/`, `lib/tests/`, and `examples/`
392
+ - Scaffold `adapters/`, `app/`, `shared/` directories inside `lib/src/event_tools/`
360
393
  - Add `lib/README.md`, `.cache/` handling, and install examples from the built wheel in `lib/dist/`
361
394
  - Configure `uv`, Ruff, Pyright, Pytest, `pytest-cov`, and `pip-audit`
362
395
  - Verify with `make lint-fix`, `make test`, and `make build`
363
396
 
364
397
  **Input:** "Scaffold a Python CLI package"
365
- - Add `lib/src/<package_name>/__main__.py`
398
+ - Add CLI entry point in `lib/src/<package_name>/adapters/cli/__init__.py`
366
399
  - Add `[project.scripts]` in `lib/pyproject.toml` when the command name must differ from the module name
367
400
  - Keep the same Makefile and quality checks
368
401
 
@@ -20,7 +20,7 @@ What monorepo structure, naming conventions, tooling, and build standards should
20
20
  For step-by-step scaffolding instructions see [skill 002-monorepo-setup](skills/002-monorepo-setup/SKILL.md).
21
21
  Module folder responsibilities, artifact locations, and test-folder conventions follow [agentme-edr-016](../principles/016-cross-language-module-structure.md).
22
22
 
23
- ### Implementation Details
23
+ ### Details
24
24
 
25
25
  #### 01-top-level-directory-layout
26
26
 
@@ -19,7 +19,7 @@ What GitHub Actions workflows should every project follow to ensure a safe, pred
19
19
 
20
20
  Separating these concerns eliminates accidental publishes from CI runs, ensures monotag has access to the full git history, and makes each workflow independently auditable and re-runnable.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### Workflow overview
25
25
 
@@ -19,7 +19,7 @@ What standard set of Makefile target names and execution rules should projects a
19
19
 
20
20
  Standardizing both the target names and the execution chain removes per-project guesswork, makes CI pipelines reusable, and keeps tooling behavior visible in one place.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### 01-every-project-must-have-root-makefile
25
25
 
@@ -19,7 +19,7 @@ How should projects execute development commands so the command surface stays pr
19
19
 
20
20
  This keeps local development and CI aligned, reduces indirection, and lets contributors understand project behavior by reading one command surface.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  - Every project MUST use a root `Makefile` as the authoritative entry point for developer and pipeline commands.
25
25
  - The target names in that `Makefile` MUST follow [agentme-edr-008](008-common-targets.md).
@@ -19,7 +19,7 @@ What contributor workflow guidance must every project publish so contributors kn
19
19
 
20
20
  Projects must keep a `CONTRIBUTING.md` file at the repository root. The file must explain where bugs, feature discussions, and code changes belong so contributors follow a predictable workflow before opening pull requests.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  - Every project **MUST** have a root `CONTRIBUTING.md`.
25
25
  - The guide **MUST** direct bug reports to issues.
@@ -32,6 +32,7 @@ Language and framework-specific tooling and project structure.
32
32
  - [agentme-edr-018](application/018-ai-agent-development-standards.md) - **AI agent development standards** - Standard toolchain, framework, evaluation, and workflow patterns for AI agent projects built with Python and LangGraph
33
33
  - [agentme-edr-019](application/019-ml-dataset-structure.md) - **ML dataset structure** - Standard folder layout and file conventions for ML datasets
34
34
  - [agentme-edr-020](application/020-ai-agent-xdrs-knowledge-layer.md) - **AI agent XDRS knowledge layer** - How to integrate XDRS as the runtime source of truth for policies and skills in AI agents (apply only when the project explicitly uses XDRS)
35
+ - [agentme-edr-021](application/021-pragmatic-hexagonal-architecture.md) - **Pragmatic hexagonal architecture** - Organize application layers as External/Adapters/Application with practical coupling rules
35
36
  - [004-select-relevant-xdrs](application/skills/004-select-relevant-xdrs/SKILL.md) - **Select relevant XDRs**
36
37
 
37
38
  ## Devops
@@ -19,7 +19,7 @@ How should services expose their health status and validate operational readines
19
19
 
20
20
  All services must expose a `GET /health` endpoint that validates external dependencies using read-only operations and returns structured status with appropriate HTTP codes.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  **Endpoint contract:**
25
25
 
@@ -17,7 +17,7 @@ What coding practices should be followed across all languages and projects to ke
17
17
 
18
18
  **Apply a set of language-agnostic structural and organizational practices that keep files small, logic decomposed, types co-located, tests co-located, and documentation always in sync.**
19
19
 
20
- ### Implementation Details
20
+ ### Details
21
21
 
22
22
  #### 01-keep-files-short
23
23
 
@@ -17,7 +17,7 @@ What unit testing practices should be followed to ensure tests are meaningful, r
17
17
 
18
18
  **Every test must assert behavior, run offline without external dependencies, enforce 80% coverage, centralize shared setup, and prefer real code over mocks.**
19
19
 
20
- ### Implementation Details
20
+ ### Details
21
21
 
22
22
  #### 01-must-have-at-least-one-assertion-per-test
23
23
 
@@ -19,7 +19,7 @@ Every project must meet six minimum quality standards: a Getting Started section
19
19
 
20
20
  These standards form a non-negotiable baseline. Individual projects may raise the bar but must never fall below it.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### 01-readme-must-have-getting-started
25
25
 
@@ -31,7 +31,7 @@ These standards form a non-negotiable baseline. Individual projects may raise th
31
31
 
32
32
  **Required README structure:**
33
33
 
34
- ```markdown
34
+ ````markdown
35
35
  # Project Name
36
36
 
37
37
  One-line description.
@@ -46,7 +46,7 @@ npm install my-package
46
46
  import { myFunction } from "my-package";
47
47
  myFunction({ input: "value" });
48
48
  ```
49
- ```
49
+ ````
50
50
 
51
51
  ---
52
52
 
@@ -17,7 +17,7 @@ What error handling practices should be followed across all languages and projec
17
17
 
18
18
  **Follow a set of consistent error handling practices: catch only where you can handle, return errors as values at interfaces, centralize repetitive catch logic, communicate failure clearly at process and service boundaries, and exercise error paths with dedicated tests.**
19
19
 
20
- ### Implementation Details
20
+ ### Details
21
21
 
22
22
  #### 01-catch-only-where-handled
23
23
 
@@ -19,7 +19,7 @@ Question: What policy should developers follow to continuously enrich XDRs so re
19
19
 
20
20
  Developers must treat reusable missing guidance discovered during implementation as an XDR gap to be proposed and reviewed, not as permanent prompt-only context or repeated vibe coding.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  - The main objective is sharing, discussing, and converging practices across teams. Controlled divergence during exploration is acceptable, but recurring successful decisions must be converged into shared XDRs.
25
25
  - The non _local scope exists to share practices across projects, company areas, and functionally organized teams. Decisions placed in `_local` should be truly specific to the needs of a single application or repository.
@@ -43,4 +43,4 @@ Developers must treat reusable missing guidance discovered during implementation
43
43
  - [_core-adr-001](../../../_core/adrs/principles/001-xdrs-core.md)
44
44
  - [_core-article-001](../../../_core/adrs/principles/articles/001-xdrs-overview.md)
45
45
  - [agentme-article-001](articles/001-continuous-xdr-improvement.md)
46
- - [002-write-policy skill](../../../../.github/skills/002-write-policy/SKILL.md)
46
+ - [002-write-policy skill](../../../_core/adrs/principles/skills/002-write-policy/SKILL.md)
@@ -19,7 +19,7 @@ What baseline structure rules must every buildable module follow regardless of l
19
19
 
20
20
  Language-specific EDRs may add ecosystem details, but they must not redefine these baseline folder responsibilities.
21
21
 
22
- ### Implementation Details
22
+ ### Details
23
23
 
24
24
  #### 01-module-must-own-folder-root
25
25
 
@@ -2,13 +2,13 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- This article explains how architects, engineers and business professionals should recognize, organize, and promote reusable delivery decisions into XDRs as a continuous improvement activity. It is aimed at people working with coding agents, vibe-coding loops, or SDD-oriented delivery who need a practical path from task friction to shared documentation.
5
+ A practical guide for recognizing recurring delivery decisions and promoting them into shared XDRs. Intended for engineers, architects, and business professionals working with coding agents or SDD-oriented delivery.
6
6
 
7
- Continuous improvement matters because delivery decisions do not stay correct forever. Team structures change, platforms evolve, tools mature, and the trade-offs behind earlier choices shift over time. If XDRs are not revisited and improved continuously, previously useful decisions become stale guidance and eventually turn into a form of legacy documentation that misleads delivery instead of guiding it.
7
+ ## Content
8
8
 
9
- Continuous improvement also keeps the target state explicit. As XDRs evolve across projects and tracks, teams need a clear shared view of where they are trying to converge, what remains intentionally different, and what should be treated as technical debt on the path toward that target. Keeping XDRs current reduces confusion about the desired future state and helps each project evolve toward it deliberately instead of drifting through ad hoc local decisions.
9
+ Delivery decisions do not stay correct forever. Team structures change, platforms evolve, tools mature, and the trade-offs behind earlier choices shift over time. If XDRs are not revisited and improved continuously, previously useful decisions become stale guidance that misleads delivery instead of guiding it.
10
10
 
11
- ## Content
11
+ Keeping XDRs current also makes the target state explicit. Teams need a clear shared view of where they are converging, what remains intentionally different, and what is technical debt on the path to that target.
12
12
 
13
13
  ### Start from delivery friction
14
14
 
@@ -90,4 +90,4 @@ If the same clarification would likely be needed in another feature, by another
90
90
  - [_core-adr-001](../../../../_core/adrs/principles/001-xdrs-core.md) - XDR structure, numbering, and mandatory template
91
91
  - [_core-article-001](../../../../_core/adrs/principles/articles/001-xdrs-overview.md) - XDR introduction and general adoption guidance
92
92
  - [agentme-edr-012](../012-continuous-xdr-enrichment.md) - Shared-first XDR enrichment policy and 80% coverage target
93
- - [002-write-policy skill](../../../../../.github/skills/002-write-policy/SKILL.md) - Step-by-step procedure for drafting new XDRs
93
+ - [002-write-policy skill](../../../../_core/adrs/principles/skills/002-write-policy/SKILL.md) - Step-by-step procedure for drafting new XDRs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentme",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "",
5
5
  "dependencies": {
6
6
  "filedist": "^0.34.1"