Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .agents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# .agents/

Canonical home for AI-agent artifacts in this repo. Follows the **VTEX Engineering Golden Path** layout:

```
.agents/
├── skills/ # Slash-invokable skills — vendored verbatim from vtex/vtex-agent-skills
│ ├── specification/{SKILL.md, references/template.md}
│ └── implementing/SKILL.md
├── commands/ # Custom slash commands (workflow bootstraps for THIS repo)
│ ├── sdd-full-bootstrap.md
│ └── sdd-lite-bootstrap.md
└── rules/ # Always-on rules applied to every conversation (REPO-SPECIFIC)
├── 00-delivery-packages.md
├── 10-test-discipline.md
└── 20-api-discipline.md
```

> **Note:** this is a **published library** (`@vtex/delivery-packages` on npm), not an application. Rules emphasize public-API discipline because every change reaches every consumer.

Each agent reads from a different place. We use symlinks to fan this folder out without duplicating content:

| Tool | Reads from | Mechanism |
|---|---|---|
| Claude Code | `.claude/skills`, `.claude/commands`, `.claude/rules` | Symlinks → `../.agents/*` |
| Cursor | `.cursor/rules/` | Symlink → `../.agents/rules` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O README documenta que Cursor lê as rules de .cursor/rules/ via symlink, mas esse arquivo não foi criado no PR.

Sem ele, agentes usando Cursor não terão as rules de 00-, 10- e 20- auto-attached nas conversas.

Sugestão de follow-up:

mkdir -p .cursor && ln -s ../.agents/rules .cursor/rules

| Copilot | `.github/copilot-instructions.md` | Symlink → `../AGENTS.md` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O README documenta que Copilot lê de .github/copilot-instructions.md (symlink para AGENTS.md), mas o arquivo não foi criado.

Sugestão de follow-up:

mkdir -p .github && ln -s ../AGENTS.md .github/copilot-instructions.md

| Generic | `AGENTS.md` at repo root | Native to Cursor, Copilot; Claude Code reads via `CLAUDE.md` symlink |

## Editing rules

- One rule per file. Filename prefix sets ordering (`00-`, `10-`, `20-`).
- Each rule file has YAML frontmatter with `name`, `description`, and an `applyTo` glob.
- **Skills are vendored verbatim** from upstream. Do not edit `.agents/skills/specification/SKILL.md` or `.agents/skills/implementing/SKILL.md` — refresh from upstream instead (see `skills/README.md`). Repo-specific guidance goes in `rules/`.
- Commands are short workflow bootstraps; their filename (without `.md`) becomes the slash command.
61 changes: 61 additions & 0 deletions .agents/commands/sdd-full-bootstrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
name: sdd-full-bootstrap
description: Walk through the SDD Full (Spec Kit) workflow for a new task in this repo.
---

# /sdd-full-bootstrap

Use this command when you've decided the task warrants **SDD Full** (Spec Kit) — typically >5 days, cross-team, significant architectural impact, or a coordinated breaking change.

**Note for a library:** SDD Full work is rare in `@vtex/delivery-packages`. Most legitimate work here is bug fixes or small additive changes that fit SDD Lite. Use Full only when the public API itself changes in non-trivial ways.

## Prerequisites

- `specify version` works (uv tool installed). Follow `.specify/memory/constitution.md` setup notes
- The Constitution (`.specify/memory/constitution.md`) is up-to-date
- A scoped scope-of-work file exists at `docs/scope_of_work/<feature-name>.md`. Create it from the PRD/RFC sections relevant to this task before running `/speckit.specify`
- The cross-consumer impact has been considered — this is a published library, every API change reaches every consumer

## Sequence (one command, one session — guard your context window)

1. `/speckit.specify` — output: `specs/{feature}/spec.md` (committed)
2. `/speckit.clarify` — surface ambiguities; loop with the PM until resolved; update spec
3. `/speckit.plan` — output: `specs/{feature}/plan.md` (NOT committed)
4. `/speckit.tasks` — output: `specs/{feature}/tasks.md` (NOT committed)
5. `/speckit.analyze` — output: `specs/{feature}/analysis.md` (NOT committed)
6. `/speckit.implement phase 1 only` — work in slices, commit code per slice

After each step, decide whether to start a **new session** to avoid context compaction.

## Models to use

- Steps 1, 3 (specify, plan): Tier-1 reasoning model (e.g. Claude Opus)
- Steps 2, 4, 5, 6 (clarify, tasks, analyze, implement): Standard execution model (e.g. Claude Sonnet)

## What to commit vs not commit

