aigent-team 0.1.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +253 -0
  3. package/dist/chunk-N3RYHWTR.js +267 -0
  4. package/dist/cli.js +576 -0
  5. package/dist/index.d.ts +234 -0
  6. package/dist/index.js +27 -0
  7. package/package.json +67 -0
  8. package/templates/shared/git-workflow.md +44 -0
  9. package/templates/shared/project-conventions.md +48 -0
  10. package/templates/teams/ba/agent.yaml +25 -0
  11. package/templates/teams/ba/references/acceptance-criteria.md +87 -0
  12. package/templates/teams/ba/references/api-contract-design.md +110 -0
  13. package/templates/teams/ba/references/requirements-analysis.md +83 -0
  14. package/templates/teams/ba/references/user-story-mapping.md +73 -0
  15. package/templates/teams/ba/skill.md +85 -0
  16. package/templates/teams/be/agent.yaml +34 -0
  17. package/templates/teams/be/conventions.md +102 -0
  18. package/templates/teams/be/references/api-design.md +91 -0
  19. package/templates/teams/be/references/async-processing.md +86 -0
  20. package/templates/teams/be/references/auth-security.md +58 -0
  21. package/templates/teams/be/references/caching.md +79 -0
  22. package/templates/teams/be/references/database.md +65 -0
  23. package/templates/teams/be/references/error-handling.md +106 -0
  24. package/templates/teams/be/references/observability.md +83 -0
  25. package/templates/teams/be/references/review-checklist.md +50 -0
  26. package/templates/teams/be/references/testing.md +100 -0
  27. package/templates/teams/be/review-checklist.md +54 -0
  28. package/templates/teams/be/skill.md +71 -0
  29. package/templates/teams/devops/agent.yaml +35 -0
  30. package/templates/teams/devops/conventions.md +133 -0
  31. package/templates/teams/devops/references/ci-cd.md +218 -0
  32. package/templates/teams/devops/references/cost-optimization.md +218 -0
  33. package/templates/teams/devops/references/disaster-recovery.md +199 -0
  34. package/templates/teams/devops/references/docker.md +237 -0
  35. package/templates/teams/devops/references/infrastructure-as-code.md +238 -0
  36. package/templates/teams/devops/references/kubernetes.md +397 -0
  37. package/templates/teams/devops/references/monitoring.md +224 -0
  38. package/templates/teams/devops/references/review-checklist.md +149 -0
  39. package/templates/teams/devops/references/security.md +225 -0
  40. package/templates/teams/devops/review-checklist.md +72 -0
  41. package/templates/teams/devops/skill.md +131 -0
  42. package/templates/teams/fe/agent.yaml +28 -0
  43. package/templates/teams/fe/conventions.md +80 -0
  44. package/templates/teams/fe/references/accessibility.md +92 -0
  45. package/templates/teams/fe/references/component-architecture.md +87 -0
  46. package/templates/teams/fe/references/css-styling.md +89 -0
  47. package/templates/teams/fe/references/forms.md +73 -0
  48. package/templates/teams/fe/references/performance.md +104 -0
  49. package/templates/teams/fe/references/review-checklist.md +51 -0
  50. package/templates/teams/fe/references/security.md +90 -0
  51. package/templates/teams/fe/references/state-management.md +117 -0
  52. package/templates/teams/fe/references/testing.md +112 -0
  53. package/templates/teams/fe/review-checklist.md +53 -0
  54. package/templates/teams/fe/skill.md +68 -0
  55. package/templates/teams/lead/agent.yaml +18 -0
  56. package/templates/teams/lead/references/cross-team-coordination.md +68 -0
  57. package/templates/teams/lead/references/quality-gates.md +64 -0
  58. package/templates/teams/lead/references/task-decomposition.md +69 -0
  59. package/templates/teams/lead/skill.md +83 -0
  60. package/templates/teams/qa/agent.yaml +32 -0
  61. package/templates/teams/qa/conventions.md +130 -0
  62. package/templates/teams/qa/references/ci-integration.md +337 -0
  63. package/templates/teams/qa/references/e2e-testing.md +292 -0
  64. package/templates/teams/qa/references/mocking.md +249 -0
  65. package/templates/teams/qa/references/performance-testing.md +288 -0
  66. package/templates/teams/qa/references/review-checklist.md +143 -0
  67. package/templates/teams/qa/references/security-testing.md +271 -0
  68. package/templates/teams/qa/references/test-data.md +275 -0
  69. package/templates/teams/qa/references/test-strategy.md +192 -0
  70. package/templates/teams/qa/review-checklist.md +53 -0
  71. package/templates/teams/qa/skill.md +131 -0
