agentme 0.5.0 → 0.6.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.
@@ -13,7 +13,7 @@ What tooling and project structure should JavaScript/TypeScript projects follow
13
13
 
14
14
  ## Decision Outcome
15
15
 
16
- **Use a Mise-managed Node.js and pnpm toolchain together with pnpm, tsc, esbuild, eslint, and jest in a standard layout separating library code (`lib/`) from runnable usage examples (`examples/`), coordinated by root-level Makefiles.**
16
+ **Use a Mise-managed Node.js and pnpm toolchain together with pnpm, tsc, esbuild, eslint, and jest in a module-root layout that follows [agentme-edr-016](../principles/016-cross-language-module-structure.md), with runnable usage examples in sibling `examples/` folders and Makefiles as the only entry points.**
17
17
 
18
18
  Clear, consistent tooling and layout enable fast onboarding, reliable CI pipelines, and a predictable developer experience across projects.
19
19
 
@@ -47,29 +47,39 @@ When `tsconfig.json` extends `@tsconfig/node24/tsconfig.json`, the default `modu
47
47
  #### Project structure
48
48
 
49
49
  ```
50
- / # workspace root
50
+ / # workspace root or parent aggregation root
51
51
  ├── .mise.toml # pinned Node.js and pnpm versions
52
+ ├── .gitignore # MUST ignore dist/ and .cache/
52
53
  ├── Makefile # delegates build/lint/test to /lib and /examples
53
- ├── README.md # Quick Start first; used as npm registry page
54
- ├── lib/ # the published npm package
54
+ ├── README.md # workspace overview and quickstart
55
+ ├── lib/ # one JavaScript/TypeScript module root
55
56
  │ ├── Makefile # build, lint, test, publish targets
57
+ │ ├── README.md # package README used for publishing
56
58
  │ ├── package.json # package manifest
57
59
  │ ├── tsconfig.json # TypeScript config for build and linting
58
60
  │ ├── jest.config.js # Jest config
59
61
  │ ├── eslint.config.mjs # ESLint config (ESLint 9 flat config)
62
+ │ ├── .cache/ # eslint, jest, tsc incremental state, coverage
63
+ │ ├── dist/ # compiled files and packed .tgz artifacts
60
64
  │ └── src/ # all TypeScript source files
61
65
  │ ├── index.ts # public API re-exports
62
66
  │ └── *.test.ts # test files co-located with source
63
- └── examples/ # runnable usage examples
64
- ├── Makefile # build + test all examples in sequence
65
- ├── usage-x/ # first example
66
- │ └── package.json
67
- └── usage-y/ # second example
68
- └── package.json
67
+ ├── examples/ # runnable usage examples outside the module root
68
+ ├── Makefile # build + test all examples in sequence
69
+ ├── usage-x/ # first example
70
+ └── package.json
71
+ └── usage-y/ # second example
72
+ └── package.json
73
+ ├── tests_integration/ # optional cross-example or cross-module integration tests
74
+ └── tests_benchmark/ # optional benchmark harnesses
69
75
  ```
70
76
 
71
77
  The root `Makefile` delegates every target to `/lib` then `/examples` in sequence and is expected to execute module commands inside the repository's Mise-managed environment.
72
78
 
79
+ 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/`.
80
+
81
+ Persistent caches MUST live under `.cache/`. Recommended locations are Jest `cacheDirectory`, ESLint `--cache-location`, TypeScript `tsBuildInfoFile`, and coverage outputs.
82
+
73
83
  The commands below assume they are invoked through `mise exec -- make <target>` or from an activated Mise shell.
74
84
 
75
85
  #### lib/Makefile targets
@@ -83,7 +93,7 @@ The commands below assume they are invoked through `mise exec -- make <target>`
83
93
  | `lint-fix` | `pnpm exec eslint ./src --fix` |
84
94
  | `test` | `pnpm exec jest --verbose` |
85
95
  | `test-watch` | `pnpm exec jest --watch` |
86
- | `clean` | remove `node_modules/` and `dist/` |
96
+ | `clean` | remove `node_modules/`, `dist/`, and `.cache/` |
87
97
  | `all` | `build lint test` |
88
98
  | `publish` | version-bump with `monotag`, then `npm publish --provenance` |
89
99
 
