# Development

This repo is built around determinism: the same inputs should produce the same client outputs locally and in CI. These steps keep tooling pinned, workflows repeatable, and changes reviewable so you can trust what ships.

## Prerequisites
- Go 1.26.0+
- Git
- Make (via Xcode Command Line Tools on macOS)
- Recommended: `pre-commit` for local hooks

## macOS quick start (fresh machine)
1. Install Xcode Command Line Tools (includes Git):
   ```bash
   xcode-select --install
   ```
2. Install Go 1.26.0+ (from https://go.dev/dl/) and confirm it works:
   ```bash
   go version
   ```
3. Install `pre-commit` (recommended) and confirm it works:
   ```bash
   pre-commit --version
   ```

## One-time setup (per clone)
```bash
./scripts/setup.sh
```

## Daily workflow
- Use the commands in `docs/agent-layer/COMMANDS.md` for format, lint, test, coverage, and release builds.
- Prefer `make` targets (see `docs/agent-layer/COMMANDS.md`) instead of running `goimports` / `golangci-lint` directly; tools are installed repo-locally under `.tools/bin` so you do not need to edit your shell PATH. This avoids “works on my machine” drift and keeps local output aligned with CI.
- Use `make dev` for a quick local pass (format + fmt-check + lint + coverage + release tests). Run `./scripts/setup.sh` or `make tools` first.
- **Template sources live in `internal/templates/`**, not in `.agent-layer/`. The `.agent-layer/` directory is the *install output* created by `al init`/`al upgrade` in target repos. When adding or editing templates (instructions, memory files, skills, config), always edit the source in `internal/templates/`. If you change installer templates, run `al upgrade` in a target repo to apply the updated templates. When testing from this source repo's scratch target (`tmp/dev-repo`), use `go run ../../cmd/al upgrade` (or `go run ../../cmd/al init` for a fresh repo).
- If template-managed file semantics change for release upgrades, regenerate the release manifest: `./scripts/generate-template-manifest.sh --tag vX.Y.Z`.
- If you change upgrade behavior or upgrade-facing guidance, update the canonical upgrade contract page at `site/docs/upgrades.mdx` and keep release notes/docs links aligned.
- If you change VS Code launch behavior, update `docs/architecture/vscode-launch.md` and keep troubleshooting guidance aligned.

## Go Tooling & Environment
Agent Layer uses several light shell wrappers and `make` targets around standard Go commands (`go fmt`, `go test`, etc.). This is intentional to ensure consistent behavior across local development and CI (GitHub Actions). It also keeps tool versions explicit, which makes regressions easier to trace.

### Common Issues
- **`go mod tidy` or `go run` fails with network errors**: If your environment restricts access to `proxy.golang.org`, you can try setting `GOPROXY=direct` or ensure you have a working internet connection.
- **Permission errors on Go cache**: If you see errors related to `GOCACHE` or `GOMODCACHE`, you can override them to a local directory:
  ```bash
  export GOCACHE=$PWD/tmp/gocache
  export GOMODCACHE=$PWD/tmp/gomodcache
  go mod tidy
  ```
- **Tools not found**: If `make lint` fails because `golangci-lint` is missing, run `make tools` to install all pinned dependencies into `.tools/bin`.

## Run the CLI locally (always uses latest changes)
Run from source (`go run`):
```bash
# One-time init for a fresh repo (creates .agent-layer/ and docs/agent-layer/)
go run ./cmd/al init

# Generate outputs (optional; client commands already sync on run)
go run ./cmd/al sync

# Launch a client (always runs sync first)
go run ./cmd/al agy
```

Optional: build a local dev binary from the current source (no global install):
```bash
go build -o ./tmp/al ./cmd/al
./tmp/al init
./tmp/al agy
```

### Run against a scratch repo (recommended for install/sync testing)
```bash
mkdir -p tmp/dev-repo
cd tmp/dev-repo
go run ../../cmd/al init
go run ../../cmd/al agy
```

Notes:
- `init` is required once per repo to seed `.agent-layer/` and `docs/agent-layer/`.
- `init` prompts to run the setup wizard by default; pass `--no-wizard` to skip (non-interactive shells skip automatically).
- `sync` is optional because `al <client>` always syncs before launch.
- `./scripts/setup.sh` is only for tool + hook setup, not required just to run the CLI.

## Run checks locally
```bash
# Quick pass (format + fmt-check + lint + coverage + release tests)
make dev

# Targeted checks (optional)
make test
make lint
make coverage
```
Notes:
- `make dev` includes coverage and `test-release`; use `make test` when you want a faster loop without the coverage gate and release checks.
- `make test` uses `gotestsum` for more readable output (installed via `make tools`).
- `make lint` and `make test` fail fast if tools are missing; run `make tools` once per clone.

## Full local verification (closest CI parity)
```bash
make ci
make release-dist AL_VERSION=ci DIST_DIR=dist
```
Note: `make ci` includes `make tidy-check`, which fails if `go.mod` or `go.sum` would change. While you are actively editing dependencies, use `make test`, `make lint`, and `make coverage` instead. `make ci` expects tools to be installed via `make tools`. The `make release-dist ...` command mirrors CI's dry-run release artifact build.

## Managing project conventions

`04_conventions.md` contains project-specific defaults (frontend rules, test coverage thresholds, package policies, typing requirements, schema safety). Unlike other instruction files, it is **user-managed**: seeded on `al init` but never overwritten during `al upgrade`. Users can freely edit, add, or remove entries to match their tech stack.

### Ownership model
- **New projects** (`al init`): `04_conventions.md` is created from the template in `internal/templates/instructions/04_conventions.md`.
- **Existing projects** (`al upgrade`): the file is never overwritten. User edits are preserved.
- **Managed diffs**: `04_conventions.md` does not appear in `al upgrade plan` managed diffs.

### Adding a new default convention
Edit `internal/templates/instructions/04_conventions.md`. This only affects new `al init` — existing users are not impacted.

### Delivering a new convention to existing users via migration
To add a convention that existing users should see:
1. Add the convention to `internal/templates/instructions/04_conventions.md` (for new projects).
2. Add an `append_to_file` migration entry to the next version's migration manifest:
   ```json
   {
     "id": "add_<convention_name>",
     "kind": "append_to_file",
     "rationale": "Add <convention description>",
     "source_agnostic": true,
     "path": ".agent-layer/instructions/04_conventions.md",
     "value": "\"- **Convention name:** Convention text.\\n\"",
     "from": "**Convention name:**"
   }
   ```
   - `path`: the file to append to (relative to repo root).
   - `value`: JSON-encoded string content to append.
   - `from`: duplicate-detection match string. If this string is already present in the file, the migration is a no-op.
3. During `al upgrade`, the migration appends the content to the end of the file and reports it in the upgrade output.
4. The user can keep, edit, or remove the convention after upgrade.

### Future enhancement
Per-item accept/reject prompting during upgrade (not yet implemented).

## Troubleshooting
- If you see `golangci-lint: command not found` or `goimports: command not found`, run:
  ```bash
  make tools
  ```

- If `pre-commit install` fails with:
  - `[ERROR] Cowardly refusing to install hooks with core.hooksPath set.`

  Unset it for this repo and retry:
  ```bash
  git config --show-origin --get core.hooksPath
  git config --unset-all core.hooksPath
  # If it was set globally instead:
  # git config --global --unset-all core.hooksPath
  ./scripts/setup.sh
  ```

- If `go mod download` fails due to proxy access, ensure your network can reach `proxy.golang.org` or set `GOPROXY=direct` temporarily.
- If Go reports a cache permission error, the scripts use a repo-local cache by default. To set it manually:
  ```bash
  GOCACHE=.cache/go-build GOMODCACHE=.cache/go-mod go mod tidy
  ```
