agentme 0.1.1

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 (49) hide show
  1. package/.github/agents/speckit.analyze.agent.md +184 -0
  2. package/.github/agents/speckit.checklist.agent.md +295 -0
  3. package/.github/agents/speckit.clarify.agent.md +181 -0
  4. package/.github/agents/speckit.constitution.agent.md +84 -0
  5. package/.github/agents/speckit.implement.agent.md +198 -0
  6. package/.github/agents/speckit.plan.agent.md +90 -0
  7. package/.github/agents/speckit.specify.agent.md +237 -0
  8. package/.github/agents/speckit.tasks.agent.md +200 -0
  9. package/.github/agents/speckit.taskstoissues.agent.md +30 -0
  10. package/.github/prompts/speckit.analyze.prompt.md +3 -0
  11. package/.github/prompts/speckit.checklist.prompt.md +3 -0
  12. package/.github/prompts/speckit.clarify.prompt.md +3 -0
  13. package/.github/prompts/speckit.constitution.prompt.md +3 -0
  14. package/.github/prompts/speckit.implement.prompt.md +3 -0
  15. package/.github/prompts/speckit.plan.prompt.md +3 -0
  16. package/.github/prompts/speckit.specify.prompt.md +3 -0
  17. package/.github/prompts/speckit.tasks.prompt.md +3 -0
  18. package/.github/prompts/speckit.taskstoissues.prompt.md +3 -0
  19. package/.specify/memory/constitution.md +119 -0
  20. package/.specify/scripts/bash/check-prerequisites.sh +190 -0
  21. package/.specify/scripts/bash/common.sh +253 -0
  22. package/.specify/scripts/bash/create-new-feature.sh +333 -0
  23. package/.specify/scripts/bash/setup-plan.sh +73 -0
  24. package/.specify/scripts/bash/update-agent-context.sh +808 -0
  25. package/.specify/templates/agent-file-template.md +28 -0
  26. package/.specify/templates/checklist-template.md +40 -0
  27. package/.specify/templates/constitution-template.md +50 -0
  28. package/.specify/templates/plan-template.md +110 -0
  29. package/.specify/templates/spec-template.md +115 -0
  30. package/.specify/templates/tasks-template.md +251 -0
  31. package/.vscode/settings.json +14 -0
  32. package/.xdrs/agentme/edrs/application/003-javascript-project-tooling.md +89 -0
  33. package/.xdrs/agentme/edrs/application/010-golang-project-tooling.md +141 -0
  34. package/.xdrs/agentme/edrs/application/skills/001-create-javascript-project/SKILL.md +360 -0
  35. package/.xdrs/agentme/edrs/application/skills/003-create-golang-project/SKILL.md +311 -0
  36. package/.xdrs/agentme/edrs/devops/005-monorepo-structure.md +104 -0
  37. package/.xdrs/agentme/edrs/devops/006-github-pipelines.md +170 -0
  38. package/.xdrs/agentme/edrs/devops/008-common-targets.md +207 -0
  39. package/.xdrs/agentme/edrs/devops/skills/002-monorepo-setup/SKILL.md +270 -0
  40. package/.xdrs/agentme/edrs/index.md +41 -0
  41. package/.xdrs/agentme/edrs/observability/011-service-health-check-endpoint.md +78 -0
  42. package/.xdrs/agentme/edrs/principles/002-coding-best-practices.md +110 -0
  43. package/.xdrs/agentme/edrs/principles/004-unit-test-requirements.md +97 -0
  44. package/.xdrs/agentme/edrs/principles/007-project-quality-standards.md +156 -0
  45. package/.xdrs/agentme/edrs/principles/009-error-handling.md +327 -0
  46. package/.xdrs/index.md +32 -0
  47. package/README.md +119 -0
  48. package/bin/npmdata.js +3 -0
  49. package/package.json +102 -0