@@ -98,6 +108,12 @@ The commands below assume they are invoked through `mise exec -- make <target>`
98
108
 
99
109
  Each sub-folder under `examples/` is an independent package. The Makefile installs the locally built `.tgz` pack from `lib/dist/` so examples simulate real external usage.
100
110
 
111
+ Examples MUST remain outside the module root and MUST consume the package through the packed artifact in `dist/`, never through `../src` imports or other direct source links.
112
+
113
+ Module-specific integration tests that are not just runnable examples belong in `lib/tests_integration/` or a sibling `tests_integration/` when they cover multiple modules.
114
+
115
+ Benchmarks belong in `lib/tests_benchmark/` when they require dedicated harnesses; simple micro-benchmarks may stay co-located only if the local testing stack makes that idiomatic.
116
+
101
117
  The examples folder MUST exist for any libraries and utilities that are published or have more than 500 lines of code
102
118
 
103
119
  ### Related Skills
@@ -13,7 +13,7 @@ What tooling and project structure should Go projects follow to ensure consisten
13
13
 
14
14
  ## Decision Outcome
15
15
 
16
- **Use the standard Go toolchain (`go build`, `go test`) with `golangci-lint` for linting, feature packages in subdirectories (no `internal/` by default), a `cli/` package for command wiring, and a Makefile as the single entry point for all development tasks, with the Go toolchain and related CLIs sourced from the repository's Mise-managed environment when the repository defines `.mise.toml`.**
16
+ **Use the standard Go toolchain (`go build`, `go test`) with `golangci-lint`, module-root folder responsibilities from [agentme-edr-016](../principles/016-cross-language-module-structure.md), feature packages in subdirectories, a `cli/` package for command wiring, and a Makefile as the single entry point for all development tasks.**
17
17
 
18
18
  A predictable layout and minimal external tooling keep Go projects approachable, fast to build, and easy to distribute as cross-platform binaries.
19
19
 
@@ -34,33 +34,40 @@ Direct installation of project-required Go CLIs with `go install ...@latest` as
34
34
  #### Project structure
35
35
 
36
36
  ```
37
- / # project root (single Go module)
37
+ / # project root or Go module root inside a monorepo
38
38
  ├── Makefile # build, lint, test, publish, and utility targets
39
+ ├── README.md # module README with usage and development commands
40
+ ├── .gitignore # MUST ignore dist/ and .cache/
41
+ ├── .golangci.yml # golangci-lint configuration
39
42
  ├── go.mod # module declaration (github.com/<owner>/<project>)
40
43
  ├── go.sum # locked dependency checksums
41
44
  ├── main.go # binary entry point — argument dispatch only, no logic
42
- ├── .golangci.yml # golangci-lint configuration
43
- ├── .gitignore
44
- ├── README.md
45
+ ├── .cache/ # GOCACHE, GOMODCACHE, golangci-lint cache, coverage
46
+ ├── dist/ # built binaries and packaged outputs
45
47
  ├── <feature-a>/ # domain package (e.g. ownership/, changes/, utils/)
46
48
  │ ├── *.go # business logic
47
49
  │ └── *_test.go # unit tests co-located with source
48
50
  ├── <feature-b>/
49
51
  │ └── ...
50
- └── cli/ # CLI wiring — ties flags to domain packages
51
- ├── <feature-a>/
52
- │ └── *.go
53
- └── <feature-b>/
54
- └── *.go
52
+ ├── cli/ # CLI wiring — ties flags to domain packages
53
+ ├── <feature-a>/
54
+ └── *.go
55
+ └── <feature-b>/
56
+ └── *.go
57
+ ├── tests_integration/ # optional integration tests for this module
58
+ ├── tests_benchmark/ # optional benchmark harnesses and datasets
59
+ └── examples/ # optional sibling consumer examples for libraries
55
60
  ```
56
61
 
57
62
  **Key layout rules:**
58
63
 
59
64
  - 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.
65
+ - In a multi-module repository, each Go module MUST live in its own folder root with its own `Makefile`, `README.md`, `dist/`, and `.cache/`.
60
66
  - `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`.
61
67
  - 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.
62
68
  - `cli/` packages own flag parsing, output formatting, and the wiring between flags and domain functions. No business logic lives in `cli/`.
