agentme 0.10.0 → 0.12.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 (26) hide show
  1. package/.filedist-package.yml +1 -1
  2. package/.xdrs/agentme/edrs/application/003-javascript-project-tooling.md +41 -5
  3. package/.xdrs/agentme/edrs/application/010-golang-project-tooling.md +39 -15
  4. package/.xdrs/agentme/edrs/application/014-python-project-tooling.md +76 -17
  5. package/.xdrs/agentme/edrs/application/015-cli-tool-standards.md +25 -24
  6. package/.xdrs/agentme/edrs/application/018-ai-agent-development-standards.md +29 -11
  7. package/.xdrs/agentme/edrs/application/021-pragmatic-hexagonal-architecture.md +112 -0
  8. package/.xdrs/agentme/edrs/application/skills/001-create-javascript-project/SKILL.md +26 -11
  9. package/.xdrs/agentme/edrs/application/skills/003-create-golang-project/SKILL.md +31 -14
  10. package/.xdrs/agentme/edrs/application/skills/005-create-python-project/SKILL.md +64 -33
  11. package/.xdrs/agentme/edrs/devops/005-monorepo-structure.md +1 -1
  12. package/.xdrs/agentme/edrs/devops/006-github-pipelines.md +1 -1
  13. package/.xdrs/agentme/edrs/devops/008-common-targets.md +1 -1
  14. package/.xdrs/agentme/edrs/devops/017-tool-execution-and-scripting.md +2 -2
  15. package/.xdrs/agentme/edrs/governance/013-contributing-guide-requirements.md +1 -1
  16. package/.xdrs/agentme/edrs/index.md +2 -0
  17. package/.xdrs/agentme/edrs/observability/011-service-health-check-endpoint.md +1 -1
  18. package/.xdrs/agentme/edrs/principles/002-coding-best-practices.md +1 -1
  19. package/.xdrs/agentme/edrs/principles/004-unit-test-requirements.md +8 -2
  20. package/.xdrs/agentme/edrs/principles/007-project-quality-standards.md +3 -3
  21. package/.xdrs/agentme/edrs/principles/009-error-handling.md +1 -1
  22. package/.xdrs/agentme/edrs/principles/012-continuous-xdr-enrichment.md +2 -2
  23. package/.xdrs/agentme/edrs/principles/016-cross-language-module-structure.md +1 -1
  24. package/.xdrs/agentme/edrs/principles/022-secrets-management.md +128 -0
  25. package/.xdrs/agentme/edrs/principles/articles/001-continuous-xdr-improvement.md +5 -5
  26. package/package.json +2 -2
@@ -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
+ ty, 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`**
@@ -157,13 +157,13 @@ build: install
157
157
  lint: install
158
158
  $(MISE) uv run --project . ruff format --check .
159
159
  $(MISE) uv run --project . ruff check .
160
- $(MISE) uv run --project . pyright
160
+ $(MISE) uv run --project . ty check
161
161
  $(MISE) uv run --project . pip-audit
162
162
 
163
163
  lint-fix: install
164
164
  $(MISE) uv run --project . ruff format .
165
165
  $(MISE) uv run --project . ruff check . --fix
166
- $(MISE) uv run --project . pyright
166
+ $(MISE) uv run --project . ty check
167
167
  $(MISE) uv run --project . pip-audit
168
168
 
169
169
  test-unit: install
@@ -203,7 +203,7 @@ dev = []
203
203
  [dependency-groups]
204
204
  dev = [
205
205
  "pip-audit>=2.9.0",
206
- "pyright>=1.1.400",
206
+ "ty>=0.1.0",
207
207
  "pytest>=8.4.0",
208
208
  "pytest-cov>=6.1.0",
209
209
  "ruff>=0.11.0",
@@ -214,25 +214,40 @@ 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
- [tool.pyright]
224
- include = ["src", "tests"]
225
- venvPath = ".."
226
- venv = ".venv"
227
- typeCheckingMode = "standard"
240
+ [tool.ty]
241
+ src = ["src", "tests"]
228
242
 
229
243
  [tool.pytest.ini_options]
230
244
  testpaths = ["tests"]
245
+ python_files = "*_test.py"
231
246
  addopts = "-q"
232
247
  ```
233
248
 
234
249
  Use `lib/pyproject.toml` as the single configuration file for the package. Do not add