@@ -0,0 +1,311 @@
1
+ ---
2
+ name: 003-create-golang-project
3
+ description: >
4
+ Scaffolds the initial boilerplate structure for a Go (Golang) CLI or library project following
5
+ the standard tooling and layout defined in agentme-edr-010. Activate this skill when the user
6
+ asks to create, scaffold, or initialize a new Go project, CLI binary, or Go module.
7
+ metadata:
8
+ author: flaviostutz
9
+ version: "1.0"
10
+ compatibility: Go 1.21+
11
+ ---
12
+
13
+ ## Overview
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.
16
+
17
+ Related EDR: [agentme-edr-010](../../010-golang-project-tooling.md)
18
+
19
+ ## Instructions
20
+
21
+ ### Phase 1: Gather information
22
+
23
+ Ask for (or infer from context):
24
+
25
+ - **Module name** — Go module path, e.g. `github.com/<owner>/<project>` (in a monorepo this is typically the workspace module path plus the project subdirectory)
26
+ - **Binary name** — name of the produced CLI binary (default: project name)
27
+ - **Short description** — one sentence
28
+ - **Author** name or GitHub username
29
+ - **Go version** — default `1.24`
30
+ - **First feature package name** — the first domain package to scaffold (e.g. `analyze`, `parse`, `report`)
31
+ - **First CLI subcommand name** — typically matches the feature package (e.g. `analyze`)
32
+ - **Confirm target directory** — default: current workspace root
33
+
34
+ ---
35
+
36
+ ### Phase 2: Create root files
37
+
38
+ **`go.mod`** (replace `[module]`, `[go-version]`):
39
+
40
+ ```
41
+ module [module]
42
+
43
+ go [go-version]
44
+
45
+ require (
46
+ github.com/sirupsen/logrus v1.9.3
47
+ github.com/stretchr/testify v1.9.0
48
+ )
49
+ ```
50
+
51
+ **`main.go`** (replace `[module]`, `[subcommand]`, `[feature]`):
52
+
53
+ ```go
54
+ package main
55
+
56
+ import (
57
+ "fmt"
58
+ "os"
59
+
60
+ cli[Feature] "[module]/cli/[feature]"
61
+ )
62
+
63
+ func main() {
64
+ if len(os.Args) < 2 {
65
+ fmt.Println("Usage: [binary] [[feature]]")
66
+ os.Exit(1)
67
+ }
68
+
69
+ switch os.Args[1] {
70
+ case "[subcommand]":
71
+ cli[Feature].Run(os.Args)
72
+ default:
73
+ fmt.Printf("Unknown command: %s\n", os.Args[1])
74
+ fmt.Println("Usage: [binary] [[feature]]")
75
+ os.Exit(1)
76
+ }
77
+ }
78
+ ```
79
+
80
+ **`Makefile`** (replace `[binary]`):
81
+
82
+ ```makefile
83
+ SHELL := /bin/bash
84
+
85
+ BINARY := [binary]
86
+
87
+ all: build lint test
88
+
89
+ build: install
90
+ @mkdir -p dist
91
+ go build -o dist/$(BINARY) .
92
+
93
+ 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
94
+ @echo "All platform builds complete"
95
+
96
+ build-arch-os-darwin-amd64:
97
+ $(MAKE) build-arch-os OS=darwin ARCH=amd64
98
+
99
+ build-arch-os-darwin-arm64:
100
+ $(MAKE) build-arch-os OS=darwin ARCH=arm64
101
+
102
+ build-arch-os-linux-amd64:
103
+ $(MAKE) build-arch-os OS=linux ARCH=amd64
104
+
105
+ build-arch-os-linux-arm64:
106
+ $(MAKE) build-arch-os OS=linux ARCH=arm64
107
+
108
+ build-arch-os-windows-amd64:
109
+ $(MAKE) build-arch-os OS=windows ARCH=amd64
110
+
111
+ build-arch-os:
112
+ @if [ "${OS}" == "" ]; then echo "ENV OS is required"; exit 1; fi
113
+ @if [ "${ARCH}" == "" ]; then echo "ENV ARCH is required"; exit 1; fi
114
+ @echo "Compiling $(BINARY) for ${OS}-${ARCH}..."
115
+ @mkdir -p dist/${OS}-${ARCH}
116
+ go mod download
117
+ GOOS=${OS} GOARCH=${ARCH} CGO_ENABLED=0 go build -a -o dist/${OS}-${ARCH}/$(BINARY) .
118
+ @echo "Done"
119
+
120
+ install:
121
+ go mod download
122
+
123
+ lint:
124
+ golangci-lint run ./...
125
+
126
+ lint-fix:
127
+ golangci-lint run --fix ./...
128
+
129
+ test:
130
+ go test -cover ./...
131
+
132
+ test-coverage:
133
+ go test -coverprofile=coverage.out ./...
134
+ go tool cover -func coverage.out
135
+
136
+ benchmark:
137
+ go test -bench . -benchmem -count 5 ./...
138
+
139
+ clean:
140
+ rm -rf dist
141
+ rm -f coverage.out
142
+
143
+ start:
144
+ go run ./ [subcommand]
145
+ ```
146
+
147
+ **`.golangci.yml`**:
148
+
149
+ ```yaml
150
+ linters:
151
+ enable:
152
+ - errcheck
153
+ - govet
154
+ - staticcheck
155
+ - unused
156
+ - gosimple
157
+ - ineffassign
158
+ - typecheck
159
+ run:
160
+ timeout: 5m
161
+ ```
162
+
163
+ **`.gitignore`**:
164
+
165
+ ```
166
+ dist/
167
+ coverage.out
168
+ *.pprof
169
+ .DS_Store
170
+ ```
171
+
172
+ **`README.md`** (replace `[binary]`, `[description]`, `[owner]`, `[repo]`):
173
+
174
+ ```markdown
175
+ # [binary]
176
+
177
+ [description]
178
+
179
+ ## Usage
180
+
181
+ [binary] [subcommand] --help
182
+
183
+ ## Development
184
+
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
189
+ ```
190
+
191
+ ---
192
+
193
+ ### Phase 3: Create the feature package
194
+
195
+ **`[feature]/[feature].go`** (replace `[feature]`, `[Feature]`):
196
+
197
+ ```go
198
+ package [feature]
199
+
200
+ import "github.com/sirupsen/logrus"
201
+
202
+ // Options holds the parameters for [Feature] analysis.
203
+ type Options struct {
204
+ Verbose bool
205
+ }
206
+
207
+ // Result holds the output of a [Feature] run.
208
+ type Result struct {
209
+ Summary string
210
+ }
211
+
212
+ // Run executes the [Feature] logic with the given options.
213
+ func Run(opts Options) (Result, error) {
214
+ if opts.Verbose {
215
+ logrus.SetLevel(logrus.DebugLevel)
216
+ }
217
+ logrus.Debug("[Feature] started")
218
+
219
+ // TODO: implement business logic here
220
+
221
+ return Result{Summary: "ok"}, nil
222
+ }
223
+ ```
224
+
225
+ **`[feature]/[feature]_test.go`** (replace `[feature]`, `[Feature]`):
226
+
227
+ ```go
228
+ package [feature]
229
+
230
+ import (
231
+ "testing"
232
+
233
+ "github.com/stretchr/testify/assert"
234
+ "github.com/stretchr/testify/require"
235
+ )
236
+
237
+ func Test[Feature]Run(t *testing.T) {
238
+ result, err := Run(Options{Verbose: false})
239
+ require.NoError(t, err)
240
+ assert.Equal(t, "ok", result.Summary)
241
+ }
242
+ ```
243
+
244
+ ---
245
+
246
+ ### Phase 4: Create the CLI package
247
+
248
+ **`cli/[feature]/[feature].go`** (replace `[module]`, `[feature]`, `[Feature]`, `[subcommand]`):
249
+
250
+ ```go
251
+ package cli[Feature]
252
+
253
+ import (
254
+ "flag"
255
+ "fmt"
256
+ "os"
257
+
258
+ "github.com/sirupsen/logrus"
259
+ "[module]/[feature]"
260
+ )
261
+
262
+ // Run parses CLI flags for the [subcommand] command and calls the domain package.
263
+ func Run(args []string) {
264
+ fs := flag.NewFlagSet("[subcommand]", flag.ExitOnError)
265
+ verbose := fs.Bool("verbose", false, "Show verbose logs during processing")
266
+
267
+ if err := fs.Parse(args[2:]); err != nil {
268
+ fmt.Fprintf(os.Stderr, "error parsing flags: %v\n", err)
269
+ os.Exit(1)
270
+ }
271
+
272
+ if *verbose {
273
+ logrus.SetLevel(logrus.DebugLevel)
274
+ }
275
+
276
+ result, err := [feature].Run([feature].Options{
277
+ Verbose: *verbose,
278
+ })
279
+ if err != nil {
280
+ fmt.Fprintf(os.Stderr, "error: %v\n", err)
281
+ os.Exit(1)
282
+ }
283
+
284
+ fmt.Println(result.Summary)
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ### Phase 5: Verify and run
291
+
292
+ After creating all files, run the following in the project root:
293
+
294
+ ```bash
295
+ go mod tidy
296
+ make all
297
+ ```
298
+
299
+ Fix any compile or lint errors before finishing.
300
+
301
+ ---
302
+
303
+ ## Conventions and reminders
304
+
305
+ - `main.go` dispatches only — no logic.
306
+ - Business logic only in `[feature]/` packages — no flag parsing, no `fmt.Println` for diagnostics.
307
+ - `cli/[feature]/` owns flags, output, and calls domain. No logic here beyond reading flags and printing results.
308
+ - All tests co-located (`*_test.go` next to the file under test).
309
+ - Log with `logrus`; never use `fmt.Println` for diagnostic/debug output.
310
+ - All development tasks go through `make` targets — never run `go` directly for routine ops.
311
+ - Do not create an `internal/` package unless explicitly justified (importability is preferred).
@@ -0,0 +1,104 @@
1
+ # agentme-edr-005: Monorepo structure
2
+
3
+ ## Context and Problem Statement
4
+
5
+ Without a defined monorepo layout, teams independently organize projects in ways that are inconsistent, hard to navigate, and difficult to build uniformly. Shared code gets duplicated, tooling varies per project, and onboarding new contributors is slow because there is no standard entry point or build convention.
6
+
7
+ What monorepo structure, naming conventions, tooling, and build standards should be followed to keep multiple projects cohesive, discoverable, and easy to build?
8
+
9
+ ## Decision Outcome
10
+
11
+ **Adopt a standardized monorepo layout with top-level application folders, a shared library area, Mise-managed tooling, and Makefiles at every level so any contributor can build, lint, and test any part of the monorepo with a single, predictable command.**
12
+
13
+ For step-by-step scaffolding instructions see [skill 002-monorepo-setup](skills/002-monorepo-setup/SKILL.md).
14
+
15
+ ### Policies
16
+
17
+ #### 1. Top-level directory layout
18
+
19
+ ```
20
+ /
21
+ ├── shared/ # Resources shared across ALL applications
22
+ │ ├── libs/ # Reusable libraries consumed by applications
23
+ │ └── scripts/ # Build/CI/dev scripts used across applications
24
+
25
+ ├── <application>/ # One folder per application or project
26
+ │ ├── README.md # REQUIRED
27
+ │ ├── <module>/ # One folder per compilable module
28
+ │ └── shared/ # Resources shared by modules within THIS application
29
+
30
+ ├── Makefile # Root Makefile coordinating all areas
31
+ ├── README.md # REQUIRED — onboarding and quickstart guide
32
+ └── .mise.toml # Mise tool version configuration
33
+ ```
34
+
35
+ #### 2. Application folders
36
+
37
+ - Represent a cohesive unit with its own lifecycle (e.g., `mymobileapp`, `graph-visualizer`).
38
+ - **MUST** depend only on resources in `/shared/`. Direct cross-application dependencies are forbidden; use published artifacts (container images, published libraries) instead.
39
+ - **MUST** contain a `README.md` with: purpose, architecture overview, how to build, and how to run.
40
+
41
+ *Why:* Isolating applications prevents implicit coupling and makes the `shared/` boundary explicit and intentional.
42
+
43
+ #### 3. Module folders
44
+
45
+ - A module is a subfolder inside an application that is independently compilable and produces a build artifact.
46
+ - May depend on sibling modules within the same application or on `/shared/` resources.
47
+ - **MUST NOT** depend on modules from other applications.
48
+
49
+ #### 4. Naming conventions
50
+
51
+ - All folder and file names **MUST** be **lowercase**.
52
+ - Use hyphens (`-`) to separate words (e.g., `data-loader`, `graph-visualizer`).
53
+ - Avoid abbreviations unless universally understood in the domain (e.g., `cli`, `api`).
54
+
55
+ #### 5. Makefiles at every level
56
+
57
+ A `Makefile` **MUST** be present at the repository root, in every application folder, and in every module folder.
58
+
59
+ Each Makefile **MUST** define at minimum: `build`, `lint`, and `test` targets.
60
+
61
+ The root `Makefile` **MUST** also define a `setup` target that guides a new contributor to prepare their machine.
62
+
63
+ *Why:* Makefiles provide a universal, stack-agnostic entry point regardless of programming language.
64
+
65
+ #### 6. Mise for tooling management
66
+
67
+ - [Mise](https://mise.jdx.dev/) **MUST** be used to pin all tool versions (compilers, runtimes, CLI tools).
68
+ - A `.mise.toml` **MUST** exist at the repository root.
69
+ - Every language runtime or CLI referenced by any module `Makefile`, CI workflow, or README command **MUST** be pinned in `.mise.toml`.
70
+ - Contributors run `mise install` once after cloning.
71
+ - Agents and contributors **MUST** check `.mise.toml` before using a system-installed compiler, runtime, or CLI.
72
+ - When `.mise.toml` exists, all build, test, lint, and code-generation commands **MUST** run inside the Mise-managed environment, preferably via `mise exec -- <command>` or an activated Mise shell.
73
+ - If a required tool is missing, the first remediation step **MUST** be to update `.mise.toml` or run `mise install`, not to install ad-hoc global tools with language-specific installers such as `go install`, `npm install -g`, `pip install --user`, or `cargo install`.
74
+ - Root and module `Makefile` targets **SHOULD** work correctly when invoked through `mise exec -- make <target>`.
75
+
76
+ *Why:* Eliminates "works on my machine" build failures by ensuring identical tool versions across all environments.
77
+
78
+ #### 7. Root README
79
+
80
+ The root `README.md` **MUST** include: overview, machine setup, quickstart, and a repository map.
81
+
82
+ #### 8. Git tagging and artifact versioning
83
+
84
+ All releases **MUST** be tagged using the format `<module-name>/<semver>` (e.g., `graphvisualizer/renderer/1.0.0`, `shared/libs/mylib/2.1.0`).
85
+
86
+ `<module-name>` is preferably the path-like identifier of the module being released. A custom name is allowed but the folder name is strongly preferred.
87
+
88
+ *Why:* Namespacing tags by module prevents collisions and makes it easy to filter release history when multiple modules release independently.
89
+
90
+ ---
91
+
92
+ #### 11. Summary of requirements
93
+
94
+ | Requirement | Scope | Mandatory |
95
+ |---|---|---|
96
+ | Lowercase folder/file names | All | Yes |
97
+ | `README.md` per application | Application folders | Yes |
98
+ | `Makefile` with `build`, `lint`, `test` | All modules and applications | Yes |
99
+ | Root `Makefile` with `setup` target | Repository root | Yes |
100
+ | Root `README.md` with setup + quickstart | Repository root | Yes |
101
+ | Mise `.mise.toml` at root | Repository root | Yes |
102
+ | Applications depend only on `/shared/` | Application folders | Yes |
103
+ | Modules depend only on siblings or `/shared/` | Module folders | Yes |
104
+ | Git tags follow `<module-name>/<semver>` format | All modules | Yes |
@@ -0,0 +1,170 @@
1
+ # agentme-edr-006: GitHub CI/CD pipelines
2
+
3
+ ## Context and Problem Statement
4
+
5
+ Without a defined GitHub Actions pipeline structure, projects end up with inconsistent workflows — some combine CI and publishing in a single file, others trigger builds on wrong events, and release tagging is done ad-hoc. This leads to accidental publishes, broken release histories, and non-reproducible builds.
6
+
7
+ What GitHub Actions workflows should every project follow to ensure a safe, predictable, and automated CI/CD lifecycle?
8
+
9
+ ## Decision Outcome
10
+
11
+ **Use three separate, purpose-scoped GitHub Actions workflows: `ci.yml` for build verification on PRs and main, `release.yml` for calculating and creating a version tag with monotag, and `publish.yml` for publishing artifacts when a version tag is pushed.**
12
+
13
+ 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.
14
+
15
+ ### Implementation Details
16
+
17
+ #### Workflow overview
18
+
19
+ | Workflow | Trigger | Purpose |
20
+ |----------|---------|---------|
21
+ | `ci.yml` | `pull_request` → `main`, `push` → `main` | Build, lint, and test the codebase |
22
+ | `release.yml` | `workflow_dispatch` | Tag the next version using monotag |
23
+ | `publish.yml` | `push` of tags matching `*` | Publish artifacts for the tagged version |
24
+
25
+ All workflows run on `ubuntu-latest`. Tool versions MUST be managed by Mise via `jdx/mise-action`. Projects should have a .mise.toml file to configure it
26
+
27
+ ---
28
+
29
+ #### 1. CI workflow — `.github/workflows/ci.yml`
30
+
31
+ Triggered on every PR targeting `main` and every push to `main`. Runs the standard `build`, `lint`, and `test` targets from the root Makefile and fails the workflow if any step exits non-zero.
32
+
33
+ ```yaml
34
+ name: ci
35
+
36
+ on:
37
+ push:
38
+ branches: [main]
39
+ pull_request:
40
+ branches: [main]
41
+
42
+ jobs:
43
+ ci:
44
+ runs-on: ubuntu-latest
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ - uses: jdx/mise-action@v3
48
+ - run: make build
49
+ - run: make lint
50
+ - run: make test
51
+ ```
52
+
53
+ *Why separate steps:* Separate steps surface exactly which phase failed (build, lint, or test) without requiring log inspection.
54
+
55
+ ---
56
+
57
+ #### 2. Release workflow — `.github/workflows/release.yml`
58
+
59
+ Manually dispatched (`workflow_dispatch`). Calculates the next semantic version tag using **monotag** and pushes that tag to the repository. Pushing the tag then automatically triggers the publish workflow.
60
+
61
+ The checkout step **must** use `fetch-depth: 0` so monotag can traverse the full commit history to determine the correct next version.
62
+
63
+ ```yaml
64
+ name: release
65
+
66
+ on:
67
+ workflow_dispatch:
68
+ inputs:
69
+ prerelease:
70
+ description: 'Pre-release'
71
+ type: boolean
72
+ default: true
73
+
74
+ jobs:
75
+ create-tag:
76
+ runs-on: ubuntu-latest
77
+ permissions:
78
+ contents: write
79
+ steps:
80
+ - uses: actions/checkout@v3
81
+ with:
82
+ fetch-depth: 0
83
+ # this is needed if you want the tag push to trigger another workflow
84
+ # create a personal token and set a secret with name GH_PERSONAL_TOKEN
85
+ # https://github.com/orgs/community/discussions/27028
86
+ token: ${{ secrets.GH_PERSONAL_TOKEN }}
87
+ - name: Create tag and push to repo
88
+ run: |
89
+ git config --global user.email "noreply@github.com"
90
+ git config --global user.name "Github Wokflow"
91
+ npx -y monotag@latest tag-push ${{ inputs.prerelease == true && '--pre-release' || '' }}
92
+ ```
93
+
94
+ *Why `workflow_dispatch`:* Manual triggering gives developers explicit control over when a new release tag is created, preventing unintended releases from routine merges.
95
+
96
+ *Why `contents: write`:* Required to allow the workflow to push the new tag back to the repository.
97
+
98
+ ---
99
+
100
+ #### 3. Publish workflow — `.github/workflows/publish.yml`
101
+
102
+ Triggered exclusively when a tag matching `v*.*.*` is pushed to the repository. This ensures only explicitly tagged commits produce published artifacts. Runs `make publish` against the tagged commit.
103
+
104
+ ```yaml
105
+ name: publish
106
+
107
+ on:
108
+ push:
109
+ tags:
110
+ - '*'
111
+
112
+ permissions:
113
+ contents: read
114
+ id-token: write
115
+
116
+ jobs:
117
+ publish:
118
+ runs-on: ubuntu-latest
119
+ steps:
120
+ - uses: actions/checkout@v4
121
+ - uses: jdx/mise-action@v3
122
+ - run: make build
123
+ - run: make lint
124
+ - run: make test
125
+ - run: git reset --hard HEAD
126
+ - run: make publish
127
+
128
+ ```
129
+
130
+ *Why rebuild on publish:* The checkout is done from the exact tag commit. Rebuilding ensures the published artifact matches exactly what is tagged, rather than relying on a prior CI artifact.
131
+
132
+ *Why `id-token: write`:* Required for npm provenance attestation via `npm publish --provenance`, as specified in [agentme-edr-003](003-javascript-project-tooling.md).
133
+
134
+ ---
135
+
136
+ #### Required secrets and permissions
137
+
138
+ | Secret / Permission | Used in | Purpose |
139
+ |--------------------|---------|---------|
140
+ | `GITHUB_TOKEN` (built-in) | `release.yml` | Push newly calculated tag back to the repository |
141
+ | `id-token: write` | `publish.yml` | Generate OIDC token for npm provenance |
142
+ | `contents: write` | `release.yml` | Allow the workflow job to push tags |
143
+
144
+ ---
145
+
146
+ #### Relationship between workflows
147
+
148
+ ```
149
+ PR opened / push to main
150
+
151
+
152
+ ci.yml runs
153
+ (build + lint + test)
154
+
155
+ ▼ (merge to main)
156
+ developer dispatches
157
+ release.yml manually
158
+
159
+
160
+ monotag calculates
161
+ next semver tag
162
+
163
+
164
+ tag pushed → v1.2.3
165
+
166
+
167
+ publish.yml triggered
168
+ (build + publish artifacts)
169
+ ```
170
+