63
69
  - Packages are flat by default; sub-packages are only introduced when a feature package itself exceeds ~400 lines or has clearly separable sub-concerns.
70
+ - 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.
64
71
 
65
72
  #### go.mod
66
73
 
@@ -74,16 +81,16 @@ Direct installation of project-required Go CLIs with `go install ...@latest` as
74
81
  | Target | Description |
75
82
  |--------|-------------|
76
83
  | `all` | Default; runs `build lint test` in sequence |
77
- | `build` | `go mod download && go build -o dist/<binary>` |
84
+ | `build` | `go mod download && go build -o dist/<binary>` with Go caches redirected into `.cache/` |
78
85
  | `build-all` | Cross-compile for all target platforms (darwin/linux/windows × amd64/arm64) |
79
86
  | `build-arch-os` | Compile for a specific `OS` and `ARCH` environment variable pair; output to `dist/${OS}-${ARCH}/<binary>` |
80
87
  | `install` | `go mod download` |
81
- | `lint` | `golangci-lint run ./...` |
82
- | `lint-fix` | `golangci-lint run --fix ./...` |
83
- | `test` | `go test -cover ./...` — runs all tests with coverage |
88
+ | `lint` | `golangci-lint run ./...` with its cache redirected into `.cache/` |
89
+ | `lint-fix` | `golangci-lint run --fix ./...` with its cache redirected into `.cache/` |
90
+ | `test` | `go test -cover ./...` — runs all tests with coverage and stores disposable outputs under `.cache/` |
84
91
  | `test-unit` | `go test -cover ./...` — alias for unit tests only (same here; integration tests get a separate tag) |
85
- | `coverage` | `go tool cover -func ./coverage.out` — displays coverage summary |
86
- | `clean` | Remove `dist/` and any coverage files |
92
+ | `coverage` | `go tool cover -func .cache/coverage.out` — displays coverage summary |
93
+ | `clean` | Remove `dist/` and `.cache/` |
87
94
  | `start` | `go run ./ <default-args>` — launch the binary locally for dev use |
88
95
  | `publish` | Tag with `monotag`, then push tag + binaries to GitHub Releases |
89
96
 
@@ -112,8 +119,10 @@ When the project produces a CLI binary for end-users:
112
119
  - Tests are co-located with source: `<feature>/<file>_test.go`.
113
120
  - Use `github.com/stretchr/testify` (`assert`, `require`) for test assertions.
114
121
  - Run all tests: `go test -cover ./...`
115
- - Benchmarks: `go test -bench . -benchmem -count 20`
116
- - Integration or slow tests: guard with `//go:build integration` and skip in unit runs via `-tags=unit`.
122
+ - Benchmarks: keep simple `Benchmark*` functions co-located in `*_test.go`; use `tests_benchmark/` when the benchmark needs dedicated harnesses or datasets.
123
+ - 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.
124
+
125
+ 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.
117
126
 
118
127
  #### Linting
119
128
 
@@ -13,9 +13,9 @@ What tooling and project structure should Python projects follow to ensure consi
13
13
 
14
14
  ## Decision Outcome
15
15
 
16
- **Use a uv-managed Python project with `pyproject.toml`, `ruff`, `pyright`, `pytest`, `pytest-cov`, `pip-audit`, and a Makefile as the only development entry point.**
16
+ **Use a uv-managed Python project with `pyproject.toml`, `ruff`, `pyright`, `pytest`, `pytest-cov`, `pip-audit`, and a layout that follows [agentme-edr-016](../principles/016-cross-language-module-structure.md): a module root under `lib/`, runnable consumer examples in sibling `examples/`, and standardized `dist/` and `.cache/` locations.**
17
17
 
18
- A single dependency manager, one canonical config file, and standard targets keep Python projects predictable for contributors and CI.
18
+ 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.
19
19
 
20
20
  ### Implementation Details
21
21
 
@@ -35,40 +35,64 @@ All routine commands must run through the project `Makefile`, never by calling `
35
35
 
36
36
  When the repository defines a root `.mise.toml`, Python and uv must be pinned there and commands should run through `mise exec --` or an activated Mise shell.
37
37
 
38
+ 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.
39
+
40
+ Persistent caches must live under `.cache/`, preferably the module `lib/.cache/` plus a shared root `.cache/uv/` when uv cache sharing is desired.
41
+
38
42
  #### Project structure
39
43
 
40
44
  ```text