235
- `requirements.txt`, `setup.py`, `setup.cfg`, `ruff.toml`, or `pyrightconfig.json` by default.
250
+ `requirements.txt`, `setup.py`, `setup.cfg`, `ruff.toml`, or `ty.toml` by default.
236
251
 
237
252
  **`lib/README.md`**
238
253
 
@@ -267,29 +282,37 @@ make test
267
282
 
268
283
  ### Phase 4: Create the package and tests inside `lib/`
269
284
 
270
- Create this baseline structure.
285
+ Create this baseline structure following [agentme-edr-021](../../021-pragmatic-hexagonal-architecture.md).
271
286
 
272
287
  **`lib/src/[package_name]/__init__.py`**
273
288
 
274
289
  ```python
275
- from .core import hello
290
+ from .app.hello import hello
276
291
 
277
292
  __all__ = ["hello"]
278
293
  ```
279
294
 
280
- **`lib/src/[package_name]/core.py`**
295
+ **`lib/src/[package_name]/app/__init__.py`**
296
+
297
+ ```python
298
+ ```
299
+
300
+ **`lib/src/[package_name]/app/hello.py`**
281
301
 
282
302
  ```python
283
303
  def hello(name: str) -> str:
284
304
  return f"Hello, {name}!"
285
305
  ```
286
306
 
287
- **`lib/src/[package_name]/__main__.py`**
307
+ **`lib/src/[package_name]/adapters/__init__.py`**
308
+
309
+ ```python
310
+ ```
288
311
 
289
- Use this only for CLI-oriented projects.
312
+ **`lib/src/[package_name]/adapters/cli/__init__.py`**
290
313
 
291
314
  ```python
292
- from .core import hello
315
+ from [package_name].app.hello import hello
293
316
 
294
317
 
295
318
  def main() -> None:
@@ -300,10 +323,17 @@ if __name__ == "__main__":
300
323
  main()
301
324
  ```
302
325
 
303
- **`lib/tests/test_core.py`**
326
+ **`lib/src/[package_name]/shared/__init__.py`**
327
+
328
+ ```python
329
+ ```
330
+
331
+ Create empty `adapters/connectors/` directory with a `.gitkeep` for outbound adapters.
332
+
333
+ **`lib/tests/hello_test.py`**
304
334
 