| Artifact | Commit? |
|---|---|
| `specs/{feature}/spec.md` | yes |
| `plan.md`, `tasks.md`, `analysis.md` | no — ephemeral |
| Generated code | yes |
| `.specify/memory/constitution.md` | yes (manual edits only) |
| `dist/` | **no** — generated by `yarn build` at publish time |

## delivery-packages specific notes

- New source files are `.js` only — no TypeScript
- Tests live in `tests/`, named `<name>.test.js` — they are **not colocated** with source
- Run `yarn lint` and `yarn test` before opening a PR — husky will enforce this on push
- For breaking changes, the spec must include the cross-consumer impact analysis in Risks & Mitigations
- Do not change `rollup.config.js` entry points or `package.json` `main`/`module` fields without explicit approval
- Do not add a new runtime dependency to `dependencies` — every byte ships to every consumer
- Do not bump the version in `package.json` — Releasy manages it

## Cross-consumer considerations

This library is consumed by multiple VTEX frontends. Before merging a Full-scope change:

- List the known consumers in Risks & Mitigations (search for `@vtex/delivery-packages` across the VTEX organization)
- Identify which exported function(s) the consumers depend on
- For breaking changes, propose a deprecation path that gives consumers time to migrate (see `.agents/rules/20-api-discipline.md`)
45 changes: 45 additions & 0 deletions .agents/commands/sdd-lite-bootstrap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
name: sdd-lite-bootstrap
description: Walk through the SDD Lite workflow for a small task or bug fix in this repo.
---

# /sdd-lite-bootstrap

Use this command when the work is **small, contained, and lower risk**: bug fixes, additive helpers, focused refactors of internal modules. Most legitimate work in `@vtex/delivery-packages` fits here.

## Sequence

1. `/specification "<task description with definition of done>"`
- Skill produces `specs/<feature-name>.md` with `status: Draft`
- The skill opens a PR on branch `spec/<feature-name>` containing **only** the spec file
2. Review the PR, ask the PM if needed, edit the spec
3. **Manually flip** the spec's frontmatter `Status` from `Draft` to `Approved` and merge the spec PR
4. `/implementing "specs/<feature-name>.md"`
- The skill runs non-interactively: branches `feat/<feature-name>` (or `fix/<feature-name>` for bug fixes), writes failing tests in `tests/`, implements minimal code in `src/`, runs `yarn lint` + `yarn test`, updates CHANGELOG, opens an implementation PR with named sections
- On success, status moves to `Done`. If the spec is contradictory or blocked, the skill opens a GitHub issue titled `implementing blocked: <feature-name>` and ends — no half-baked PR
5. Standard code review and merge

## delivery-packages specific notes

- New source code is `.js` only — no TypeScript
- New tests go in `tests/<name>.test.js` (not colocated with source)
- Use `tests/mockGenerator.js` for building test inputs when possible
- For logic that depends on `@vtex/estimate-calculator`, mock the dependency at the test boundary
- Run `yarn lint` (= `eslint src`) and `yarn test` (= Jest) — husky enforces this on push
- New public functions must be re-exported from `src/index.js` and documented in `README.md`
- Do not write tests in CommonJS — use ES modules (Babel transforms them at test time)
- Do not commit `dist/` — it's generated at publish time by Rollup

## When to NOT use SDD Lite

Switch to `/sdd-full-bootstrap` if any of the following apply:

- Estimated effort >5 days
- **The work changes the public API** in a breaking way (removing exports, renaming parameters, changing return shapes, changing defaults) — see `.agents/rules/20-api-discipline.md`
- Adding a new runtime dependency to `dependencies` — every byte ships to every consumer; this is a coordinated decision
- Bumping a major version of a devDependency (Babel 6, Jest 22, ESLint 4, Rollup 0.56) — coordinated tooling decision
- Changes to `rollup.config.js` build configuration
- Changes to `package.json` `main`/`module` entry-point fields
- High ambiguity, unresolved product decisions
- Cross-consumer coordination needed for a breaking change
- Adding CI/CD workflows under `.github/workflows/`
111 changes: 111 additions & 0 deletions .agents/rules/00-delivery-packages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
name: delivery-packages-baseline
description: Baseline rules every agent must follow when editing this repo.
applyTo: "**/*"
---

# Baseline rules — vtex/delivery-packages

These rules apply to **every** agent conversation in this repo. They override generic best practices and codify the library's standards.

## Repository purpose

`@vtex/delivery-packages` is a **published JavaScript library** (npm: `@vtex/delivery-packages`) that provides helper functions for splitting order items into delivery parcels and supporting delivery-selection UIs. It is consumed as a runtime dependency by multiple VTEX frontends.