41
45
  /
42
46
  ├── .mise.toml # optional but required when the repo uses Mise
43
- ├── Makefile # single entry point for build/lint/test/run tasks
44
- ├── pyproject.toml # package metadata + tool config
45
- ├── uv.lock # committed lockfile
46
- ├── README.md # Getting Started near the top
47
- ├── src/
48
- │ └── <package_name>/
49
- ├── __init__.py
50
- ├── __main__.py # when the project exposes a CLI
51
- └── ...
52
- ├── tests/
53
- │ ├── conftest.py # shared fixtures when needed
54
- └── test_*.py
55
- └── examples/ # required for libraries and shared utilities
56
- ├── Makefile
57
- └── basic-usage/
47
+ ├── .gitignore
48
+ ├── .cache/ # optional shared uv cache at repo level
49
+ ├── .venv/ # shared uv environment for lib/ and examples/
50
+ ├── Makefile # root entry point; delegates to lib/ and runs examples/
51
+ ├── README.md # workspace/repository overview
52
+ ├── lib/ # everything the published library needs
53
+ ├── Makefile # build, lint, test, publish targets for the library
54
+ ├── pyproject.toml # package metadata + tool config
55
+ ├── uv.lock # committed lockfile for the library
56
+ ├── README.md # package README used for publishing
57
+ │ ├── .cache/ # pytest, Ruff, coverage, Python bytecode cache
58
+ ├── src/
59
+ │ │ └── <package_name>/
60
+ │ │ ├── __init__.py
61
+ │ │ ├── __main__.py # when the project exposes a CLI
62
+ │ │ └── ...
63
+ │ ├── tests/
64
+ │ │ ├── conftest.py # shared fixtures when needed
65
+ │ │ └── test_*.py
66
+ │ ├── tests_integration/ # optional integration tests for this module
67
+ │ ├── tests_benchmark/ # optional benchmark harnesses and datasets
68
+ │ └── dist/ # wheels / sdists built from lib/
69
+ └── examples/ # independent consumer projects
70
+ ├── example1/
71
+ │ ├── pyproject.toml
72
+ │ └── main.py
73
+ └── example2/
74
+ ├── pyproject.toml
75
+ └── main.py
58
76
  ```
59
77
 
60
- Use the `src/` layout for import safety and packaging clarity. Keep tests under `tests/` and shared test setup in `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 `pyproject.toml`.
78
+ Keep the repository root clean: source code, tests, distribution artifacts, and package metadata live under `lib/`, while the root contains only orchestration and repository-level files.
79
+
80
+ 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`.
61
81
 
62
- 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).
82
+ 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/`.
63
83
 
64
- #### `pyproject.toml`
84
+ 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.
85
+
86
+ #### `lib/pyproject.toml`
65
87
 
66
88
  - Runtime dependencies belong in `[project.dependencies]`.
67
89
  - Development-only tooling belongs in `[dependency-groups].dev`.
68
- - Configure Ruff, Pyright, and Pytest in `pyproject.toml` under their `tool.*` sections.
69
- - Commit `uv.lock` and keep it in sync with `pyproject.toml`.
90
+ - Configure Ruff, Pyright, and Pytest in `lib/pyproject.toml` under their `tool.*` sections.
91
+ - Commit `lib/uv.lock` and keep it in sync with `lib/pyproject.toml`.
70
92
  - Expose CLI entry points with `[project.scripts]` when the project provides commands.
71
93
 
94
+ When Pyright runs from `lib/`, configure it to discover the shared root virtual environment, for example with `venvPath = ".."` and `venv = ".venv"`.
95
+
72
96
  Ruff is the default formatter and linter. Do not add Black, isort, or Flake8 unless another XDR for that repository explicitly requires them.
73
97
 
74
98
  Pyright must run on every lint pass. `typeCheckingMode = "standard"` is the minimum baseline; projects may raise this to `strict` when the codebase is ready.
