Compare commits
2
Commits
v0.1.0
..
46c4416ed4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46c4416ed4 | ||
|
|
7d36785649 |
No files matched your search
+13
-1
@@ -2,7 +2,15 @@ name: ci
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths-ignore:
|
||||||
|
# Keep embedded Markdown templates in CI; paths-ignore cannot undo a match.
|
||||||
|
- "*.md"
|
||||||
|
- "docs/**"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- "*.md"
|
||||||
|
- "docs/**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
@@ -18,7 +26,11 @@ jobs:
|
|||||||
run: test -z "$(gofmt -l .)"
|
run: test -z "$(gofmt -l .)"
|
||||||
- run: go vet ./...
|
- run: go vet ./...
|
||||||
- run: go test -race ./...
|
- run: go test -race ./...
|
||||||
- run: go run ./cmd/docs check
|
- name: Require issue URLs in TODO comments
|
||||||
|
run: |
|
||||||
|
find . -type d \( -name .git -o -name node_modules -o -name vendor -o -name generated -o -name gen -o -name target -o -name dist -o -name build -o -name .svelte-kit -o -name .next \) -prune -o -type f \( -name '*.go' -o -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.svelte' -o -name '*.rs' -o -name '*.sql' -o -name '*.sh' -o -name '*.proto' -o -name '*.graphql' -o -name '*.yml' -o -name '*.yaml' -o -name '*.toml' \) -exec awk 'match($0, "((^|[^:])[/][/]|[/][*]|(^|[[:space:]])(#|--)|^[[:space:]]*([*]|<!--))") { comment=substr($0, RSTART + RLENGTH); todo=index(comment, "TO" "DO"); if (todo && substr(comment, todo + 4) !~ "https?:[/][/]") { print FILENAME ":" FNR ":" $0; bad=1 } } END { exit bad }' {} + # shortcut: line-based scan can flag comment-like strings and misses multiline issue links, use a parser when these need accurate coverage
|
||||||
|
- name: Go lint
|
||||||
|
run: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.15.0 run ./...
|
||||||
- uses: goreleaser/goreleaser-action@v7.3.0
|
- uses: goreleaser/goreleaser-action@v7.3.0
|
||||||
with:
|
with:
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
name: Documentation
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
docs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7.0.1
|
||||||
|
- uses: actions/setup-go@v7.0.0
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: false
|
||||||
|
- run: go run ./cmd/docs check
|
||||||
@@ -15,6 +15,9 @@ jobs:
|
|||||||
- uses: actions/setup-go@v7.0.0
|
- uses: actions/setup-go@v7.0.0
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
- name: Require issue URLs in TODO comments
|
||||||
|
run: |
|
||||||
|
find . -type d \( -name .git -o -name node_modules -o -name vendor -o -name generated -o -name gen -o -name target -o -name dist -o -name build -o -name .svelte-kit -o -name .next \) -prune -o -type f \( -name '*.go' -o -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.svelte' -o -name '*.rs' -o -name '*.sql' -o -name '*.sh' -o -name '*.proto' -o -name '*.graphql' -o -name '*.yml' -o -name '*.yaml' -o -name '*.toml' \) -exec awk 'match($0, "((^|[^:])[/][/]|[/][*]|(^|[[:space:]])(#|--)|^[[:space:]]*([*]|<!--))") { comment=substr($0, RSTART + RLENGTH); todo=index(comment, "TO" "DO"); if (todo && substr(comment, todo + 4) !~ "https?:[/][/]") { print FILENAME ":" FNR ":" $0; bad=1 } } END { exit bad }' {} + # shortcut: line-based scan can flag comment-like strings and misses multiline issue links, use a parser when these need accurate coverage
|
||||||
- uses: goreleaser/goreleaser-action@v7.3.0
|
- uses: goreleaser/goreleaser-action@v7.3.0
|
||||||
with:
|
with:
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
version: "2"
|
||||||
|
linters:
|
||||||
|
default: none
|
||||||
|
enable:
|
||||||
|
- revive
|
||||||
|
settings:
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
- name: exported
|
||||||
|
- name: package-comments
|
||||||
|
exclusions:
|
||||||
|
presets: []
|
||||||
@@ -1,9 +1,51 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
Go module `go.auvem.com/corestack`. Reading map:
|
## Commands
|
||||||
|
- Check: `go build ./...`, `go vet ./...`, `go test -race ./...`, `go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.15.0 run ./...`; from the project root, run the TODO check below.
|
||||||
|
- Generate: No code generation is configured; format with `gofmt -w .`.
|
||||||
|
- Documentation: `go run ./cmd/docs check`; create records with `go run ./cmd/docs new adr|plan "Title"`. This checker repository uses its local implementation as the source of truth.
|
||||||
|
|
||||||
|
## Scope and decisions
|
||||||
|
- Before editing under a directory with its own AGENTS.md, read it. Scoped files: none currently; this root governs the repository, including nested Go modules unless nearer instructions override it.
|
||||||
|
- Explicit user instructions win; nearer scoped rules override broader rules.
|
||||||
|
- Distinguish confirmed requirements, proposed defaults and unresolved decisions; resolve material ambiguity before dependent work.
|
||||||
|
- Proposed ADRs are context, not authority; read relevant accepted decisions before changing their scope.
|
||||||
|
- Before final review and merge, reconcile affected records against the latest target branch plus the PR, following [/docs/adr/README.md](/docs/adr/README.md).
|
||||||
|
- Documentation tier: ADRs only. Create a plan only when work needs durable execution context across areas, phases or sessions; then enable the plans tier.
|
||||||
|
- In a sandbox, request required network/cache access before first codegen; on permission/cache errors retry once with that access. Never hand-edit generated output.
|
||||||
|
- Shared databases and ports may belong to other worktrees/agents; read project rules before starting, stopping or resetting them.
|
||||||
|
- Ask before lint/autofix changes that could alter runtime behavior.
|
||||||
|
- Report commands actually run and their results; never claim an unrun check passed.
|
||||||
|
- Name branches `<type>/<kebab>` without agent-name prefixes.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
- Document package/module purpose, ownership and boundaries, and every public/exported contract in native doc comments; document generated surfaces at their source.
|
||||||
|
- Explain why at invariants, auth decisions, concurrency/ordering, destructive edges and deliberate deviations; no narration, changelog comments or commented-out code.
|
||||||
|
- Use `invariant: <property>`, `authz: <who and enforcement>`, `shortcut: <limit>, <when to upgrade>` on relevant code; retain Go `Deprecated:` and Rust `// SAFETY:`.
|
||||||
|
- Every TODO needs an issue URL; reviewers recheck tagged comments on touched code.
|
||||||
|
|
||||||
|
## Project map
|
||||||
|
|
||||||
|
Go module `go.auvem.com/corestack`.
|
||||||
|
|
||||||
- Build and test: `go build ./...`, `go vet ./...`, `go test -race ./...`; format with `gofmt -w .`.
|
|
||||||
- Docs format (the spec `docs check` implements): `docs/docs-format.md`.
|
- Docs format (the spec `docs check` implements): `docs/docs-format.md`.
|
||||||
- Check records: `go run ./cmd/docs check`. Create one: `go run ./cmd/docs new adr|plan "Title"`.
|
|
||||||
- Decisions live in `docs/adr/`, plans in `docs/plans/`. Records are permanent; never rename them.
|
- Decisions live in `docs/adr/`, plans in `docs/plans/`. Records are permanent; never rename them.
|
||||||
- Dependencies are limited to `go.yaml.in/yaml/v3` and `github.com/yuin/goldmark`.
|
- Add dependencies only to the module that needs them; heavy dependencies go in nested modules (see the [module-boundary ADR](/docs/adr/20261025T214616275Z-version-light-core-packages-in-the-root-module-and-nest-heavy-dependency-modules.md)).
|
||||||
|
|
||||||
|
## Go
|
||||||
|
- Default backend language is Go; follow existing package boundaries.
|
||||||
|
- Define interfaces at the consumer only when a second implementation or a test seam needs one.
|
||||||
|
- Wrap contextual errors with `%w`; inspect causes with `errors.Is`/`errors.As`.
|
||||||
|
- Do not add package-level mutable state or `init` side effects.
|
||||||
|
- Put `context.Context` first in parameters; never store it in a struct.
|
||||||
|
- Give every goroutine an owner and a shutdown path.
|
||||||
|
- Run `gofmt`, `go vet ./...`, tests and the project's configured linter from the owning module.
|
||||||
|
- Use `.golangci.yml` (revive exported/package-comments); the pinned linter command is listed above.
|
||||||
|
|
||||||
|
## TODO check
|
||||||
|
|
||||||
|
Run from the project root (also enforced in CI):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
find . -type d \( -name .git -o -name node_modules -o -name vendor -o -name generated -o -name gen -o -name target -o -name dist -o -name build -o -name .svelte-kit -o -name .next \) -prune -o -type f \( -name '*.go' -o -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.svelte' -o -name '*.rs' -o -name '*.sql' -o -name '*.sh' -o -name '*.proto' -o -name '*.graphql' -o -name '*.yml' -o -name '*.yaml' -o -name '*.toml' \) -exec awk 'match($0, "((^|[^:])[/][/]|[/][*]|(^|[[:space:]])(#|--)|^[[:space:]]*([*]|<!--))") { comment=substr($0, RSTART + RLENGTH); todo=index(comment, "TO" "DO"); if (todo && substr(comment, todo + 4) !~ "https?:[/][/]") { print FILENAME ":" FNR ":" $0; bad=1 } } END { exit bad }' {} + # shortcut: line-based scan can flag comment-like strings and misses multiline issue links, use a parser when these need accurate coverage
|
||||||
|
```
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
title: "Version light core packages in the root module and nest heavy-dependency modules"
|
||||||
|
date: 2026-10-25
|
||||||
|
status: accepted
|
||||||
|
implementation: implemented
|
||||||
|
summary: Keep light core packages on root-module versions and isolate heavy or independently versioned packages in nested modules from their first commit.
|
||||||
|
tags:
|
||||||
|
- modules
|
||||||
|
- versioning
|
||||||
|
supersedes: []
|
||||||
|
superseded_by: []
|
||||||
|
related: []
|
||||||
|
tracking:
|
||||||
|
- https://gitea.auvem.com/corestack/go/issues/2
|
||||||
|
implemented_by:
|
||||||
|
- https://gitea.auvem.com/corestack/go/pulls/4
|
||||||
|
---
|
||||||
|
|
||||||
|
# Version light core packages in the root module and nest heavy-dependency modules
|
||||||
|
|
||||||
|
## Context and Problem Statement
|
||||||
|
|
||||||
|
The repository currently has one Go module, `go.auvem.com/corestack`. A plain `vX.Y.Z` tag versions every package in that module together and triggers a release of the `docs` binary. Light core packages can share this version stream and one changelog per tag; packages with heavy dependencies or independent release needs benefit from their own module boundaries.
|
||||||
|
|
||||||
|
Carving a package out after it has shipped in the root module is the expensive case: older root versions still contain it, while the new nested module supplies the same import path. Consumers can encounter ambiguous imports until coordinated releases and dependency upgrades remove the overlap. Starting a package as a nested module from its first commit avoids that migration.
|
||||||
|
|
||||||
|
The fixed dependency list in AGENTS.md described only the docs checker. It would block the planned Bob and Goose dependencies for `page` and `migrate`; dependency placement needs a module-boundary rule instead of a repository-wide allowlist.
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
* Keep every package in the root module: simplest releases, but couples heavy and independently versioned packages to core releases and makes later extraction costly.
|
||||||
|
* Give every package a nested module immediately: avoids later extraction, but adds module and release bookkeeping to light core packages that can share a version.
|
||||||
|
* Keep light core packages in the root module and start heavy or independently versioned packages as nested modules: retain simple core releases while avoiding the costly extraction case.
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
Choose the mixed boundary: light core packages share the root module; heavy-dependency or independently versioned packages begin as nested modules.
|
||||||
|
|
||||||
|
* Root module, plain `v*` tags: `lifecycle`, `lifecycle/cli`, `migrate`, `page`, and `cmd/docs`. They share one version stream and one changelog per root tag. Before 1.0, breaking changes use minor version bumps.
|
||||||
|
* Nested modules from their first commit: `gql`, `connect`, and any future package that brings heavy dependencies, such as gqlgen or protobuf, or is likely to need independent versioning. Each has its own `go.mod` and directory-prefixed tags, for example `gql/v0.1.0` and `connect/v0.1.0`.
|
||||||
|
* Add dependencies only to the module that needs them. The named core packages remain in the root module; heavy dependencies belong in the relevant nested module.
|
||||||
|
* Keep `cmd/docs` in the root module. The [release workflow](/.gitea/workflows/release.yml) listens only for plain `v*` tags, and [GoReleaser](/.goreleaser.yaml) builds `./cmd/docs`, so only root-module tags publish binaries. Prefixed library tags never publish binaries.
|
||||||
|
|
||||||
|
This decision establishes the boundary before the planned packages are added. The rule is implemented in [AGENTS.md](/AGENTS.md), and the existing release configuration already follows it. Future packages apply the rule when introduced; no empty modules are needed.
|
||||||
|
|
||||||
|
### Consequences
|
||||||
|
|
||||||
|
* Light core packages retain coordinated versions and releases. Consumers do not compile dependencies of packages they do not import; module graph pruning helps limit the dependency graph they load.
|
||||||
|
* Heavy-dependency and independently versioned packages avoid overlapping ownership of an import path with older root-module versions.
|
||||||
|
* Each nested module needs its own dependency maintenance, checks, and prefixed release tags. That bookkeeping is reserved for packages that need the boundary.
|
||||||
|
* Root-module consumers share version bumps even when only another core package changes. Moving a shipped root package into a nested module later still requires coordinated releases and consumer upgrades.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
Baseline copied from corestack/standards at a36288e7cec933a32f4819a1308201027c9f57ec; this project owns and may adapt it.
|
||||||
|
|
||||||
|
# Documentation policy
|
||||||
|
|
||||||
|
The [corestack/go docs-format specification](https://gitea.auvem.com/corestack/go/src/branch/main/docs/docs-format.md) owns record format, templates, and validation. In scaffolded projects, generate records and run checks with the pinned documentation command in the root AGENTS.md; do not maintain local format templates.
|
||||||
|
|
||||||
|
The copied policy is a project-owned baseline that the project may adapt; scaffold re-runs never refresh it unless the owner explicitly asks. The project owns its locked checker pin and upgrades: update the tag and ensure compliance; scaffold re-runs retain the existing pin unless the owner asks.
|
||||||
|
|
||||||
|
## Choose the smallest useful tier
|
||||||
|
|
||||||
|
| Tier | Use when | Scaffold output |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Neither | A single-purpose CLI, library, or script has no consequential architectural choice or durable execution context yet. | No record directories and no docs-check CI step; root instructions tell agents to ask the owner to run scaffold-project to enable records when a consequential choice arises. |
|
||||||
|
| ADRs only | Consequential choices need durable rationale, but execution fits a short issue or PR. | Local policy in docs/adr/README.md, ADRs as warranted and docs-check CI. |
|
||||||
|
| ADRs + plans | Work spans areas, phases, or sessions and needs durable execution context. | Local policy in docs/adr/README.md, a docs/plans/README.md pointer, ADRs as warranted, one file per plan, and docs-check CI. |
|
||||||
|
|
||||||
|
Project size is a signal, not an exemption: a small security-sensitive library can warrant an ADR. Add the CI docs-check step exactly when the selected tier enables records. Change tiers when actual work warrants it; do not create empty record directories in anticipation.
|
||||||
|
|
||||||
|
## Decisions and execution
|
||||||
|
|
||||||
|
Write an ADR for a consequential choice among real alternatives: difficult to reverse, crossing areas, changing a boundary, data model or security posture, or establishing a convention. Routine details and choices already governed by an accepted ADR or practice guide do not need another record. Read relevant accepted decisions and verify their claims against code before dependent work. Proposed ADRs are context, not authority; only the owner accepts a decision.
|
||||||
|
|
||||||
|
Write a plan when work spanning areas, phases or sessions needs durable execution context. Otherwise keep planning in a PR, issue or chat. Each plan has its own file; the directory is the index. Never create a central living plan or living PRD checklist that parallel worktrees continually edit. Closed plans are history, never standing instructions.
|
||||||
|
|
||||||
|
Use `write-adr` and `review-adr` when available: they guide reasoning while deferring textual format to repository conventions. Seek independent review and owner acceptance before treating a proposal as binding. Neither a self-check nor an independent recommendation accepts an ADR. ADRs may share a PR with implementation; no separate ADR PR or extra sections are required by this policy.
|
||||||
|
|
||||||
|
## Reconcile before final review and merge
|
||||||
|
|
||||||
|
Compare the latest target branch plus the PR with the affected decisions and plans, not just the working branch's previous metadata. Update ADR implementation state and `implemented_by` with the real PR URL when delivery evidence supports it. Close finished plans with completion evidence and an Outcome; keep work active when scope remains. Never invent PR links, completed checks, owner acceptance, or delivery evidence. Run `docs check` using the pinned documentation command in the root AGENTS.md after reconciliation.
|
||||||
Reference in new issue
Block a user