Because this is a published library — not an application — **every change to the public API affects every consumer**.

## Stack (do not invent alternatives — versions are deliberately frozen)

- **Build system:** Rollup 0.56 driven by `rollup.config.js`. Produces two dist outputs:
- `dist/index.js` — CommonJS (`main` in package.json)
- `dist/index.esm.js` — ES Modules (`module` in package.json, for tree-shaking)
- **Transpilation:** Babel 6 with `babel-preset-env` and `babel-plugin-transform-object-rest-spread`. Production build uses `external-helpers` to keep dist size small. The `production` env preset sets `modules: false` so Rollup can do the ESM emission
- **Source language:** JavaScript only — pure ES modules using `import`/`export`. No TypeScript
- **Testing:** Jest 22 + babel-jest 22
- **Linting:** ESLint 4 with `eslint-config-vtex` + `eslint-plugin-jest`
- **Formatting:** Prettier — no semicolons, single quotes, trailing comma es5
- **Git hooks:** Husky 1
- **Package manager:** both `yarn.lock` and `package-lock.json` exist; Yarn is the historical choice but npm works
- **The single runtime dependency** is `@vtex/estimate-calculator`. Adding a second is a deliberate decision

## Code style — non-negotiable

- New code is **JavaScript only** — no TypeScript
- 2 spaces, LF, UTF-8
- ESLint authority: `eslint-config-vtex` via `.eslintrc`. Plugin: `eslint-plugin-jest`
- Prettier authority: `.prettierrc` (no semicolons, single quotes, trailing comma es5)
- **Always run `yarn lint` and `yarn test` before opening a PR** — husky enforces this on push
- Never disable an ESLint rule without an inline comment explaining why

## Public API discipline

This is the most important rule for this repo:

- **The public API is whatever `src/index.js` re-exports.** Adding, removing, or renaming a named export is a **breaking change**
- **Parameter signatures are part of the contract.** Adding a parameter at the end is non-breaking; adding it in the middle, renaming it, or changing its semantics is breaking
- **Return shape is part of the contract.** Renaming a field on a returned object is breaking
- **Defaults are part of the contract.** Changing a default value is breaking
- Breaking changes require:
- `BREAKING CHANGE:` footer in the Conventional Commit
- Explicit call-out in the PR description
- A `### Breaking Changes` section in `CHANGELOG.md`
- Coordination with downstream consumers — agents do not make this call alone

## Architectural rules

- **Source files in `src/` are pure helpers.** No side effects beyond returning values. No network calls. No DOM access. No storage access
- **`src/index.js` is the public surface.** Internal-only helpers must not be re-exported from `index.js`
- **`src/constants.js` is the place for shared enums.** Do not duplicate string literals across modules
- **`src/polyfills.js` is intentionally minimal** — only polyfills strictly required by the helpers
- **No runtime side effects on import.** Importing any module from `src/` must not register globals, attach listeners, or run network calls
- **`dist/` is generated** — never commit, never edit by hand

## Dependency rules

- **The single runtime dependency is `@vtex/estimate-calculator`.** Adding another `dependencies` entry requires explicit justification — every byte ships to every consumer
- **devDependencies are pinned to old major versions** (Babel 6, Jest 22, ESLint 4, Rollup 0.56) — bumping is a coordinated tooling decision, not a casual change
- **Do not add a `peerDependency`** without team approval — peer deps complicate consumer installs
- **Do not switch package manager** between yarn and npm in a single PR — pick one and stay consistent with the surrounding commits

## Versioning & releases

- Releases are gated by **Releasy** (`_releasy.json`)
- Agents do **not** bump the version in `package.json` or run `npm publish` / `yarn publish`
- `CHANGELOG.md` follows Keep a Changelog. Breaking changes go under `### Breaking Changes` — not under `### Changed`
- The `prepublishOnly` hook ensures `dist/` is rebuilt before publishing

## Husky hooks

- `lint-not-beta` and `test-not-beta` are husky hooks that run lint and tests on changed files. They skip on the `beta` branch (which is the release-staging branch)
- Do not bypass husky with `--no-verify` to "make CI pass" — fix the underlying issue instead

## Sensitive areas — extra caution

- `src/index.js` — public API surface
- `src/parcel.js` — parcelify is the central function of the library; bugs here propagate to every consumer
- `src/sla.js` — SLA selection logic; bugs affect shipping options shown to shoppers
- `src/shipping.js` — shipping computation; bugs may show wrong delivery dates
- `tests/Order.json` — shared fixture; changing it can break unrelated tests
- `rollup.config.js` — changing dist output structure affects downstream resolution