@@ -0,0 +1,234 @@
1
+ import { z } from 'zod';
2
+
3
+ declare const PLATFORMS: readonly ["claude-code", "cursor", "codex", "antigravity"];
4
+ type Platform = (typeof PLATFORMS)[number];
5
+ declare const TEAM_ROLES: readonly ["lead", "ba", "fe", "be", "qa", "devops"];
6
+ type TeamRole = (typeof TEAM_ROLES)[number];
7
+ interface ReferenceFile {
8
+ id: string;
9
+ title: string;
10
+ description: string;
11
+ whenToRead: string;
12
+ content: string;
13
+ }
14
+ interface TechStackConfig {
15
+ languages: string[];
16
+ frameworks: string[];
17
+ libraries: string[];
18
+ buildTools: string[];
19
+ }
20
+ interface ToolPermissions {
21
+ allowed: string[];
22
+ denied?: string[];
23
+ }
24
+ interface WorkflowDefinition {
25
+ name: string;
26
+ description: string;
27
+ steps: string[];
28
+ }
29
+ interface AgentDefinition {
30
+ id: string;
31
+ name: string;
32
+ description: string;
33
+ role: TeamRole;
34
+ systemPrompt: string;
35
+ skillContent: string;
36
+ techStack: TechStackConfig;
37
+ conventions: string;
38
+ reviewChecklist: string;
39
+ tools: ToolPermissions;
40
+ workflows: WorkflowDefinition[];
41
+ sharedKnowledge: string[];
42
+ references: ReferenceFile[];
43
+ globs?: string[];
44
+ }
45
+ declare const ConfigSchema: z.ZodObject<{
46
+ projectName: z.ZodString;
47
+ platforms: z.ZodArray<z.ZodEnum<["claude-code", "cursor", "codex", "antigravity"]>, "many">;
48
+ teams: z.ZodArray<z.ZodEnum<["lead", "ba", "fe", "be", "qa", "devops"]>, "many">;
49
+ overrides: z.ZodOptional<z.ZodRecord<z.ZodEnum<["lead", "ba", "fe", "be", "qa", "devops"]>, z.ZodObject<{
50
+ name: z.ZodOptional<z.ZodString>;
51
+ description: z.ZodOptional<z.ZodString>;
52
+ systemPrompt: z.ZodOptional<z.ZodString>;
53
+ techStack: z.ZodOptional<z.ZodObject<{
54
+ languages: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
55
+ frameworks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
56
+ libraries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
57
+ buildTools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
58
+ }, "strip", z.ZodTypeAny, {
59
+ languages?: string[] | undefined;
60
+ frameworks?: string[] | undefined;
61
+ libraries?: string[] | undefined;
62
+ buildTools?: string[] | undefined;
63
+ }, {
64
+ languages?: string[] | undefined;
65
+ frameworks?: string[] | undefined;
66
+ libraries?: string[] | undefined;
67
+ buildTools?: string[] | undefined;
68
+ }>>;
69
+ conventions: z.ZodOptional<z.ZodString>;
70
+ reviewChecklist: z.ZodOptional<z.ZodString>;
71
+ tools: z.ZodOptional<z.ZodObject<{
72
+ allowed: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
73
+ denied: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
74
+ }, "strip", z.ZodTypeAny, {
75
+ allowed?: string[] | undefined;
76
+ denied?: string[] | undefined;
77
+ }, {
78
+ allowed?: string[] | undefined;
79
+ denied?: string[] | undefined;
80
+ }>>;
81
+ globs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
82
+ }, "strip", z.ZodTypeAny, {
83
+ name?: string | undefined;
84
+ description?: string | undefined;
85
+ systemPrompt?: string | undefined;
86
+ techStack?: {
87
+ languages?: string[] | undefined;
88
+ frameworks?: string[] | undefined;
89
+ libraries?: string[] | undefined;
90
+ buildTools?: string[] | undefined;
91
+ } | undefined;
92
+ conventions?: string | undefined;
93
+ reviewChecklist?: string | undefined;
94
+ tools?: {
95
+ allowed?: string[] | undefined;
96
+ denied?: string[] | undefined;
97
+ } | undefined;
98
+ globs?: string[] | undefined;
99
+ }, {
100
+ name?: string | undefined;
101
+ description?: string | undefined;
102
+ systemPrompt?: string | undefined;
103
+ techStack?: {
104
+ languages?: string[] | undefined;
105
+ frameworks?: string[] | undefined;
106
+ libraries?: string[] | undefined;
107
+ buildTools?: string[] | undefined;
108
+ } | undefined;
109
+ conventions?: string | undefined;
110
+ reviewChecklist?: string | undefined;
111
+ tools?: {
112
+ allowed?: string[] | undefined;
113
+ denied?: string[] | undefined;
114
+ } | undefined;
115
+ globs?: string[] | undefined;
116
+ }>>>;
117
+ shared: z.ZodOptional<z.ZodObject<{
118
+ conventions: z.ZodOptional<z.ZodString>;
119
+ apiSpecs: z.ZodOptional<z.ZodString>;
120
+ architecture: z.ZodOptional<z.ZodString>;
121
+ }, "strip", z.ZodTypeAny, {
122
+ conventions?: string | undefined;
123
+ apiSpecs?: string | undefined;
124
+ architecture?: string | undefined;
125
+ }, {
126
+ conventions?: string | undefined;
127
+ apiSpecs?: string | undefined;
128
+ architecture?: string | undefined;
129
+ }>>;
130
+ output: z.ZodOptional<z.ZodObject<{
131
+ directory: z.ZodOptional<z.ZodString>;
132
+ }, "strip", z.ZodTypeAny, {
133
+ directory?: string | undefined;
134
+ }, {
135
+ directory?: string | undefined;
136
+ }>>;
137
+ }, "strip", z.ZodTypeAny, {
138
+ projectName: string;
139
+ platforms: ("claude-code" | "cursor" | "codex" | "antigravity")[];
140
+ teams: ("lead" | "ba" | "fe" | "be" | "qa" | "devops")[];
141
+ overrides?: Partial<Record<"lead" | "ba" | "fe" | "be" | "qa" | "devops", {
142
+ name?: string | undefined;
143
+ description?: string | undefined;
144
+ systemPrompt?: string | undefined;
145
+ techStack?: {
146
+ languages?: string[] | undefined;
147
+ frameworks?: string[] | undefined;
148
+ libraries?: string[] | undefined;
149
+ buildTools?: string[] | undefined;
150
+ } | undefined;
151
+ conventions?: string | undefined;
152
+ reviewChecklist?: string | undefined;
153
+ tools?: {
154
+ allowed?: string[] | undefined;
155
+ denied?: string[] | undefined;
156
+ } | undefined;
157
+ globs?: string[] | undefined;
158
+ }>> | undefined;
159
+ shared?: {
160
+ conventions?: string | undefined;
161
+ apiSpecs?: string | undefined;
162
+ architecture?: string | undefined;
163
+ } | undefined;
164
+ output?: {
165
+ directory?: string | undefined;
166
+ } | undefined;
167
+ }, {
168
+ projectName: string;
169
+ platforms: ("claude-code" | "cursor" | "codex" | "antigravity")[];
170
+ teams: ("lead" | "ba" | "fe" | "be" | "qa" | "devops")[];
171
+ overrides?: Partial<Record<"lead" | "ba" | "fe" | "be" | "qa" | "devops", {
172
+ name?: string | undefined;
173
+ description?: string | undefined;
174
+ systemPrompt?: string | undefined;
175
+ techStack?: {
176
+ languages?: string[] | undefined;
177
+ frameworks?: string[] | undefined;
178
+ libraries?: string[] | undefined;
179
+ buildTools?: string[] | undefined;
180
+ } | undefined;
181
+ conventions?: string | undefined;
182
+ reviewChecklist?: string | undefined;
183
+ tools?: {
184
+ allowed?: string[] | undefined;
185
+ denied?: string[] | undefined;
186
+ } | undefined;
187
+ globs?: string[] | undefined;
188
+ }>> | undefined;
189
+ shared?: {
190
+ conventions?: string | undefined;
191
+ apiSpecs?: string | undefined;
192
+ architecture?: string | undefined;
193
+ } | undefined;
194
+ output?: {
195
+ directory?: string | undefined;
196
+ } | undefined;
197
+ }>;
198
+ type AigentTeamConfig = z.infer<typeof ConfigSchema>;
199
+ interface CompiledOutput {
200
+ filePath: string;
201
+ content: string;
202
+ overwriteStrategy: 'replace' | 'merge' | 'skip-if-exists';
203
+ }
204
+ interface ValidationResult {
205
+ valid: boolean;
206
+ errors: string[];
207
+ warnings: string[];
208
+ }
209
+
210
+ declare function loadConfig(cwd?: string): Promise<AigentTeamConfig>;
211
+ declare function configExists(cwd?: string): boolean;
212
+
213
+ declare function loadAgents(config: AigentTeamConfig, cwd?: string): AgentDefinition[];
214
+
215
+ /**
216
+ * Assemble the slim skill index for an agent (~150-200 lines).
217
+ * Used as the primary agent content that's always loaded.
218
+ * If agent has skillContent (from skill.md), use that directly.
219
+ * Otherwise, fall back to legacy assembly from parts.
220
+ */
221
+ declare function assembleSkillIndex(agent: AgentDefinition): string;
222
+ /**
223
+ * Legacy: assemble full agent markdown from all parts.
224
+ * Used when no skill.md exists.
225
+ */
226
+ declare function assembleAgentMarkdown(agent: AgentDefinition): string;
227
+ /**
228
+ * Format a single reference file for output.
229
+ */
230
+ declare function assembleReference(ref: ReferenceFile): string;
231
+
232
+ declare function defineConfig(config: AigentTeamConfig): AigentTeamConfig;
233
+
234
+ export { type AgentDefinition, type AigentTeamConfig, type CompiledOutput, PLATFORMS, type Platform, type ReferenceFile, TEAM_ROLES, type TeamRole, type TechStackConfig, type ToolPermissions, type ValidationResult, type WorkflowDefinition, assembleAgentMarkdown, assembleReference, assembleSkillIndex, configExists, defineConfig, loadAgents, loadConfig };
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ import { createRequire } from 'module'; const require = createRequire(import.meta.url);
2
+ import {
3
+ PLATFORMS,
4
+ TEAM_ROLES,
5
+ assembleAgentMarkdown,
6
+ assembleReference,
7
+ assembleSkillIndex,
8
+ configExists,
9
+ loadAgents,
10
+ loadConfig
11
+ } from "./chunk-N3RYHWTR.js";
12
+
13
+ // src/index.ts
14
+ function defineConfig(config) {
15
+ return config;
16
+ }
17
+ export {
18
+ PLATFORMS,
19
+ TEAM_ROLES,
20
+ assembleAgentMarkdown,
21
+ assembleReference,
22
+ assembleSkillIndex,
23
+ configExists,
24
+ defineConfig,
25
+ loadAgents,
26
+ loadConfig
27
+ };
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "aigent-team",
3
+ "version": "0.1.0",
4
+ "description": "Cross-platform AI agent team plugin for Claude Code, Cursor, Codex, and Antigravity",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "aigent-team": "./dist/cli.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "templates"
20
+ ],
21
+ "scripts": {
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "lint": "tsc --noEmit",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "ai",
31
+ "agent",
32
+ "claude",
33
+ "cursor",
34
+ "codex",
35
+ "antigravity",
36
+ "cli"
37
+ ],
38
+ "author": "Đức Trần Xuân <ductranxuan.29710@gmail.com> (https://github.com/ducsatthu)",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/ducsatthu/aigent-team.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/ducsatthu/aigent-team/issues"
45
+ },
46
+ "homepage": "https://github.com/ducsatthu/aigent-team#readme",
47
+ "license": "MIT",
48
+ "engines": {
49
+ "node": ">=18"
50
+ },
51
+ "dependencies": {
52
+ "chalk": "^5.4.1",
53
+ "commander": "^13.1.0",
54
+ "deepmerge-ts": "^7.1.5",
55
+ "glob": "^11.0.1",
56
+ "gray-matter": "^4.0.3",
57
+ "inquirer": "^12.4.0",
58
+ "yaml": "^2.7.1",
59
+ "zod": "^3.24.3"
60
+ },
61
+ "devDependencies": {
62
+ "@types/node": "^22.13.0",
63
+ "tsup": "^8.4.0",
64
+ "typescript": "^5.7.3",
65
+ "vitest": "^3.1.1"
66
+ }
67
+ }
@@ -0,0 +1,44 @@
1
+ ## Branch Strategy
2
+
3
+ - **Main branch** (`main`): Always deployable. Protected — no direct pushes. All changes via PR.
4
+ - **Feature branches**: `feat/{ticket-id}-{short-description}` — e.g., `feat/PROJ-123-add-oauth-login`
5
+ - **Bug fix branches**: `fix/{ticket-id}-{short-description}` — e.g., `fix/PROJ-456-null-pointer-on-empty-cart`
6
+ - **Other types**: `refactor/`, `docs/`, `test/`, `chore/`, `ci/`
7
+ - **Hotfix**: `hotfix/{ticket-id}-{description}` — branches from the production tag, merges to main AND production.
8
+
9
+ ## Commit Standards
10
+
11
+ - Follow Conventional Commits: `type(scope): description`
12
+ - `feat`: New functionality visible to users
13
+ - `fix`: Bug fix
14
+ - `refactor`: Code change that neither fixes a bug nor adds a feature
15
+ - `test`: Adding or modifying tests
16
+ - `docs`: Documentation only
17
+ - `chore`: Build process, tooling, dependency updates
18
+ - `ci`: CI/CD pipeline changes
19
+ - `perf`: Performance improvement
20
+ - Description is imperative mood, lowercase, no period: `add login form` not `Added login form.`
21
+ - Body (optional): explain **why**, not what. The diff shows what changed.
22
+ - Breaking changes: add `!` after type — `feat(api)!: remove deprecated /v1/users endpoint`
23
+
24
+ ## Pull Request Process
25
+
26
+ 1. **Before opening PR**: Rebase on latest main. Run linter + tests locally. Self-review your own diff.
27
+ 2. **PR title**: Same as commit message format. Keep under 72 characters.
28
+ 3. **PR description must include**:
29
+ - **What**: Brief summary of the change (1-3 sentences)
30
+ - **Why**: Link to ticket/issue. Business context for the change.
31
+ - **How to test**: Step-by-step verification instructions. Include curl commands, screenshots, or test commands.
32
+ - **Breaking changes**: If any, describe migration steps.
33
+ 4. **Review requirements**: Minimum 1 approval. 2 approvals for: database migrations, auth changes, infrastructure, CI/CD, and changes touching >10 files.
34
+ 5. **Merge strategy**: Squash merge for feature branches (clean history). Merge commit for release branches (preserve individual commits).
35
+ 6. **Post-merge**: Delete the branch. Verify CI passes on main. Check staging deployment if auto-deployed.
36
+
37
+ ## Release Process
38
+
39
+ - Semantic versioning: `MAJOR.MINOR.PATCH`
40
+ - MAJOR: Breaking API changes
41
+ - MINOR: New features, backward compatible
42
+ - PATCH: Bug fixes, backward compatible
43
+ - Tag releases on main: `git tag -a v1.2.3 -m "Release v1.2.3"`
44
+ - Changelog generated from conventional commit messages (using `standard-version` or `changesets`).
@@ -0,0 +1,48 @@
1
+ ## Naming Conventions
2
+
3
+ - Variables/functions: `camelCase` (JS/TS), `snake_case` (Python/Go/Rust)
4
+ - Types/classes/interfaces: `PascalCase`
5
+ - Constants: `UPPER_SNAKE_CASE` for true compile-time constants. Regular `camelCase` for runtime values that don't change.
6
+ - File names: `kebab-case.ts` for modules, `PascalCase.tsx` for React components
7
+ - Database tables: `snake_case` plural (`users`, `order_items`). Columns: `snake_case` singular.
8
+ - API URLs: `kebab-case` (`/api/user-profiles`). Query params: `camelCase` or `snake_case` (be consistent).
9
+
10
+ ## Code Quality Rules
11
+
12
+ - **Single responsibility**: Functions do one thing. If you can't name it without "and", split it.
13
+ - **Early returns**: Validate preconditions at the top and return early. Avoid nested if-else pyramids:
14
+ ```typescript
15
+ // BAD
16
+ function process(user) {
17
+ if (user) {
18
+ if (user.active) {
19
+ // ...30 lines of logic
20
+ }
21
+ }
22
+ }
23
+ // GOOD
24
+ function process(user) {
25
+ if (!user) return;
26
+ if (!user.active) return;
27
+ // ...30 lines of logic
28
+ }
29
+ ```
30
+ - **Explicit over implicit**: Named parameters over boolean flags. `createUser({ admin: true })` not `createUser(true)`.
31
+ - **Error handling**: Handle errors explicitly at the point where you can do something useful about them. Don't catch at every level — let errors propagate to a handler that can provide meaningful feedback.
32
+ - **No magic numbers/strings**: Extract to named constants. `const MAX_RETRY_ATTEMPTS = 3` not bare `3` in a loop.
33
+ - **Dependencies**: Pin exact versions in lockfiles. Audit dependencies quarterly — remove unused, update vulnerable.
34
+ - **Environment config**: All environment-specific values via environment variables. Use a typed config module that validates at startup (fail fast, not on first use).
35
+
36
+ ## Code Review Standards
37
+
38
+ - Review for correctness first, then maintainability, then style. Don't bikeshed formatting — that's the linter's job.
39
+ - Every PR must answer: what changed, why, and how to verify. If the reviewer can't understand the "why", the PR description needs work.
40
+ - Look for what's NOT there: missing error handling, missing tests, missing logging, missing edge cases.
41
+ - Large PRs (>500 lines changed) should be broken into smaller, reviewable chunks. Exception: mechanical refactors (renames, moves) where the diff is large but the change is simple.
42
+
43
+ ## Git Hygiene
44
+
45
+ - Commit messages: `type(scope): description` — e.g., `feat(auth): add OAuth2 login flow`
46
+ - Atomic commits: each commit compiles and passes tests. Don't commit broken intermediate states.
47
+ - Rebase feature branches on main before merging. Resolve conflicts locally, not in the merge commit.
48
+ - Delete merged branches immediately. Stale branches are noise.
@@ -0,0 +1,25 @@
1
+ id: ba
2
+ name: BA Agent
3
+ description: >
4
+ Business Analyst agent. Translates business requirements into technical specs,
5
+ acceptance criteria, user stories, API contracts, and data flow diagrams.
6
+ role: ba
7
+ techStack:
8
+ languages: [Markdown, YAML, JSON]
9
+ frameworks: []
10
+ libraries: [Mermaid, OpenAPI]
11
+ buildTools: []
12
+ tools:
13
+ allowed: [Read, Write, Edit, Grep, Glob]
14
+ globs:
15
+ - "docs/**/*"
16
+ - "specs/**/*"
17
+ - "requirements/**/*"
18
+ - "**/*.md"
19
+ - "**/*.yaml"
20
+ - "**/*.yml"
21
+ - "openapi.*"
22
+ - "swagger.*"
23
+ sharedKnowledge:
24
+ - project-conventions
25
+ - git-workflow
@@ -0,0 +1,87 @@
1
+ # Writing Acceptance Criteria
2
+
3
+ ## Format: Given / When / Then
4
+
5
+ ```
6
+ GIVEN [precondition — the state of the world before the action]
7
+ WHEN [action — what the user does]
8
+ THEN [expected outcome — what should happen]
9
+ AND [additional outcomes if needed]
10
+ ```
11
+
12
+ ## Rules for Good Acceptance Criteria
13
+
14
+ 1. **Testable**: QA must be able to write an automated test from this criterion alone
15
+ - BAD: "The form should be user-friendly"
16
+ - GOOD: "GIVEN an empty form WHEN user submits THEN inline errors appear below each required field"
17
+
18
+ 2. **Specific**: Include exact values, behaviors, and states
19
+ - BAD: "The page loads quickly"
20
+ - GOOD: "GIVEN a list of 1000 items WHEN user loads the page THEN first 20 items render within 2 seconds"
21
+
22
+ 3. **Independent**: Each criterion should be verifiable on its own
23
+
24
+ 4. **Complete**: Cover happy path AND failure paths AND edge cases
25
+
26
+ ## Coverage Checklist
27
+
28
+ For every user story, write criteria covering:
29
+
30
+ - [ ] **Happy path**: Normal successful flow
31
+ - [ ] **Validation errors**: What happens with invalid input?
32
+ - [ ] **Authentication**: What if user is not logged in?
33
+ - [ ] **Authorization**: What if user doesn't have permission?
34
+ - [ ] **Empty state**: What if there's no data to display?
35
+ - [ ] **Error state**: What if the server returns an error?
36
+ - [ ] **Loading state**: What does the user see while waiting?
37
+ - [ ] **Boundary values**: Minimum, maximum, empty string, very long text
38
+ - [ ] **Concurrent action**: What if the same action happens simultaneously?
39
+
40
+ ## Example: User Registration
41
+
42
+ ```
43
+ Story: As a new user, I want to register an account so I can access the platform.
44
+
45
+ AC1: Successful registration
46
+ GIVEN I am on the registration page
47
+ WHEN I enter a valid email, password (8+ chars, 1 uppercase, 1 number), and name
48
+ AND I click "Register"
49
+ THEN my account is created
50
+ AND I receive a verification email within 60 seconds
51
+ AND I am redirected to the "check your email" page
52
+
53
+ AC2: Duplicate email
54
+ GIVEN a user with email "existing@example.com" already exists
55
+ WHEN I enter "existing@example.com" and a valid password
56
+ AND I click "Register"
57
+ THEN I see an error "An account with this email already exists"
58
+ AND a "Sign in" link is shown
59
+
60
+ AC3: Weak password
61
+ GIVEN I am on the registration page
62
+ WHEN I enter a password shorter than 8 characters
63
+ AND I move focus away from the password field (blur)
64
+ THEN I see inline error "Password must be at least 8 characters"
65
+ AND the submit button remains enabled (errors shown inline, not blocking)
66
+
67
+ AC4: Email format validation
68
+ GIVEN I am on the registration page
69
+ WHEN I enter "not-an-email" in the email field
70
+ AND I move focus away (blur)
71
+ THEN I see inline error "Please enter a valid email address"
72
+
73
+ AC5: Empty form submission
74
+ GIVEN I am on the registration page with all fields empty
75
+ WHEN I click "Register"
76
+ THEN inline errors appear below each required field
77
+ AND focus moves to the first field with an error
78
+ AND the page does NOT scroll to top or show a toast
79
+ ```
80
+
81
+ ## Anti-patterns
82
+
83
+ - **Vague criteria**: "System should handle errors gracefully" — which errors? What does "gracefully" mean?
84
+ - **Implementation details**: "System stores user in PostgreSQL users table" — that's a design decision, not a requirement
85
+ - **Untestable**: "System should be fast" — what's "fast"? Specify response time targets.
86
+ - **Missing negative cases**: Only happy path criteria = bugs in production from unhandled edge cases
87
+ - **Ambiguous pronouns**: "It should display the message" — which message? To whom?
@@ -0,0 +1,110 @@
1
+ # API Contract Design
2
+
3
+ ## Purpose
4
+
5
+ An API contract is the agreement between FE and BE about how they communicate. It must be defined BEFORE implementation starts so both can work in parallel against the same spec.
6
+
7
+ ## Contract Template
8
+
9
+ ```yaml
10
+ # Endpoint: Create Order
11
+ method: POST
12
+ path: /api/v1/orders
13
+ auth: required (role: user)
14
+ rate_limit: 30/min per user
15
+
16
+ request:
17
+ headers:
18
+ Content-Type: application/json
19
+ Authorization: Bearer {access_token}
20
+ body:
21
+ productId:
22
+ type: string
23
+ required: true
24
+ example: "prod_abc123"
25
+ quantity:
26
+ type: integer
27
+ required: true
28
+ min: 1
29
+ max: 100
30
+ couponCode:
31
+ type: string
32
+ required: false
33
+ maxLength: 20
34
+ example: "SAVE10"
35
+
36
+ response:
37
+ 201 Created:
38
+ description: Order created successfully
39
+ body:
40
+ data:
41
+ id: string (e.g., "ord_xyz789")
42
+ productId: string
43
+ quantity: integer
44
+ unitPrice: integer (cents)
45
+ discount: integer (cents)
46
+ total: integer (cents)
47
+ status: "pending" | "confirmed" | "shipped"
48
+ createdAt: string (ISO 8601)
49
+
50
+ 400 Bad Request:
51
+ description: Validation error
52
+ body:
53
+ error:
54
+ code: "VALIDATION_ERROR"
55
+ message: string
56
+ details:
57
+ - field: string
58
+ message: string
59
+
60
+ 401 Unauthorized:
61
+ body:
62
+ error:
63
+ code: "UNAUTHORIZED"
64
+ message: "Authentication required"
65
+
66
+ 404 Not Found:
67
+ description: Product not found
68
+ body:
69
+ error:
70
+ code: "PRODUCT_NOT_FOUND"
71
+ message: "Product {productId} does not exist"
72
+
73
+ 409 Conflict:
74
+ description: Insufficient stock
75
+ body:
76
+ error:
77
+ code: "INSUFFICIENT_STOCK"
78
+ message: "Only {available} units available"
79
+ ```
80
+
81
+ ## Design Principles
82
+
83
+ 1. **BE owns the data model, FE drives the API shape** — FE knows what it needs to render, BE knows how to store/compute it. Meet in the middle.
84
+
85
+ 2. **Response includes everything FE needs** — FE should not make N requests to assemble one view. If a list page needs user name + avatar, include them in the list response.
86
+
87
+ 3. **Consistent patterns across endpoints** — same pagination format, same error format, same date format everywhere.
88
+
89
+ 4. **Version from day one** — `/v1/` prefix. Even if you never make v2, it costs nothing and saves you later.
90
+
91
+ 5. **Error codes are machine-readable** — FE switches on `error.code` (not `error.message`) to decide what to show the user.
92
+
93
+ ## Review Checklist
94
+
95
+ Before finalizing a contract, verify:
96
+ - [ ] All FE views can be rendered with the data in the response
97
+ - [ ] All user actions have a corresponding endpoint
98
+ - [ ] Error responses cover all failure modes (validation, auth, not-found, conflict)
99
+ - [ ] Pagination included for list endpoints
100
+ - [ ] Sorting and filtering params defined
101
+ - [ ] Response includes `id` for every entity (for FE to use as key/link)
102
+ - [ ] Date/time fields are ISO 8601 strings
103
+ - [ ] Money fields are integers in smallest unit (cents)
104
+ - [ ] Consistent naming (camelCase for JSON, snake_case only if project convention)
105
+
106
+ ## Contract Evolution
107
+
108
+ - **Non-breaking** (no version bump needed): add optional request field, add response field, add new endpoint
109
+ - **Breaking** (requires v2): remove/rename field, change field type, add required request field, change URL
110
+ - **Migration path**: support v1 and v2 simultaneously for 3 months, then deprecate v1