create-rigel 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.
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/cli.js +122 -0
- package/package.json +47 -0
- package/templates/express/.claude/CLAUDE.md +114 -0
- package/templates/express/.claude/agents/arch-validator.md +85 -0
- package/templates/express/.claude/agents/db-optimizer.md +72 -0
- package/templates/express/.claude/agents/doc-gardener.md +67 -0
- package/templates/express/.claude/agents/garbage-collector.md +94 -0
- package/templates/express/.claude/agents/gate-checker.md +176 -0
- package/templates/express/.claude/agents/reviewer.md +84 -0
- package/templates/express/.claude/agents/security-auditor.md +82 -0
- package/templates/express/.claude/hooks/post-write.sh +93 -0
- package/templates/express/.claude/rules/api.md +149 -0
- package/templates/express/.claude/rules/architecture.md +78 -0
- package/templates/express/.claude/rules/database.md +104 -0
- package/templates/express/.claude/rules/jobs.md +81 -0
- package/templates/express/.claude/rules/security.md +92 -0
- package/templates/express/.claude/rules/testing.md +97 -0
- package/templates/express/.claude/settings.json +35 -0
- package/templates/express/.claude/skills/00-infra-setup/SKILL.md +479 -0
- package/templates/express/.claude/skills/01-write-roadmap/SKILL.md +72 -0
- package/templates/express/.claude/skills/02-write-spec/SKILL.md +119 -0
- package/templates/express/.claude/skills/03-write-plan/SKILL.md +124 -0
- package/templates/express/.claude/skills/04-build-layer/SKILL.md +216 -0
- package/templates/express/.claude/skills/05-validate-layer/SKILL.md +43 -0
- package/templates/express/.claude/skills/06-push-layer/SKILL.md +59 -0
- package/templates/express/.claude/skills/07-layer-check/SKILL.md +62 -0
- package/templates/express/.claude/skills/08-garbage-collect/SKILL.md +86 -0
- package/templates/express/.claude/skills/09-doc-garden/SKILL.md +64 -0
- package/templates/express/.claude/skills/10-db-optimize/SKILL.md +96 -0
- package/templates/express/.claude/skills/11-load-test/SKILL.md +77 -0
- package/templates/express/.dockerignore +43 -0
- package/templates/express/.env.example +42 -0
- package/templates/express/.github/CODEOWNERS +22 -0
- package/templates/express/.github/dependabot.yml +48 -0
- package/templates/express/.github/pull_request_template.md +58 -0
- package/templates/express/.github/workflows/ci.yml +278 -0
- package/templates/express/.github/workflows/load-test.yml +41 -0
- package/templates/express/.gitleaks.toml +18 -0
- package/templates/express/.lintstagedrc.json +3 -0
- package/templates/express/.nvmrc +1 -0
- package/templates/express/.prettierrc +8 -0
- package/templates/express/.sequelizerc +8 -0
- package/templates/express/AGENTS.md +94 -0
- package/templates/express/ARCHITECTURE.md +161 -0
- package/templates/express/Dockerfile +40 -0
- package/templates/express/Makefile +79 -0
- package/templates/express/QUICKSTART.md +131 -0
- package/templates/express/docker-compose.yml +114 -0
- package/templates/express/docs/PLANS.md +111 -0
- package/templates/express/docs/QUALITY_SCORE.md +66 -0
- package/templates/express/docs/design-docs/core-beliefs.md +89 -0
- package/templates/express/docs/design-docs/decisions/ADR-000-infrastructure.md +70 -0
- package/templates/express/docs/design-docs/decisions/ADR-001-observability.md +82 -0
- package/templates/express/docs/design-docs/decisions/index.md +23 -0
- package/templates/express/docs/design-docs/index.md +11 -0
- package/templates/express/docs/design-docs/observability.md +194 -0
- package/templates/express/docs/design-docs/team-workflow.md +64 -0
- package/templates/express/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/express/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/express/docs/exec-plans/tech-debt-tracker.md +31 -0
- package/templates/express/docs/generated/.gitkeep +0 -0
- package/templates/express/docs/product-specs/ROADMAP.md +49 -0
- package/templates/express/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/express/docs/product-specs/index.md +21 -0
- package/templates/express/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/express/eslint.config.mjs +94 -0
- package/templates/express/gitignore +36 -0
- package/templates/express/infra/monitoring/alloy/config.alloy +59 -0
- package/templates/express/jest.config.ts +61 -0
- package/templates/express/package.json +45 -0
- package/templates/express/scripts/openapi.export.ts +77 -0
- package/templates/express/tests/architecture/isolation.test.ts +51 -0
- package/templates/express/tests/architecture/layers.test.ts +83 -0
- package/templates/express/tests/integration/health.test.ts +40 -0
- package/templates/express/tests/integration/isolation.test.template.ts +88 -0
- package/templates/express/tests/load/smoke.js +46 -0
- package/templates/express/tests/load/soak.js +45 -0
- package/templates/express/tests/load/stress.js +44 -0
- package/templates/express/tests/unit/utils/response.util.test.ts +53 -0
- package/templates/express/tsconfig.build.json +8 -0
- package/templates/express/tsconfig.json +20 -0
- package/templates/fastapi/.claude/CLAUDE.md +122 -0
- package/templates/fastapi/.claude/agents/arch-validator.md +64 -0
- package/templates/fastapi/.claude/agents/db-optimizer.md +59 -0
- package/templates/fastapi/.claude/agents/doc-gardener.md +55 -0
- package/templates/fastapi/.claude/agents/garbage-collector.md +74 -0
- package/templates/fastapi/.claude/agents/gate-checker.md +133 -0
- package/templates/fastapi/.claude/agents/reviewer.md +74 -0
- package/templates/fastapi/.claude/agents/security-auditor.md +69 -0
- package/templates/fastapi/.claude/hooks/post-write.sh +65 -0
- package/templates/fastapi/.claude/rules/api.md +119 -0
- package/templates/fastapi/.claude/rules/architecture.md +84 -0
- package/templates/fastapi/.claude/rules/database.md +153 -0
- package/templates/fastapi/.claude/rules/jobs.md +85 -0
- package/templates/fastapi/.claude/rules/security.md +102 -0
- package/templates/fastapi/.claude/rules/testing.md +207 -0
- package/templates/fastapi/.claude/settings.json +50 -0
- package/templates/fastapi/.claude/skills/00-infra-setup/SKILL.md +311 -0
- package/templates/fastapi/.claude/skills/01-write-roadmap/SKILL.md +61 -0
- package/templates/fastapi/.claude/skills/02-write-spec/SKILL.md +82 -0
- package/templates/fastapi/.claude/skills/03-write-plan/SKILL.md +83 -0
- package/templates/fastapi/.claude/skills/04-build-layer/SKILL.md +170 -0
- package/templates/fastapi/.claude/skills/05-validate-layer/SKILL.md +20 -0
- package/templates/fastapi/.claude/skills/06-push-layer/SKILL.md +31 -0
- package/templates/fastapi/.claude/skills/07-layer-check/SKILL.md +51 -0
- package/templates/fastapi/.claude/skills/08-garbage-collect/SKILL.md +47 -0
- package/templates/fastapi/.claude/skills/09-doc-garden/SKILL.md +9 -0
- package/templates/fastapi/.claude/skills/10-db-optimize/SKILL.md +53 -0
- package/templates/fastapi/.claude/skills/11-load-test/SKILL.md +81 -0
- package/templates/fastapi/.dockerignore +30 -0
- package/templates/fastapi/.github/dependabot.yml +24 -0
- package/templates/fastapi/AGENTS.md +87 -0
- package/templates/fastapi/ARCHITECTURE.md +141 -0
- package/templates/fastapi/Makefile +42 -0
- package/templates/fastapi/README.md +179 -0
- package/templates/fastapi/docs/PLANS.md +26 -0
- package/templates/fastapi/docs/QUALITY_SCORE.md +26 -0
- package/templates/fastapi/docs/design-docs/core-beliefs.md +46 -0
- package/templates/fastapi/docs/design-docs/decisions/ADR-000-infrastructure.md +79 -0
- package/templates/fastapi/docs/design-docs/decisions/index.md +7 -0
- package/templates/fastapi/docs/design-docs/index.md +9 -0
- package/templates/fastapi/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/fastapi/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/fastapi/docs/exec-plans/tech-debt-tracker.md +19 -0
- package/templates/fastapi/docs/generated/.gitkeep +0 -0
- package/templates/fastapi/docs/product-specs/ROADMAP.md +49 -0
- package/templates/fastapi/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/fastapi/docs/product-specs/index.md +18 -0
- package/templates/fastapi/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/fastapi/gitignore +46 -0
- package/templates/fastapi/scripts/gate.sh +68 -0
- package/templates/nestjs/.claude/CLAUDE.md +121 -0
- package/templates/nestjs/.claude/agents/db-optimizer.md +51 -0
- package/templates/nestjs/.claude/agents/doc-gardener.md +45 -0
- package/templates/nestjs/.claude/agents/garbage-collector.md +50 -0
- package/templates/nestjs/.claude/agents/gate-checker.md +127 -0
- package/templates/nestjs/.claude/agents/reviewer.md +68 -0
- package/templates/nestjs/.claude/agents/security-auditor.md +72 -0
- package/templates/nestjs/.claude/hooks/post-write.sh +91 -0
- package/templates/nestjs/.claude/rules/api.md +87 -0
- package/templates/nestjs/.claude/rules/architecture.md +104 -0
- package/templates/nestjs/.claude/rules/database.md +111 -0
- package/templates/nestjs/.claude/rules/security.md +110 -0
- package/templates/nestjs/.claude/rules/testing.md +145 -0
- package/templates/nestjs/.claude/settings.json +33 -0
- package/templates/nestjs/.claude/skills/00-infra-setup/SKILL.md +222 -0
- package/templates/nestjs/.claude/skills/01-write-spec/SKILL.md +25 -0
- package/templates/nestjs/.claude/skills/02-write-plan/SKILL.md +18 -0
- package/templates/nestjs/.claude/skills/03-build-layer/SKILL.md +242 -0
- package/templates/nestjs/.claude/skills/04-validate-layer/SKILL.md +4 -0
- package/templates/nestjs/.claude/skills/05-push-layer/SKILL.md +6 -0
- package/templates/nestjs/.claude/skills/06-layer-check/SKILL.md +12 -0
- package/templates/nestjs/.claude/skills/07-garbage-collect/SKILL.md +2 -0
- package/templates/nestjs/.claude/skills/08-doc-garden/SKILL.md +4 -0
- package/templates/nestjs/.claude/skills/09-api-sync/SKILL.md +36 -0
- package/templates/nestjs/.claude/skills/10-load-test/SKILL.md +29 -0
- package/templates/nestjs/.env.example +11 -0
- package/templates/nestjs/AGENTS.md +88 -0
- package/templates/nestjs/ARCHITECTURE.md +192 -0
- package/templates/nestjs/docs/PLANS.md +22 -0
- package/templates/nestjs/docs/QUALITY_SCORE.md +27 -0
- package/templates/nestjs/docs/design-docs/core-beliefs.md +18 -0
- package/templates/nestjs/docs/design-docs/decisions/ADR-000-infrastructure.md +58 -0
- package/templates/nestjs/docs/design-docs/decisions/index.md +7 -0
- package/templates/nestjs/docs/design-docs/index.md +7 -0
- package/templates/nestjs/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/nestjs/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/nestjs/docs/exec-plans/tech-debt-tracker.md +16 -0
- package/templates/nestjs/docs/generated/.gitkeep +0 -0
- package/templates/nestjs/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/nestjs/docs/product-specs/index.md +7 -0
- package/templates/nestjs/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/nestjs/gitignore +8 -0
- package/templates/nextjs/.claude/CLAUDE.md +139 -0
- package/templates/nextjs/.claude/agents/arch-validator.md +66 -0
- package/templates/nextjs/.claude/agents/contract-checker.md +78 -0
- package/templates/nextjs/.claude/agents/doc-gardener.md +52 -0
- package/templates/nextjs/.claude/agents/garbage-collector.md +61 -0
- package/templates/nextjs/.claude/agents/gate-checker.md +129 -0
- package/templates/nextjs/.claude/agents/perf-auditor.md +109 -0
- package/templates/nextjs/.claude/agents/reviewer.md +79 -0
- package/templates/nextjs/.claude/agents/security-auditor.md +50 -0
- package/templates/nextjs/.claude/hooks/post-write.sh +121 -0
- package/templates/nextjs/.claude/rules/api-contract.md +166 -0
- package/templates/nextjs/.claude/rules/architecture.md +99 -0
- package/templates/nextjs/.claude/rules/components.md +122 -0
- package/templates/nextjs/.claude/rules/security.md +122 -0
- package/templates/nextjs/.claude/rules/testing.md +187 -0
- package/templates/nextjs/.claude/scripts/infra-setup.sh +550 -0
- package/templates/nextjs/.claude/settings.json +33 -0
- package/templates/nextjs/.claude/skills/00-infra-setup/SKILL.md +471 -0
- package/templates/nextjs/.claude/skills/01-write-roadmap/SKILL.md +77 -0
- package/templates/nextjs/.claude/skills/02-write-spec/SKILL.md +78 -0
- package/templates/nextjs/.claude/skills/03-write-plan/SKILL.md +91 -0
- package/templates/nextjs/.claude/skills/04-build-layer/SKILL.md +141 -0
- package/templates/nextjs/.claude/skills/05-validate-layer/SKILL.md +13 -0
- package/templates/nextjs/.claude/skills/06-push-layer/SKILL.md +20 -0
- package/templates/nextjs/.claude/skills/07-layer-check/SKILL.md +28 -0
- package/templates/nextjs/.claude/skills/08-garbage-collect/SKILL.md +14 -0
- package/templates/nextjs/.claude/skills/09-doc-garden/SKILL.md +12 -0
- package/templates/nextjs/.claude/skills/10-api-sync/SKILL.md +50 -0
- package/templates/nextjs/.claude/skills/11-perf-budget/SKILL.md +51 -0
- package/templates/nextjs/.dockerignore +25 -0
- package/templates/nextjs/.gitattributes +10 -0
- package/templates/nextjs/.github/CODEOWNERS +24 -0
- package/templates/nextjs/.github/dependabot.yml +31 -0
- package/templates/nextjs/.github/pull_request_template.md +59 -0
- package/templates/nextjs/.github/workflows/ci.yml +143 -0
- package/templates/nextjs/.github/workflows/lighthouse.yml +54 -0
- package/templates/nextjs/.github/workflows/load-test.yml +54 -0
- package/templates/nextjs/.husky/pre-commit +1 -0
- package/templates/nextjs/.lintstagedrc.json +4 -0
- package/templates/nextjs/.mcp.json +8 -0
- package/templates/nextjs/.prettierignore +13 -0
- package/templates/nextjs/.prettierrc +9 -0
- package/templates/nextjs/AGENTS.md +88 -0
- package/templates/nextjs/ARCHITECTURE.md +165 -0
- package/templates/nextjs/Dockerfile +38 -0
- package/templates/nextjs/Makefile +50 -0
- package/templates/nextjs/QUICKSTART.md +128 -0
- package/templates/nextjs/docs/PLANS.md +23 -0
- package/templates/nextjs/docs/QUALITY_SCORE.md +27 -0
- package/templates/nextjs/docs/design-docs/core-beliefs.md +43 -0
- package/templates/nextjs/docs/design-docs/decisions/ADR-000-infrastructure.md +72 -0
- package/templates/nextjs/docs/design-docs/decisions/index.md +7 -0
- package/templates/nextjs/docs/design-docs/index.md +7 -0
- package/templates/nextjs/docs/design-docs/team-workflow.md +66 -0
- package/templates/nextjs/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/nextjs/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/nextjs/docs/exec-plans/tech-debt-tracker.md +19 -0
- package/templates/nextjs/docs/generated/.gitkeep +0 -0
- package/templates/nextjs/docs/product-specs/ROADMAP.md +59 -0
- package/templates/nextjs/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/nextjs/docs/product-specs/index.md +18 -0
- package/templates/nextjs/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/nextjs/eslint.config.mjs +150 -0
- package/templates/nextjs/gitignore +35 -0
- package/templates/nextjs/lighthouserc.js +37 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# /write-spec — Write a Product Spec
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-19 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/write-spec`
|
|
7
|
+
|
|
8
|
+
## Step 1 — Consult the Roadmap (if present)
|
|
9
|
+
```bash
|
|
10
|
+
ls docs/product-specs/ROADMAP.md 2>/dev/null
|
|
11
|
+
```
|
|
12
|
+
If it exists, read it. Pick the first row with Status `NOT_STARTED` — the **walking skeleton**
|
|
13
|
+
if nothing is created yet, otherwise the next dependency-unblocked row. Use that row's Name,
|
|
14
|
+
Epic, and Depends-On to pre-fill the spec's title and the `**Epic:**` / `**Depends on:**` fields.
|
|
15
|
+
If no roadmap exists, proceed ad hoc (a single standalone spec).
|
|
16
|
+
|
|
17
|
+
## Step 2 — Get Next Spec Number
|
|
18
|
+
```bash
|
|
19
|
+
ls docs/product-specs/{draft,ready}/ 2>/dev/null | grep "SPEC-" | sort | tail -1
|
|
20
|
+
```
|
|
21
|
+
Increment by 1. Start at SPEC-001 if none. (`ROADMAP.md` is CAPS, so the `grep SPEC-` is unaffected.)
|
|
22
|
+
|
|
23
|
+
## Step 3 — Write the Spec
|
|
24
|
+
Save to: `docs/product-specs/draft/SPEC-XXX-{slug}.md`
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
# SPEC-XXX — {Feature Name}
|
|
28
|
+
|
|
29
|
+
**Status:** DRAFT
|
|
30
|
+
**Created:** YYYY-MM-DD
|
|
31
|
+
**Plan:** —
|
|
32
|
+
**Epic:** — <!-- from ROADMAP.md row, if roadmap-driven -->
|
|
33
|
+
**Depends on:** — <!-- from ROADMAP.md row, if roadmap-driven -->
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Problem Statement
|
|
38
|
+
{what problem, who has it, why it matters}
|
|
39
|
+
|
|
40
|
+
## What We're Building
|
|
41
|
+
{the solution at high level}
|
|
42
|
+
|
|
43
|
+
## Core Entities
|
|
44
|
+
| Entity | Purpose |
|
|
45
|
+
|---|---|
|
|
46
|
+
|
|
47
|
+
## API Endpoints
|
|
48
|
+
{METHOD /path — description}
|
|
49
|
+
|
|
50
|
+
## Business Rules
|
|
51
|
+
{numbered list}
|
|
52
|
+
|
|
53
|
+
## State Machine (if applicable)
|
|
54
|
+
{ASCII diagram + transition rules}
|
|
55
|
+
|
|
56
|
+
## Non-Functional Requirements
|
|
57
|
+
{performance, rate limits, auth, coverage targets}
|
|
58
|
+
|
|
59
|
+
## Out of Scope (v1)
|
|
60
|
+
{what is NOT being built}
|
|
61
|
+
|
|
62
|
+
## Acceptance Criteria
|
|
63
|
+
- [ ] {testable, specific}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Step 4 — Update Index + Roadmap
|
|
67
|
+
Add row to `docs/product-specs/index.md`: `| SPEC-XXX | {Name} | DRAFT | — | YYYY-MM-DD |`
|
|
68
|
+
If this spec came from a `ROADMAP.md` row, flip that row: `Spec ID: — → SPEC-XXX` and
|
|
69
|
+
`Status: NOT_STARTED → DRAFT` (mirrors how `/write-plan` updates the spec + index together).
|
|
70
|
+
|
|
71
|
+
## Step 5 — Tell the Human
|
|
72
|
+
```
|
|
73
|
+
Spec written: docs/product-specs/draft/SPEC-XXX-{slug}.md
|
|
74
|
+
Status: DRAFT
|
|
75
|
+
|
|
76
|
+
Review it. When satisfied:
|
|
77
|
+
1. Move to: docs/product-specs/ready/SPEC-XXX-{slug}.md
|
|
78
|
+
2. Change Status: DRAFT → READY
|
|
79
|
+
3. Run /write-plan
|
|
80
|
+
|
|
81
|
+
Claude will not create a plan until the spec is in ready/.
|
|
82
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# /write-plan — Write an Execution Plan
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-19 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/write-plan`
|
|
7
|
+
|
|
8
|
+
## Step 1 — Find Ready Spec
|
|
9
|
+
```bash
|
|
10
|
+
ls docs/product-specs/ready/
|
|
11
|
+
```
|
|
12
|
+
If none → tell human to mark a spec READY first. Stop.
|
|
13
|
+
|
|
14
|
+
> A large spec may span MULTIPLE plans — slice it into shippable milestones, each its own
|
|
15
|
+
> `PLAN-XXX` that ends green (e.g. data model + CRUD; then an external integration; then
|
|
16
|
+
> reporting). Plans are numbered independently, so just create the next plan for the same spec.
|
|
17
|
+
|
|
18
|
+
## Step 2 — Get Next Plan Number
|
|
19
|
+
```bash
|
|
20
|
+
ls docs/exec-plans/{active,completed}/ 2>/dev/null | grep "PLAN-" | sort | tail -1
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Step 3 — Read the Spec
|
|
24
|
+
Identify all entities → models + migrations + repos + services.
|
|
25
|
+
Identify all endpoints → routers. Background jobs → workers.
|
|
26
|
+
|
|
27
|
+
## Step 4 — Write the Plan
|
|
28
|
+
Save to: `docs/exec-plans/active/PLAN-XXX-{slug}.md`
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
# PLAN-XXX — {Feature Name}
|
|
32
|
+
|
|
33
|
+
**Status:** IN_PROGRESS
|
|
34
|
+
**Spec:** docs/product-specs/ready/SPEC-XXX-{slug}.md
|
|
35
|
+
**Created:** YYYY-MM-DD
|
|
36
|
+
**Completed:** —
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Goal
|
|
41
|
+
{one sentence}
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Layer Build Order
|
|
46
|
+
|
|
47
|
+
| # | Layer | Files | Gate Focuses On |
|
|
48
|
+
|---|---|---|---|
|
|
49
|
+
| 1 | Types | `src/types/{entity}_schema.py`, `exceptions.py` | Zero imports, zero logic |
|
|
50
|
+
| 2 | Config | `src/config/settings.py` update, `constants.py` | No os.environ elsewhere |
|
|
51
|
+
| 3 | Models | `src/models/{entity}.py` × N | deleted_at, uuid7, indexes |
|
|
52
|
+
| 4 | Migrations | `alembic/versions/...` × N | Runs clean, has downgrade() |
|
|
53
|
+
| 5 | Repo | `src/repo/{entity}_repo.py` × N | model_validate, cursor, ownership, no N+1 |
|
|
54
|
+
| 6 | Service | `src/services/{domain}_service.py` × N | No fastapi, ≥90% coverage |
|
|
55
|
+
| 7 | Runtime | `src/runtime/routers/v1/{resource}.py` × N | Depends(require_auth), typed return |
|
|
56
|
+
| 8 | Workers | `src/runtime/workers/{name}_worker.py` × N | model_validate payload, retry, logs |
|
|
57
|
+
| 9 | Tests | `tests/unit/`, `tests/integration/` | Coverage gates |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Acceptance Criteria
|
|
62
|
+
- [ ] {from spec}
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Progress Log
|
|
67
|
+
### {date} — Plan created
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Decision Log
|
|
72
|
+
*(filled during build)*
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Step 5 — Update Spec + Index
|
|
76
|
+
APPEND `PLAN-XXX` to the spec's `**Plan:**` field (do not overwrite) — a spec split across
|
|
77
|
+
several plans lists them all, e.g. `**Plan:** PLAN-003, PLAN-007`. Update index status to `PLANNED`.
|
|
78
|
+
|
|
79
|
+
## Step 6 — Tell the Human
|
|
80
|
+
```
|
|
81
|
+
Plan written: docs/exec-plans/active/PLAN-XXX-{slug}.md
|
|
82
|
+
{N} layers planned. Run /build-layer to start Layer 1.
|
|
83
|
+
```
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# /build-layer — Build Next Layer from Active Plan
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** FastAPI 0.115, SQLAlchemy 2.0, pydantic 2, pytest 8 — see .claude/rules/*.md for layer specifics
|
|
5
|
+
|
|
6
|
+
Triggered by: `/build-layer` (no argument — reads active plan automatically)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Step 1 — Find Active Plan and Next Layer
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
PLAN=$(ls docs/exec-plans/active/*.md 2>/dev/null | head -1)
|
|
14
|
+
[[ -z "$PLAN" ]] && echo "No active plan. Run /write-plan first." && exit 1
|
|
15
|
+
cat "$PLAN"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Parse the Build Order table. Find first row with `[ ]`. If all `[x]` → run `/garbage-collect`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Step 2 — Load Context
|
|
23
|
+
|
|
24
|
+
Read: active plan, linked spec, `ARCHITECTURE.md`, and the path-scoped rule:
|
|
25
|
+
|
|
26
|
+
- Types → `.claude/rules/architecture.md`
|
|
27
|
+
- Config → `.claude/rules/architecture.md`
|
|
28
|
+
- Models → `.claude/rules/database.md`
|
|
29
|
+
- Repo → `.claude/rules/database.md` + `.claude/rules/security.md`
|
|
30
|
+
- Service → `.claude/rules/architecture.md` + `.claude/rules/security.md`
|
|
31
|
+
- Runtime → `.claude/rules/api.md` + `.claude/rules/security.md`
|
|
32
|
+
- Workers → `.claude/rules/jobs.md`
|
|
33
|
+
- Tests → `.claude/rules/testing.md`
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 3 — Build the Layer
|
|
38
|
+
|
|
39
|
+
### Types (`src/types/`)
|
|
40
|
+
|
|
41
|
+
- One file per domain entity: `{entity}_schema.py`
|
|
42
|
+
- Pydantic `BaseModel` — input schemas, response schemas, enums
|
|
43
|
+
- `exceptions.py` — `DomainError` subclasses: `ApplicationNotFoundError`, `StageTransitionError` etc.
|
|
44
|
+
- `common.py` — `PageResult[T]`, cursor types
|
|
45
|
+
- Zero imports from other src layers. Zero logic.
|
|
46
|
+
|
|
47
|
+
### Config (`src/config/`)
|
|
48
|
+
|
|
49
|
+
- Update `settings.py` if new env vars needed (add to `Settings` + `.env.example`)
|
|
50
|
+
- Add domain constants to `constants.py`
|
|
51
|
+
|
|
52
|
+
### Models (`src/models/`)
|
|
53
|
+
|
|
54
|
+
- One file per entity: `{entity}.py`
|
|
55
|
+
- SQLAlchemy 2 declarative `MappedColumn` style
|
|
56
|
+
- `deleted_at: Mapped[datetime | None] = mapped_column(default=None)`
|
|
57
|
+
- `id: Mapped[UUID] = mapped_column(default=uuid_utils.uuid7)`
|
|
58
|
+
- `__table_args__` with indexes (FK cols + ORDER BY cols + partial on deleted_at)
|
|
59
|
+
- Export all from `src/models/__init__.py`
|
|
60
|
+
|
|
61
|
+
### Migrations (`alembic/versions/`)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv run alembic revision --autogenerate -m "create_{table}"
|
|
65
|
+
# Review generated file — fix any issues
|
|
66
|
+
uv run alembic upgrade head
|
|
67
|
+
# Verify it ran clean
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Repo (`src/repo/`)
|
|
71
|
+
|
|
72
|
+
- One file per entity: `{entity}_repo.py`
|
|
73
|
+
- Every result: `Schema.model_validate(row.__dict__)`
|
|
74
|
+
- List methods: cursor pagination (Op.lt on created_at + id)
|
|
75
|
+
- Ownership: `WHERE id = :id AND user_id = :user_id`
|
|
76
|
+
- No N+1: use `selectinload()` / `joinedload()` for related data
|
|
77
|
+
- Soft delete: `WHERE deleted_at IS NULL` on every query
|
|
78
|
+
|
|
79
|
+
### Service (`src/services/`)
|
|
80
|
+
|
|
81
|
+
- One file per domain: `{domain}_service.py`
|
|
82
|
+
- Receives: `AsyncSession` + typed Pydantic inputs
|
|
83
|
+
- Returns: typed Pydantic outputs
|
|
84
|
+
- Raises: `DomainError` subclasses — NEVER `HTTPException`
|
|
85
|
+
- NO `from fastapi import ...`
|
|
86
|
+
- State machines, business rules, orchestration live here
|
|
87
|
+
- Multi-table writes: `async with session.begin():`
|
|
88
|
+
|
|
89
|
+
### Runtime (`src/runtime/routers/v1/`)
|
|
90
|
+
|
|
91
|
+
- One file per resource: `{resource}.py`
|
|
92
|
+
- All routes: `Depends(require_auth)` as first dependency
|
|
93
|
+
- Handler body: service call only — no business logic
|
|
94
|
+
- Exception mapping: handled by global handlers in `exception_handlers.py`
|
|
95
|
+
- All under `/api/v1/` prefix
|
|
96
|
+
|
|
97
|
+
### Workers (`src/runtime/workers/`)
|
|
98
|
+
|
|
99
|
+
- One file per queue: `{name}_worker.py`
|
|
100
|
+
- First line: `data = PayloadSchema.model_validate(payload)`
|
|
101
|
+
- Log: start, complete, failed with structlog
|
|
102
|
+
- Re-raise on error (Celery handles retry per task config)
|
|
103
|
+
|
|
104
|
+
### Tests (`tests/`)
|
|
105
|
+
|
|
106
|
+
- `tests/unit/services/{service}_test.py` — service layer, mock repos
|
|
107
|
+
- `tests/unit/utils/{util}_test.py` — utils
|
|
108
|
+
- `tests/integration/test_{feature}.py` — full HTTP via AsyncClient
|
|
109
|
+
- Meet coverage thresholds from `.claude/rules/testing.md`
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Step 4 — Run Gate
|
|
114
|
+
|
|
115
|
+
Call `gate-checker` agent.
|
|
116
|
+
|
|
117
|
+
**If FAIL:**
|
|
118
|
+
|
|
119
|
+
- Read each ITEM → fix automatically → log fix
|
|
120
|
+
- Re-run gate (max 3 attempts)
|
|
121
|
+
- If still failing after 3: present to human with exact blocker
|
|
122
|
+
|
|
123
|
+
**If PASS:**
|
|
124
|
+
|
|
125
|
+
- Tick checkbox in plan: `- [ ] Layer N` → `- [x] Layer N`
|
|
126
|
+
- Write ADR if non-obvious decision was made
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Step 5 — ADR (if needed)
|
|
131
|
+
|
|
132
|
+
Save to `docs/design-docs/decisions/ADR-XXX-{slug}.md`.
|
|
133
|
+
Update `docs/design-docs/decisions/index.md`.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Step 6 — Commit and Push
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
git add -A
|
|
141
|
+
git commit -m "{feat|chore|test}({layer}): {description}
|
|
142
|
+
|
|
143
|
+
{bullet points}
|
|
144
|
+
|
|
145
|
+
PLAN-XXX Layer N/Total"
|
|
146
|
+
git push origin main
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Step 7 — Report to Human
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
═══════════════════════════════════════════
|
|
155
|
+
✅ Layer N ({layer-name}) — COMPLETE
|
|
156
|
+
═══════════════════════════════════════════
|
|
157
|
+
Files created: [list]
|
|
158
|
+
Gate attempts: N
|
|
159
|
+
Auto-fixed: [list of fixes]
|
|
160
|
+
ADR written: ADR-XXX / None needed
|
|
161
|
+
Committed: [hash]
|
|
162
|
+
|
|
163
|
+
Progress: [x] Layer 1 [x] Layer 2 [ ] Layer 3 ...
|
|
164
|
+
|
|
165
|
+
Ready for Layer N+1: {next-layer-name}
|
|
166
|
+
Confirm to continue? [human must respond]
|
|
167
|
+
═══════════════════════════════════════════
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Wait for human confirmation before next layer.**
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# /validate-layer — Run Gate Without Building
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/validate-layer`
|
|
7
|
+
|
|
8
|
+
Calls `gate-checker` agent on current state of `src/`. Read-only — no auto-fix.
|
|
9
|
+
|
|
10
|
+
## Steps
|
|
11
|
+
1. Find most recently checked layer from active plan
|
|
12
|
+
2. Call `gate-checker` agent with that layer name
|
|
13
|
+
3. Present full PASS/FAIL report
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
VALIDATION REPORT — Layer: {name}
|
|
17
|
+
{full gate output}
|
|
18
|
+
|
|
19
|
+
Read-only validation. To auto-fix: run /build-layer
|
|
20
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# /push-layer — Commit and Push Current Layer
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/push-layer`
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. Quick gate check before push:
|
|
11
|
+
```bash
|
|
12
|
+
uv run ruff check src/ && uv run mypy src/
|
|
13
|
+
```
|
|
14
|
+
If fails → abort, tell human to fix or run `/build-layer`.
|
|
15
|
+
|
|
16
|
+
2. Stage + commit:
|
|
17
|
+
```bash
|
|
18
|
+
git add -A
|
|
19
|
+
git status
|
|
20
|
+
git commit -m "{conventional commit message from active plan}"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
3. Push:
|
|
24
|
+
```bash
|
|
25
|
+
git push origin $(git branch --show-current)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
4. Report: `Pushed: {hash} — {message}`
|
|
29
|
+
|
|
30
|
+
## Conventional Commit Types
|
|
31
|
+
`feat` · `chore` · `test` · `refactor` · `fix` · `docs`
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# /layer-check — Ad-hoc Architecture Violation Scan
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/layer-check`
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
echo "=== ruff ==="
|
|
10
|
+
uv run ruff check src/ 2>&1
|
|
11
|
+
|
|
12
|
+
echo "=== mypy ==="
|
|
13
|
+
uv run mypy src/ 2>&1
|
|
14
|
+
|
|
15
|
+
echo "=== print() in src/ ==="
|
|
16
|
+
grep -rn "^\s*print(" src/ --include="*.py" | grep -v "src/providers/logger" | grep -v "src/config"
|
|
17
|
+
|
|
18
|
+
echo "=== os.environ outside settings ==="
|
|
19
|
+
grep -rn "os\.environ" src/ --include="*.py" | grep -v "src/config/settings.py"
|
|
20
|
+
|
|
21
|
+
echo "=== HTTPException in services ==="
|
|
22
|
+
grep -rn "HTTPException" src/services/ --include="*.py" 2>/dev/null
|
|
23
|
+
|
|
24
|
+
echo "=== raw dict returns in repo ==="
|
|
25
|
+
grep -rn "return row\.__dict__\|return dict(row" src/repo/ --include="*.py" 2>/dev/null
|
|
26
|
+
|
|
27
|
+
echo "=== offset pagination ==="
|
|
28
|
+
grep -rn "\.offset(\|OFFSET" src/repo/ --include="*.py" 2>/dev/null
|
|
29
|
+
|
|
30
|
+
echo "=== file sizes ==="
|
|
31
|
+
find src/ -name "*.py" | xargs wc -l | sort -rn | awk '$1 > 400 { print "VIOLATION:", $2, $1, "lines" }'
|
|
32
|
+
|
|
33
|
+
echo "=== architecture tests ==="
|
|
34
|
+
uv run pytest tests/architecture/ -v --no-header 2>&1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Output:
|
|
38
|
+
```
|
|
39
|
+
LAYER CHECK — {timestamp}
|
|
40
|
+
ruff: CLEAN / {N} errors
|
|
41
|
+
mypy: CLEAN / {N} errors
|
|
42
|
+
print(): NONE / {list}
|
|
43
|
+
os.environ: NONE / {list}
|
|
44
|
+
HTTPException: NONE / {list}
|
|
45
|
+
Raw returns: NONE / {list}
|
|
46
|
+
Offset: NONE / {list}
|
|
47
|
+
File sizes: NONE / {list}
|
|
48
|
+
Arch tests: PASS / FAIL
|
|
49
|
+
|
|
50
|
+
OVERALL: ✅ CLEAN / ❌ {N} violations
|
|
51
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# /garbage-collect — End-of-Feature Cleanup
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/garbage-collect`
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
### 1. File Size
|
|
11
|
+
```bash
|
|
12
|
+
find src/ -name "*.py" | xargs wc -l | awk '$1 > 400 { print $2, $1 }' | sort -rn
|
|
13
|
+
```
|
|
14
|
+
Split any file over 400 lines.
|
|
15
|
+
|
|
16
|
+
### 2. ruff + mypy
|
|
17
|
+
```bash
|
|
18
|
+
uv run ruff check src/ --fix
|
|
19
|
+
uv run mypy src/
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 3. Stale Docs
|
|
23
|
+
Check AGENTS.md, ARCHITECTURE.md, decisions/index.md, .env.example.
|
|
24
|
+
|
|
25
|
+
### 4. QUALITY_SCORE.md
|
|
26
|
+
```bash
|
|
27
|
+
uv run pytest --cov=src --cov-report=term-missing 2>&1 | tail -20
|
|
28
|
+
```
|
|
29
|
+
Update domain grades.
|
|
30
|
+
|
|
31
|
+
### 5. Log Debt → `docs/exec-plans/tech-debt-tracker.md`
|
|
32
|
+
|
|
33
|
+
### 6. Close Plan
|
|
34
|
+
- All `[x]` confirmed
|
|
35
|
+
- `Status: COMPLETE`, `Completed: YYYY-MM-DD`
|
|
36
|
+
- Move `active/PLAN-XXX.md` → `completed/`
|
|
37
|
+
|
|
38
|
+
### 7. Mark Spec Shipped
|
|
39
|
+
- `Status: SHIPPED` in spec file
|
|
40
|
+
- Update `docs/product-specs/index.md`
|
|
41
|
+
|
|
42
|
+
### 8. Final Commit
|
|
43
|
+
```bash
|
|
44
|
+
git add -A
|
|
45
|
+
git commit -m "chore: garbage collect — close PLAN-XXX"
|
|
46
|
+
git push origin main
|
|
47
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# /doc-garden — Scan and Fix Stale Docs
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** harness toolchain (uv, ruff, mypy, pytest) — process skill, no external library pins
|
|
5
|
+
|
|
6
|
+
Triggered by: `/doc-garden`
|
|
7
|
+
|
|
8
|
+
Calls `doc-gardener` agent. Checks AGENTS.md, ARCHITECTURE.md, specs index,
|
|
9
|
+
.env.example vs settings.py, decisions index. Updates what's stale. Commits if changed.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# /db-optimize — Query Optimization
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** SQLAlchemy 2.0, asyncpg 0.30, PostgreSQL EXPLAIN ANALYZE
|
|
5
|
+
|
|
6
|
+
Triggered by: `/db-optimize [method-name]`
|
|
7
|
+
|
|
8
|
+
## Step 1 — Find Slow Query
|
|
9
|
+
```bash
|
|
10
|
+
# From structlog output or pg_stat_statements
|
|
11
|
+
psql $DATABASE_URL -c "
|
|
12
|
+
SELECT query, mean_exec_time::int, calls
|
|
13
|
+
FROM pg_stat_statements
|
|
14
|
+
WHERE mean_exec_time > 200
|
|
15
|
+
ORDER BY mean_exec_time DESC LIMIT 10;"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Step 2 — EXPLAIN ANALYZE
|
|
19
|
+
```bash
|
|
20
|
+
psql $DATABASE_URL << 'SQL'
|
|
21
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
|
|
22
|
+
SELECT a.* FROM applications a
|
|
23
|
+
WHERE a.user_id = 'uuid' AND a.deleted_at IS NULL
|
|
24
|
+
ORDER BY a.created_at DESC LIMIT 21;
|
|
25
|
+
SQL
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Step 3 — Add Index via Alembic
|
|
29
|
+
Add to model `__table_args__`:
|
|
30
|
+
```python
|
|
31
|
+
Index(
|
|
32
|
+
"idx_applications_user_created",
|
|
33
|
+
"user_id", "created_at",
|
|
34
|
+
postgresql_where=text("deleted_at IS NULL"),
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Generate + run:
|
|
39
|
+
```bash
|
|
40
|
+
uv run alembic revision --autogenerate -m "add_idx_applications_user_created"
|
|
41
|
+
uv run alembic upgrade head
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Step 4 — Verify
|
|
45
|
+
Re-run EXPLAIN ANALYZE — confirm `Index Scan` used, time < 200ms.
|
|
46
|
+
|
|
47
|
+
## Step 5 — Commit
|
|
48
|
+
```bash
|
|
49
|
+
git add alembic/ src/models/
|
|
50
|
+
git commit -m "perf(db): add idx_applications_user_created
|
|
51
|
+
|
|
52
|
+
EXPLAIN before: {N}ms → after: {M}ms"
|
|
53
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# /load-test — k6 Performance Testing
|
|
2
|
+
|
|
3
|
+
**Verified:** 2026-06-18 · **Staleness threshold:** 60 days
|
|
4
|
+
**Libraries:** k6 0.54
|
|
5
|
+
**Source:** [k6 documentation](https://k6.io/docs/)
|
|
6
|
+
|
|
7
|
+
Triggered by: `/load-test [smoke|stress|soak]`
|
|
8
|
+
|
|
9
|
+
## Smoke (CI default)
|
|
10
|
+
```bash
|
|
11
|
+
k6 run --env BASE_URL=${BASE_URL:-http://localhost:8000} --env AUTH_TOKEN=${AUTH_TOKEN:-} tests/load/smoke.js
|
|
12
|
+
```
|
|
13
|
+
Thresholds: P95 < 500ms, error rate < 1%
|
|
14
|
+
|
|
15
|
+
## Stress (pre-release)
|
|
16
|
+
```bash
|
|
17
|
+
k6 run --env BASE_URL=$STAGING_URL tests/load/stress.js
|
|
18
|
+
```
|
|
19
|
+
Thresholds: P95 < 1000ms, P99 < 2000ms, errors < 5%
|
|
20
|
+
|
|
21
|
+
## stress.js scaffold
|
|
22
|
+
```javascript
|
|
23
|
+
import http from 'k6/http'
|
|
24
|
+
import { check, sleep } from 'k6'
|
|
25
|
+
|
|
26
|
+
export const options = {
|
|
27
|
+
stages: [
|
|
28
|
+
{ duration: '2m', target: 50 }, // ramp up
|
|
29
|
+
{ duration: '5m', target: 50 }, // sustained load
|
|
30
|
+
{ duration: '2m', target: 100 }, // spike
|
|
31
|
+
{ duration: '5m', target: 100 }, // sustained spike
|
|
32
|
+
{ duration: '2m', target: 0 }, // ramp down
|
|
33
|
+
],
|
|
34
|
+
thresholds: {
|
|
35
|
+
http_req_duration: ['p(95)<1000', 'p(99)<2000'],
|
|
36
|
+
http_req_failed: ['rate<0.05'],
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default function () {
|
|
41
|
+
const BASE_URL = __ENV.BASE_URL
|
|
42
|
+
const TOKEN = __ENV.AUTH_TOKEN
|
|
43
|
+
const headers = { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' }
|
|
44
|
+
|
|
45
|
+
const health = http.get(`${BASE_URL}/v1/health`)
|
|
46
|
+
check(health, { 'health 200': (r) => r.status === 200 })
|
|
47
|
+
|
|
48
|
+
// Add feature-specific tests here (list, create, update operations)
|
|
49
|
+
sleep(1)
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## smoke.js scaffold
|
|
54
|
+
```javascript
|
|
55
|
+
import http from 'k6/http'
|
|
56
|
+
import { check, sleep } from 'k6'
|
|
57
|
+
|
|
58
|
+
export const options = {
|
|
59
|
+
vus: 10, duration: '30s',
|
|
60
|
+
thresholds: { http_req_duration: ['p(95)<500'], http_req_failed: ['rate<0.01'] },
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default function () {
|
|
64
|
+
const BASE_URL = __ENV.BASE_URL
|
|
65
|
+
const TOKEN = __ENV.AUTH_TOKEN
|
|
66
|
+
const headers = { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' }
|
|
67
|
+
|
|
68
|
+
const health = http.get(`${BASE_URL}/v1/health`)
|
|
69
|
+
check(health, { 'health 200': (r) => r.status === 200 })
|
|
70
|
+
|
|
71
|
+
// Add feature-specific tests here
|
|
72
|
+
sleep(1)
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Results format for PR
|
|
77
|
+
```
|
|
78
|
+
Load Test (smoke — 10 VUs, 30s):
|
|
79
|
+
P95: {N}ms ✅/❌
|
|
80
|
+
Errors: {N}% ✅/❌
|
|
81
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Keep the Docker build context small and free of secrets.
|
|
2
|
+
.git
|
|
3
|
+
.github
|
|
4
|
+
.gitignore
|
|
5
|
+
.venv
|
|
6
|
+
__pycache__/
|
|
7
|
+
**/__pycache__/
|
|
8
|
+
*.pyc
|
|
9
|
+
*.pyo
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.mypy_cache/
|
|
12
|
+
.ruff_cache/
|
|
13
|
+
htmlcov/
|
|
14
|
+
.coverage
|
|
15
|
+
coverage.xml
|
|
16
|
+
|
|
17
|
+
# Secrets / local env — NEVER ship into an image
|
|
18
|
+
.env
|
|
19
|
+
.env.*
|
|
20
|
+
!.env.example
|
|
21
|
+
|
|
22
|
+
# Docs, tests, tooling — not needed at runtime
|
|
23
|
+
docs/
|
|
24
|
+
tests/
|
|
25
|
+
infra/
|
|
26
|
+
scripts/
|
|
27
|
+
*.md
|
|
28
|
+
Makefile
|
|
29
|
+
.pre-commit-config.yaml
|
|
30
|
+
.claude/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Python deps — the "uv" ecosystem reads pyproject.toml AND updates uv.lock.
|
|
4
|
+
# (The "pip" ecosystem does NOT understand uv.lock, so updates would skip the lockfile.)
|
|
5
|
+
- package-ecosystem: "uv"
|
|
6
|
+
directory: "/"
|
|
7
|
+
schedule:
|
|
8
|
+
interval: "weekly"
|
|
9
|
+
open-pull-requests-limit: 10
|
|
10
|
+
groups:
|
|
11
|
+
python-minor-patch:
|
|
12
|
+
update-types: ["minor", "patch"]
|
|
13
|
+
|
|
14
|
+
# GitHub Actions
|
|
15
|
+
- package-ecosystem: "github-actions"
|
|
16
|
+
directory: "/"
|
|
17
|
+
schedule:
|
|
18
|
+
interval: "weekly"
|
|
19
|
+
|
|
20
|
+
# Dockerfile base images
|
|
21
|
+
- package-ecosystem: "docker"
|
|
22
|
+
directory: "/"
|
|
23
|
+
schedule:
|
|
24
|
+
interval: "weekly"
|