## Autonomy limits — always ask before crossing these

- **Do not change the public API surface** (`src/index.js` re-exports, parameter signatures, return shapes, default values)
- **Do not modify `rollup.config.js`** or `package.json` `main`/`module` fields
- **Do not bump major versions** of Babel 6, Jest 22, ESLint 4, Rollup 0.56
- **Do not add a new runtime dependency** to `dependencies`
- **Do not modify `_releasy.json`, `pachamama.config`, or `.github/CODEOWNERS`**
- **Do not modify `.eslintrc`, `.babelrc`, or `.prettierrc`**
- **Do not run `npm publish` / `yarn publish`** — releases are team-gated
- **Do not bump the repo version** in `package.json` — Releasy manages it
- **Do not add CI/CD workflows** under `.github/workflows/` without team approval
- **Do not introduce TypeScript wholesale**

## Things NOT to do

- Do not re-export internal helpers from `src/index.js` to make them "easier to test" — write the test against the internal module directly
- Do not write tests in CommonJS (`require`/`module.exports`) — the Jest setup uses Babel to transform ES modules
- Do not commit `dist/`
- Do not commit `.env`, real credentials, or API keys
- Do not use `--no-verify` to bypass husky
- Do not introduce snapshot tests as a primary verification mechanism — prefer explicit assertions
70 changes: 70 additions & 0 deletions .agents/rules/10-test-discipline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
name: test-discipline
description: Test-first conventions for delivery-packages changes.
applyTo: "src/**/*.js"
---

# Test discipline — vtex/delivery-packages

## Order of operations

1. Read the spec or bug description
2. Identify the function(s) in `src/` that change
3. Write or extend the corresponding test in `tests/<name>.test.js` (red first)
4. Implement the minimum code in `src/<name>.js` to flip them green
5. Run `yarn lint` and `yarn test` before opening a PR

Husky enforces lint + tests on push (`lint-not-beta` and `test-not-beta`).

## Test runner

- Test framework: **Jest 22**, run via `yarn test` (= `cross-env NODE_ENV=test jest`)
- Watch mode: `yarn jest` (= `jest --watch --verbose --coverage=false`)
- With coverage: `yarn test:coverage` (= `jest --coverage`)
- Pick **either** yarn or npm and stay consistent within a single PR

## File convention

- **Tests live in `tests/`** at repo root — they are **not colocated** with source
- File naming: `<name>.test.js` to mirror the source module
- Example: `src/parcel.js` → `tests/parcel.test.js`
- The public API tests (the `parcelify` function exported from `src/index.js`) live in `tests/index.test.js`

## Shared test helpers

- **`tests/Order.json`** — a large realistic fixture representing a VTEX order. Prefer extending it carefully over creating ad-hoc fixtures from scratch
- **`tests/mockGenerator.js`** — shared helper for building test inputs. Use it in new tests for consistency

## What requires a unit test

- Every new function added to `src/`
- Every change to an exported function's behavior (including parameter handling, return shape, edge cases)
- Every bug fix — add a failing regression test before the fix
- Logic that depends on `@vtex/estimate-calculator` — mock the dependency at the test boundary
- Breaking-change PRs — the test must explicitly verify the new behavior **and** the old behavior must be documented as removed in the CHANGELOG

## What does NOT require a unit test

- Pure dependency version bumps within the same major (when allowed)
- Documentation-only changes (`README.md`, `CHANGELOG.md`, inline comments)
- Changes to `.eslintrc`, `.prettierrc`, `.babelrc` configuration (which would themselves need team approval)

## Mocking conventions

- Use Jest's built-in mocking (`jest.fn`, `jest.mock`)
- Mock `@vtex/estimate-calculator` at the boundary — do not let real estimate calculations run inside helper tests
- Prefer constructing the input object directly (or via `mockGenerator.js`) over loading the full `Order.json` fixture when a small subset is sufficient
- Do not use `jest.config.js` overrides — the default Jest config is intentional

## Snapshot tests

- **Avoid snapshot tests in this repo.** Use explicit assertions on the return shape
- If a snapshot is unavoidable (e.g., for a large parcelify output), commit it deliberately and review every diff
- Never use `--updateSnapshot` to clear noise

## Coverage

- `yarn test:coverage` produces a report
- **No coverage threshold is enforced today**
- Do not let coverage drop on changed files
- Do not add a coverage threshold unilaterally — team decision
Loading
Loading