@@ -79,21 +103,37 @@ Pytest coverage must fail below 80% line and branch coverage, following [agentme
79
103
 
80
104
  The commands below assume invocation through `mise exec -- make <target>` when the repository uses Mise, or plain `make <target>` inside an activated project environment.
81
105
 
106
+ #### Root `Makefile`
107
+
108
+ The root `Makefile` is the only contract for CI and contributors. It delegates library work to `lib/` and runs each example project in `examples/` against the shared root `.venv/`.
109
+
82
110
  | Target | Description |
83
111
  |--------|-------------|
84
- | `install` | `uv sync --frozen --all-extras --dev` |
85
- | `build` | `uv sync --frozen --all-extras --dev && uv build` |
86
- | `lint` | `uv run ruff format --check . && uv run ruff check . && uv run pyright && uv run pip-audit` |
87
- | `lint-fix` | `uv run ruff format . && uv run ruff check . --fix && uv run pyright && uv run pip-audit` |
88
- | `test-unit` | `uv run pytest --cov=src/<package_name> --cov-branch --cov-report=term-missing --cov-fail-under=80` |
89
- | `test-examples` | Run `examples/` through its own `Makefile` when the project is a library/utility |
112
+ | `install` | Run `lib/install` to create or update the shared root `.venv/` |
113
+ | `build` | Run `lib/build` |
114
+ | `lint` | Run `lib/lint` |
115
+ | `lint-fix` | Run `lib/lint-fix` |
116
+ | `test-unit` | Run `lib/test-unit` |
117
+ | `test-examples` | For each `examples/*/pyproject.toml`, sync and run the example serially against the shared root `.venv/` |
90
118
  | `test` | Run `test-unit`, then `test-examples` when applicable |
91
- | `clean` | Remove `.venv/`, `dist/`, `.pytest_cache/`, `.ruff_cache/`, `.coverage`, `htmlcov/` |
119
+ | `clean` | Remove the shared root `.venv/`, root `.cache/`, and delegate cleanup to `lib/` |
92
120
  | `all` | `build lint test` |
93
- | `update-lockfile` | `uv lock --upgrade` |
94
- | `run` | `uv run python -m <package_name>` or the project CLI entry point |
121
+
122
+ #### `lib/Makefile`
123
+
124
+ | Target | Description |
125
+ |--------|-------------|
126
+ | `install` | `uv sync --project . --frozen --all-extras --dev` using the shared root `.venv/` |
127
+ | `build` | `uv sync --project . --frozen --all-extras --dev && uv build --project . --out-dir dist` |
128
+ | `lint` | `uv run --project . ruff format --check . && uv run --project . ruff check . && uv run --project . pyright && uv run --project . pip-audit`, with caches redirected into `.cache/` |
129
+ | `lint-fix` | `uv run --project . ruff format . && uv run --project . ruff check . --fix && uv run --project . pyright && uv run --project . pip-audit`, with caches redirected into `.cache/` |
130
+ | `test-unit` | `uv run --project . pytest --cov=src/<package_name> --cov-branch --cov-report=term-missing --cov-fail-under=80`, with pytest and coverage outputs stored under `.cache/` |
131
+ | `clean` | Remove `dist/` and `.cache/` inside `lib/` |
132
+ | `all` | `build lint test-unit` |
133
+ | `update-lockfile` | `uv lock --project . --upgrade` |
134
+ | `run` | `uv run --project . python -m <package_name>` or the project CLI entry point |
95
135
  | `dev` | Same as `run`, optionally with repository-specific dev defaults |
96
- | `publish` | `uv publish` after versioning and packaging are complete |
136
+ | `publish` | `uv publish --project .` after versioning and packaging are complete |
97
137
 
98
138
  The root `Makefile` must remain the only contract for CI and contributors, in line with [agentme-edr-008](../devops/008-common-targets.md).
99
139
 
@@ -101,8 +141,8 @@ The root `Makefile` must remain the only contract for CI and contributors, in li
101
141
 
102
142
  * (REJECTED) **Mixed Python tooling** - Separate tools and config files such as `pip`, `requirements.txt`, `setup.cfg`, `flake8`, and `mypy`.
103
143
  * Reason: Increases cognitive load, duplicates configuration, and weakens the standard command surface across projects.
104
- * (CHOSEN) **uv + `pyproject.toml` + Ruff/Pyright/Pytest toolchain** - One dependency manager, one config file, and one Makefile entry point.
105
- * Reason: Keeps packaging, dependency locking, static analysis, security auditing, and test execution consistent.
144
+ * (CHOSEN) **uv + `lib/` package layout + Ruff/Pyright/Pytest toolchain** - One dependency manager, package internals isolated under `lib/`, consumer examples under `examples/`, and one root Makefile contract.
145
+ * Reason: Keeps packaging, dependency locking, static analysis, security auditing, and test execution consistent while aligning Python repositories with the established JavaScript layout.
106
146
 
107
147
  ## References
108
148
 
@@ -13,12 +13,13 @@ 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 separates
17
- library source (`lib/`) from runnable usage examples (`examples/`), coordinated by root-level
18
- Makefiles. Boilerplate is derived from the [filedist](https://github.com/flaviostutz/filedist)
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)
19
20
  project.
20
21
 
21
- Related EDR: [agentme-edr-003](../../003-javascript-project-tooling.md)
22
+ Related EDRs: [agentme-edr-003](../../003-javascript-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md)
22
23
 
23
24
  ## Instructions
24
25
 
@@ -72,6 +73,7 @@ pnpm = "10.14.0"
72
73
  ```
73
74
  node_modules/
74
75
  dist/
76
+ .cache/
75
77
  *.tgz
76
78
  .filedist
77
79
  ```
@@ -105,24 +107,29 @@ describe('hello', () => {
105
107
  ```makefile
106
108
  SHELL := /bin/bash
107
109
  MISE := mise exec --
110
+ CACHE_DIR := .cache
108
111
 
109
112
  build: install
110
113
  @rm -rf dist
111
- $(MISE) pnpm exec tsc --outDir dist
114
+ @mkdir -p $(CACHE_DIR)/tsc
115
+ $(MISE) pnpm exec tsc --incremental --tsBuildInfoFile $(CACHE_DIR)/tsc/tsconfig.tsbuildinfo --outDir dist
112
116
  @-find ./dist \( -regex '.*\.test\..*' -o -regex '.*__tests.*' \) -exec rm -rf {} \; 2> /dev/null
113
117
  @# Create pack for use by examples to simulate real external usage
114
118
  $(MISE) pnpm pack --pack-destination dist
115
119
 
116
120
  build-module: install
117
121
  @rm -rf dist
118
- $(MISE) pnpm exec tsc --outDir dist
122
+ @mkdir -p $(CACHE_DIR)/tsc
123
+ $(MISE) pnpm exec tsc --incremental --tsBuildInfoFile $(CACHE_DIR)/tsc/tsconfig.tsbuildinfo --outDir dist
119
124
  @-find ./dist \( -regex '.*\.test\..*' -o -regex '.*__tests.*' \) -exec rm -rf {} \; 2> /dev/null
120
125
 
121
126
  lint:
122
- $(MISE) pnpm exec eslint ./src
127
+ @mkdir -p $(CACHE_DIR)/eslint
128
+ $(MISE) pnpm exec eslint ./src --cache --cache-location $(CACHE_DIR)/eslint/.eslintcache
123
129
 
124
130
  lint-fix:
125
- $(MISE) pnpm exec eslint ./src --fix
131
+ @mkdir -p $(CACHE_DIR)/eslint
132
+ $(MISE) pnpm exec eslint ./src --fix --cache --cache-location $(CACHE_DIR)/eslint/.eslintcache
126
133
 
127
134
  test-watch:
128
135
  $(MISE) pnpm exec jest --watch
@@ -133,6 +140,7 @@ test:
133
140
  clean:
134
141
  rm -rf node_modules
135
142
  rm -rf dist
143
+ rm -rf .cache
136
144
 
137
145
  all: build lint test
138
146
 
@@ -223,6 +231,8 @@ Use this single tsconfig for both build and type-aware linting. Keep `*.test.ts`
223
231
  module.exports = {
224
232
  testEnvironment: 'node',
225
233
  testMatch: ['**/*.test.ts'],
234
+ cacheDirectory: '<rootDir>/.cache/jest',
235
+ coverageDirectory: '<rootDir>/.cache/coverage',
226
236
  collectCoverageFrom: ['src/**/*.ts', '!src/**/*.test.ts'],
227
237
  transform: {
228
238
  '^.+\\.tsx?$': [
@@ -323,7 +333,29 @@ console.log(result);
323
333
 
324
334
  ---
325
335
 
326
- ### Phase 5: Create `README.md`
336
+ ### Phase 5: Create `README.md` and `lib/README.md`
337
+
338
+ Keep the repository README focused on the workspace and the module README focused on consumers of
339
+ the published package.
340
+
341
+ **`README.md`**
342
+
343
+ ```markdown
344
+ # [package-name]
345
+
346
+ [description]
347
+
348
+ ## Getting Started
349
+
350
+ ```bash
351
+ mise install
352
+ make test
353
+ ```
354
+
355
+ The published module lives in `lib/` and runnable consumer examples live in `examples/`.
356
+ ```
357
+
358
+ **`lib/README.md`**
327
359
 
328
360
  Quick Start must appear at the top — it is rendered first on the npm registry page.
329
361
 
@@ -334,28 +366,37 @@ Quick Start must appear at the top — it is rendered first on the npm registry
334
366
 
335
367
  ## Quick Start
336
368
 
337
- \`\`\`bash
369
+ ```bash
338
370
  pnpm add [package-name]
339
- \`\`\`
371
+ ```
340
372
 
341
- \`\`\`typescript
373
+ ```typescript
342
374
  import { hello } from '[package-name]';
343
375
 
344
376
  const greeting = hello('world');
345
377
  console.log(greeting); // Hello, world!
346
- \`\`\`
378
+ ```
347
379
 
348
380
  ## Installation
349
381
 
350
- \`\`\`bash
382
+ ```bash
351
383
  npm install [package-name]
352
384
  # or
353
385
  pnpm add [package-name]
354
- \`\`\`
386
+ ```
355
387
 
356
388
  ## Examples
357
389
 
358
- See the [examples/](examples/) folder for complete runnable examples.
390
+ See the sibling `examples/` folder for complete runnable examples that consume the packed artifact
391
+ from `lib/dist/`.
392
+
393
+ ## Development
394
+
395
+ ```bash
396
+ make build
397
+ make lint
398
+ make test
399
+ ```
359
400
 
360
401
  ## License
361
402
 
@@ -369,12 +410,13 @@ MIT
369
410
  Review all created files and confirm:
370
411
 
371
412
  - [ ] Root `Makefile` delegates to both `lib/` and `examples/`
413
+ - [ ] `.gitignore` ignores `dist/` and `.cache/`
372
414
  - [ ] `lib/src/index.ts` exports at least one symbol
373
415
  - [ ] `lib/src/index.test.ts` has at least one passing test
374
416
  - [ ] `lib/package.json` has `main`, `types`, and `files` set correctly
375
417
  - [ ] `lib/tsconfig.json` includes co-located `src/**/*.test.ts` files for ESLint type-aware parsing
376
418
  - [ ] `lib/eslint.config.mjs` points `parserOptions.project` to `tsconfig.json`
377
- - [ ] `README.md` starts with Quick Start containing a code example
419
+ - [ ] `lib/README.md` starts with Quick Start and ends with module development commands
378
420
  - [ ] All `[package-name]` placeholders are replaced with the actual name
379
421
  - [ ] Structure matches the layout in [agentme-edr-003](../../003-javascript-project-tooling.md)
380
422
 
@@ -384,9 +426,9 @@ Review all created files and confirm:
384
426
 
385
427
  **Agent action:** Gathers: name=`retry-client`, default Node.js 24, then creates:
386
428
  - `./Makefile`, `./.mise.toml`, `./.gitignore`
387
- - `lib/src/index.ts`, `lib/src/index.test.ts`, `lib/Makefile`, `lib/package.json`, `lib/tsconfig.json`, `lib/jest.config.js`, `lib/eslint.config.mjs`
429
+ - `lib/src/index.ts`, `lib/src/index.test.ts`, `lib/Makefile`, `lib/README.md`, `lib/package.json`, `lib/tsconfig.json`, `lib/jest.config.js`, `lib/eslint.config.mjs`
388
430
  - `examples/Makefile`, `examples/usage-basic/package.json`, `examples/usage-basic/index.js`
389
- - `README.md` (Quick Start first)
431
+ - `README.md` (workspace overview)
390
432
 
391
433
  All `[package-name]` replaced with `retry-client`.
392
434
 
@@ -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 project builds cross-platform static binaries via a Makefile.
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.
16
16
 
17
- Related EDR: [agentme-edr-010](../../010-golang-project-tooling.md)
17
+ Related EDRs: [agentme-edr-010](../../010-golang-project-tooling.md), [agentme-edr-016](../../../principles/016-cross-language-module-structure.md)
18
18
 
19
19
  ## Instructions
20
20
 
@@ -83,11 +83,16 @@ func main() {
83
83
  SHELL := /bin/bash
84
84
 
85
85
  BINARY := [binary]
86
+ CACHE_DIR := .cache
87
+ export GOCACHE := $(abspath $(CACHE_DIR)/go-build)
88
+ export GOMODCACHE := $(abspath $(CACHE_DIR)/go-mod)
89
+ export GOLANGCI_LINT_CACHE := $(abspath $(CACHE_DIR)/golangci-lint)
86
90
 
87
91
  all: build lint test
88
92
 
89
93
  build: install
90
94
  @mkdir -p dist
95
+ @mkdir -p $(GOCACHE) $(GOMODCACHE)
91
96
  go build -o dist/$(BINARY) .
92
97
 
93
98
  build-all: build-arch-os-darwin-amd64 build-arch-os-darwin-arm64 build-arch-os-linux-amd64 build-arch-os-linux-arm64 build-arch-os-windows-amd64
@@ -113,6 +118,7 @@ build-arch-os:
113
118
  @if [ "${ARCH}" == "" ]; then echo "ENV ARCH is required"; exit 1; fi
114
119
  @echo "Compiling $(BINARY) for ${OS}-${ARCH}..."
115
120
  @mkdir -p dist/${OS}-${ARCH}
121
+ @mkdir -p $(GOCACHE) $(GOMODCACHE)
116
122
  go mod download
117
123
  GOOS=${OS} GOARCH=${ARCH} CGO_ENABLED=0 go build -a -o dist/${OS}-${ARCH}/$(BINARY) .
118
124
  @echo "Done"
@@ -130,15 +136,16 @@ test:
130
136
  go test -cover ./...
131
137
 
132
138
  test-coverage:
133
- go test -coverprofile=coverage.out ./...
134
- go tool cover -func coverage.out
139
+ @mkdir -p $(CACHE_DIR)
140
+ go test -coverprofile=$(CACHE_DIR)/coverage.out ./...
141
+ go tool cover -func $(CACHE_DIR)/coverage.out
135
142
 
136
143
  benchmark:
137
144
  go test -bench . -benchmem -count 5 ./...
138
145
 
139
146
  clean:
140
147
  rm -rf dist
141
- rm -f coverage.out
148
+ rm -rf .cache
142
149
 
143
150
  start:
144
151
  go run ./ [subcommand]
@@ -164,6 +171,7 @@ run:
164
171
 
165
172
  ```
166
173
  dist/
174
+ .cache/
167
175
  coverage.out
168
176
  *.pprof
169
177
  .DS_Store
@@ -182,10 +190,10 @@ coverage.out
182
190
 
183
191
  ## Development
184
192
 
185
- make build # compile binary to dist/
186
- make lint # run golangci-lint
187
- make test # run tests with coverage
188
- make start # run locally with default args
193
+ make build # compile binary to dist/
194
+ make lint # run golangci-lint with cache in .cache/
195
+ make test # run tests with coverage artifacts in .cache/
196
+ make start # run locally with default args
189
197
  ```
190
198
 
191
199
  ---
@@ -306,6 +314,8 @@ Fix any compile or lint errors before finishing.
306
314
  - Business logic only in `[feature]/` packages — no flag parsing, no `fmt.Println` for diagnostics.
307
315
  - `cli/[feature]/` owns flags, output, and calls domain. No logic here beyond reading flags and printing results.
308
316
  - All tests co-located (`*_test.go` next to the file under test).
317
+ - Use `tests_integration/` for integration flows and `tests_benchmark/` when benchmarks need dedicated harnesses or datasets.
309
318
  - Log with `logrus`; never use `fmt.Println` for diagnostic/debug output.
310
319
  - All development tasks go through `make` targets — never run `go` directly for routine ops.
311
320
  - Do not create an `internal/` package unless explicitly justified (importability is preferred).
321
+ - If the project is a reusable library, place consumer examples in a sibling `examples/` folder outside the module root and keep them on the public module import path.