305
335
  ```python
306
- from [package_name].core import hello
336
+ from [package_name].app.hello import hello
307
337
 
308
338
 
309
339
  def test_hello() -> None:
@@ -314,9 +344,9 @@ If two or more test files need shared fixtures, create `lib/tests/conftest.py` a
314
344
 
315
345
  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
346
 
317
- ### Phase 5: Create examples for libraries and utilities
347
+ ### Phase 5: Create examples
318
348
 
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.
349
+ Add an `examples/` directory with one subdirectory per runnable consumer example. Each example must be its own Python project.
320
350
 
321
351
  **`examples/basic-usage/pyproject.toml`**
322
352
 
@@ -355,14 +385,15 @@ After creating the files:
355
385
 
356
386
  ## Examples
357
387
 
358
- **Input:** "Create a Python library called `event_tools`"
388
+ **Input:** "Create a Python project called `event_tools`"
359
389
  - Create `Makefile`, `README.md`, `lib/pyproject.toml`, `lib/Makefile`, `lib/src/event_tools/`, `lib/tests/`, and `examples/`
390
+ - Scaffold `adapters/`, `app/`, `shared/` directories inside `lib/src/event_tools/`
360
391
  - Add `lib/README.md`, `.cache/` handling, and install examples from the built wheel in `lib/dist/`
361
- - Configure `uv`, Ruff, Pyright, Pytest, `pytest-cov`, and `pip-audit`
392
+ - Configure `uv`, Ruff, ty, Pytest, `pytest-cov`, and `pip-audit`
362
393
  - Verify with `make lint-fix`, `make test`, and `make build`
363
394
 
364
395
  **Input:** "Scaffold a Python CLI package"
365
- - Add `lib/src/<package_name>/__main__.py`
396
+ - Add CLI entry point in `lib/src/<package_name>/adapters/cli/__init__.py`
366
397
  - Add `[project.scripts]` in `lib/pyproject.toml` when the command name must differ from the module name
367
398
  - Keep the same Makefile and quality checks
368
399
 
@@ -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).
@@ -27,7 +27,7 @@ This keeps local development and CI aligned, reduces indirection, and lets contr
27
27
  - A Makefile target MUST execute the real operation through `mise exec --` before invoking the tool itself, so it always uses the version pinned in `.mise.toml`. Avoid intermediate script layers that hide the actual command.
28
28
  - Every Makefile target MUST start by echoing a concise summary of the target and folder or context, using fewer than 10 words. When delegating to another Makefile, echo the child path and delegated target before invoking it.
29
29
  - Direct delegation to another Makefile is allowed when traversing repo, app, or module boundaries, for example `$(MAKE) -C lib build`.
30
- - Calling the actual tool binary through its native executable launcher is allowed when that is the direct command under `mise exec --`, for example `mise exec -- pnpm exec eslint ./src`, `mise exec -- uv run pyright`, `mise exec -- go test`, or `mise exec -- npx -y monotag`.
30
+ - Calling the actual tool binary through its native executable launcher is allowed when that is the direct command under `mise exec --`, for example `mise exec -- pnpm exec eslint ./src`, `mise exec -- uv run ty check`, `mise exec -- go test`, or `mise exec -- npx -y monotag`.
31
31
  - Makefile targets MUST use `mise exec --` consistently before routine tool commands and MUST NOT call `npm run`, `pnpm run`, `yarn run`, `just`, `task`, or similar abstraction layers for routine project commands.
32
32
  - Tool installation and environment preparation MUST be handled explicitly in developer setup instructions and CI workflow steps, using ecosystem-specific installation steps such as `actions/setup-node`, `actions/setup-go`, `astral-sh/setup-uv`, system package managers, or pinned install commands such as `mise install`.
33
33
  - `package.json` scripts are optional and MAY exist only as direct reverse-compatibility aliases to one Make target, for example `"test": "make test"`. They MUST stay one-to-one and add no extra orchestration.
@@ -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.
@@ -14,6 +14,7 @@ Foundational standards, principles, and guidelines.
14
14
  - [agentme-edr-009](principles/009-error-handling.md) - **Error handling** - Standardize explicit errors, logging, and propagation rules
15
15
  - [agentme-edr-012](principles/012-continuous-xdr-enrichment.md) - **Continuous xdr improvement policy** - Promote recurring delivery lessons into reusable XDRs
16
16
  - [agentme-edr-016](principles/016-cross-language-module-structure.md) - **Cross-language module structure** - Organize modules consistently across supported languages
17
+ - [agentme-edr-022](principles/022-secrets-management.md) - **Secrets management** - Handle secrets securely using native keychains and cloud secret managers
17
18
 
18
19
  ## Articles
19
20
 
@@ -32,6 +33,7 @@ Language and framework-specific tooling and project structure.
32
33
  - [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
34
  - [agentme-edr-019](application/019-ml-dataset-structure.md) - **ML dataset structure** - Standard folder layout and file conventions for ML datasets
34
35
  - [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)
36
+ - [agentme-edr-021](application/021-pragmatic-hexagonal-architecture.md) - **Pragmatic hexagonal architecture** - Organize application layers as External/Adapters/Application with practical coupling rules
35
37
  - [004-select-relevant-xdrs](application/skills/004-select-relevant-xdrs/SKILL.md) - **Select relevant XDRs**
36
38
 
37
39
  ## 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
 
@@ -70,7 +70,13 @@ Builds that miss the threshold must not be merged.
70
70
 
71
71
  #### 04-must-place-test-files-alongside-source
72
72
 
73
- Test files must live next to the source file they test, in the same directory, following the convention of the language/framework (e.g. `file.test.ts`, `file_test.go`, `file.spec.js`).
73
+ Test files must live next to the source file they test, in the same directory, following the convention of the language/framework:
74
+
75
+ | Language | Pattern | Example |
76
+ |----------|---------|-------|
77
+ | TypeScript/JavaScript | `[name].test.ts` or `[name].spec.js` | `file1.test.ts` |
78
+ | Go | `[name]_test.go` | `file1_test.go` |
79
+ | Python | `[name]_test.py` | `myfunc_test.py` |
74
80
 
75
81
  ```
76
82
  src/mymodule/group1/file1.ts ← source