# SmartStack Layers — Execution Rules & Skill/MCP Mapping

> **Loaded by:** step-02 (planning) and step-03 (execution)
> **Purpose:** Defines per-layer folder conventions, skill/MCP tools, and verification rules.

---

## Layer Isolation Rules (Clean Architecture)

### Dependency Graph (allowed imports)

```
Domain         → (nothing)
Application    → Domain
Infrastructure → Domain, Application
Api            → Application, Infrastructure
Web            → Application (via API clients)
```

### FORBIDDEN Patterns

| Layer | FORBIDDEN import | Why |
|-------|-----------------|-----|
| Domain | Application, Infrastructure, Api | Domain is the core, depends on nothing |
| Application | Infrastructure, Api | Application defines interfaces, Infrastructure implements them |
| Controller | DbContext (direct injection) | Controllers use Application services, not database directly |
| Controller | IRepository (direct injection) | Controllers use Application services, not repositories |
| Domain | EF Core attributes (`[Table]`, `[Column]`, `[Index]`) | Domain must be persistence-ignorant; use `IEntityTypeConfiguration<T>` in Infrastructure |
| Domain | `using Microsoft.EntityFrameworkCore` | Infrastructure concern leaking into Domain |
| API response | Domain entity (e.g., `ActionResult<Employee>`) | Return DTOs (`EmployeeResponseDto`), never Domain entities |

### Enforcement

- **MCP `validate_conventions(checks: ['architecture'])`** — scans `.cs` files for forbidden imports, DbContext injection, entity exposure, and service interface placement
- **MCP `review_code(checks: ['architecture'])`** — detects layer violations, DbContext in controllers, EF Core attributes in Domain, entity exposure in API responses
- **POST-CHECKs A1–A7** — bash-based defense-in-depth (see `post-checks.md`)

---

## Layer 0 — Domain (sequential)

**Entities:** `Domain/Entities/{App}/{Module}/`
**Enums:** `Domain/Enums/{App}/{Module}/`
**Exceptions:** `Domain/Exceptions/{App}/{Module}/`

| Action | Tool |
|--------|------|
| Create entity | MCP `scaffold_extension` (type: entity) |
| Validate | MCP `validate_conventions` |

**Rules:**
- Inherit `BaseEntity`, choose tenant interface based on data isolation requirements:
  - **`ITenantEntity`** (strict mode, default): User can only access their tenant's data. Implement `Guid TenantId { get; set; }`. Service MUST filter by `_currentTenant.TenantId` with guard clause.
  - **`IOptionalTenantEntity`** (optional mode): Cross-tenant data (shared lookup tables, public content). Implement `Guid? TenantId { get; set; }`. Service MAY accept null TenantId. EF global filter handles both shared (null) and tenant-scoped (TenantId == current) rows automatically.
  - **`IScopedTenantEntity`** (scoped mode): Data scoped by Scope + TenantId combination. Validate both match current context in service layer.
  - **No tenant interface** (none mode): Cross-tenant system data (no isolation). No TenantId property, no filtering needed.
- Also implement `IAuditableEntity` for CreatedBy/UpdatedBy tracking
- See `references/smartstack-api.md` for exact BaseEntity API (Id, CreatedAt, UpdatedAt only)
- No Code/IsDeleted/RowVersion in BaseEntity — add business properties yourself
- Domain events for state changes
- Value objects for composite values

---

## Layer 0 — Infrastructure: EF Core (sequential)

**Configs:** `Infrastructure/Persistence/Configurations/{App}/{Module}/`
**Migrations:** `Infrastructure/Persistence/Migrations/` (NEVER subdirectories)

| Action | Tool |
|--------|------|
| Create config | MCP `scaffold_extension` (type: configuration) |
| Create migration | MCP `suggest_migration` → `dotnet ef migrations add` |
| Validate | MCP `check_migrations` |

**Rules:**
- One config per entity, table name = plural
- All relationships explicitly configured
- Indexes on FKs and frequent queries
- Register DbSet in ExtensionsDbContext
- Migration name ALWAYS from MCP `suggest_migration`
- Migration flag: `-o Persistence/Migrations`

**BLOCKING:** `dotnet build --no-restore` MUST pass after migration.

> **CRITICAL — Migration must cover ALL entities (POST-CHECK 36, 40):**
> Create/update migration AFTER ALL entities and EF configs are registered in DbContext.
> Verify with `dotnet ef migrations has-pending-model-changes` — must report NO pending changes.
> If entities are added incrementally across modules, create a NEW migration for each batch.

---

## Layer 1 — Application (parallel with API)

**Services:** `Application/Services/{App}/{Module}/` (interface)
**Service impls:** `Infrastructure/Services/{App}/{Module}/` (implementation)
**DTOs:** `Application/DTOs/{App}/{Module}/`
**Validators:** `Application/Validators/{App}/{Module}/`

| Action | Tool |
|--------|------|
| Create service/DTO | MCP `scaffold_extension` |
| Complex service logic | /application skill |
| Validate | MCP `validate_conventions` |

**Rules:**
- **Tenant injection depends on entity tenant mode** (see entity rules below):
  - **strict mode (default):** Inject `ICurrentTenantService` + guard clause: `var tenantId = _currentTenant.TenantId ?? throw new TenantContextRequiredException();` (mandatory, returns 400)
  - **optional mode:** Inject `ICurrentTenantService`, no guard: `var tenantId = _currentTenant.TenantId;` (nullable). EF global filter handles shared+tenant data.
  - **scoped mode:** Inject `ICurrentTenantService`, validate Scope + TenantId consistency. Tenant scope requires TenantId.
  - **none mode:** No `ICurrentTenantService` injection needed (cross-tenant data, no filtering)
- **ALL services MUST inject `ICurrentUserService`** for audit trails
- **ALL services MUST inject `ILogger<T>`** for production diagnostics
- CQRS with MediatR
- FluentValidation for all commands — **MUST register validators via DI:**
  `services.AddValidatorsFromAssemblyContaining<Create{Entity}DtoValidator>();`
  Without DI registration, `[FromBody]` DTOs are never validated (POST-CHECK 38)
- **Date fields in DTOs MUST use `DateOnly`**, not `string` (POST-CHECK 39). See `smartstack-api.md` DTO Type Mapping.
- DTOs separate from domain entities
- Service interfaces in Application, implementations in Infrastructure
- **FORBIDDEN:** `tenantId: Guid.Empty`, `TenantId!.Value`, queries without TenantId filter, `ICurrentUser` (does not exist — use `ICurrentUserService` + `ICurrentTenantService`), `string` type for date fields

---

## Layer 1 — API (parallel with Application)

**Controllers:** `Api/Controllers/{AppPascal}/{Entity}Controller.cs`

| Action | Tool |
|--------|------|
| Simple CRUD controller | MCP `scaffold_extension` |
| Complex controller | /controller skill |
| Validate | MCP `validate_security` |

**Rules:**
- `[RequirePermission(Permissions.{Module}.{Action})]` on EVERY endpoint
- **NavRoute minimum 2 segments** (application.module):
  - `[NavRoute("human-resources.employees")]` (CORRECT — module-level, 2 segments)
  - `[NavRoute("human-resources.employees.departments")]` (CORRECT — section-level, 3 segments)
  - `[NavRoute("administration.ai", Suffix = "prompts")]` (CORRECT — sub-resource with Suffix)
- **NavRoute values MUST use kebab-case for ALL multi-word segments:**
  - `[NavRoute("human-resources.employees")]` (CORRECT)
  - `[NavRoute("humanresources.employees")]` (WRONG — missing hyphens)
  - `[NavRoute("project-management.projects")]` (CORRECT)
  - `[NavRoute("projectmanagement.projects")]` (WRONG)
- Permission paths MUST use kebab-case matching NavRoute codes (e.g., `human-resources.employees.read`)
- FORBIDDEN: concatenated segments like `humanresources` — must be `human-resources`
- POST-CHECK 32 detects non-kebab-case NavRoute values. POST-CHECK 33 detects non-kebab-case permissions
- **FORBIDDEN:** `[Route("api/...")]` alongside `[NavRoute]` — causes 404s (POST-CHECK 41)
- `[NavRoute]` is the ONLY route attribute needed — resolves routes from DB at startup
- NEVER use `[Authorize]` without specific permission
- Swagger XML documentation
- Return DTOs, never domain entities

---

## Layer 1 — Seed Data (parallel)

**Folder:** `Infrastructure/Persistence/Seeding/Data/{ModulePascal}/`

> **Detailed templates:** See ralph-loop `references/core-seed-data.md` for complete C# code templates.
> Navigation hierarchy: Application → Module → Section → Resource (ALL levels need seed data).

| Action | Tool |
|--------|------|
| Generate permissions | MCP `generate_permissions` (PRIMARY) |
| Navigation seed | Templates below |
| Roles seed | Templates below |
| Provider | Templates below |

### Seed Data Chain (9 files minimum)

**Application-level (created ONCE, shared across modules):**
1. **NavigationApplicationSeedData.cs** — Application-level navigation entry (MUST be first)
2. **ApplicationRolesSeedData.cs** — Application-scoped roles (admin, manager, contributor, viewer) with random GUIDs (`Guid.NewGuid()`). Provides role entries for SeedRolesAsync().

**Per-module:**
3. **NavigationModuleSeedData.cs** — Random GUIDs (`Guid.NewGuid()`), 4 languages (fr, en, it, de)
4. **NavigationSectionSeedData.cs** — Section-level navigation (if sections defined)
5. **NavigationResourceSeedData.cs** — Resource-level navigation (if resources defined)
6. **Permissions.cs** — Static permission constants: `public static class {Module} { public const string Read = "..."; }`. Referenced by `[RequirePermission(Permissions.{Module}.Read)]`.
7. **PermissionsSeedData.cs** — MCP `generate_permissions` first, fallback template
8. **RolesSeedData.cs** — Code-based role mapping: Admin=wildcard(*), Manager=CRU, Contributor=CR, Viewer=R. **NEVER use deterministic GUIDs for roles** — look up by Code at runtime.

**Infrastructure (created ONCE per application):**
9. **{App}SeedDataProvider.cs** — Implements IClientSeedDataProvider
   - `SeedNavigationAsync()` — seeds Application → Module → Section → Resource + translations
   - `SeedRolesAsync()` — seeds application-scoped roles from ApplicationRolesSeedData
   - `SeedPermissionsAsync()` — seeds permission entries from PermissionsSeedData
   - `SeedRolePermissionsAsync()` — maps roles to permissions (roles resolved by Code, NOT by GUID)
   - DI: `services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()`

### GUID Generation Rule

```csharp
// ALWAYS use Guid.NewGuid() for ALL seed data IDs
// Avoids conflicts between projects/tenants/environments
// Idempotence is handled by Code-based lookups at runtime
public static readonly Guid ModuleId = Guid.NewGuid();
```

### Route Convention (CRITICAL — Full Paths Required)

> **Routes stored in DB drive the platform menu AND application-tracking.**
> Short routes (e.g., `humanresources`) cause **400 Bad Request** on every page navigation.

**Route format: `/{app-kebab}/{module-kebab}/{section-kebab}`**

| Level | Code (C#) | Route (DB) |
|-------|-----------|-----------|
| Application | `human-resources` | `/human-resources` |
| Module | `employees` | `/human-resources/employees` |
| Section | `departments` | `/human-resources/employees/departments` |
| Resource | `export` | `/human-resources/employees/departments/export` |

**Examples (verified from SmartStack.app):**
- `/administration` (not `administration` without `/`)
- `/administration/users` (not `users`)

- PascalCase for C# code identifiers (`HumanResources`)
- **kebab-case** for ALL URL routes in seed data (`human-resources`)
- **Routes MUST start with `/`** and include full parent hierarchy
- Helper: `ToKebabCase()` transforms PascalCase → kebab-case

```csharp
private static string ToKebabCase(string value)
    => System.Text.RegularExpressions.Regex.Replace(value, "([a-z])([A-Z])", "$1-$2").ToLowerInvariant();

// Route construction:
var appRoute = $"/{ToKebabCase(appCode)}";
// → "/human-resources"

var moduleRoute = $"{appRoute}/{ToKebabCase(moduleCode)}";
// → "/human-resources/employees"

var sectionRoute = $"{moduleRoute}/{ToKebabCase(sectionCode)}";
// → "/human-resources/employees/departments"
```

**ROUTE SPECIAL CASES (list and detail sections):**
> `list` and `detail` are view modes of the module, NOT functional sub-areas.
> - `list` section route = module route (e.g., `/human-resources/employees`) — NO `/list` suffix
> - `detail` section route = module route + `/:id` (e.g., `/human-resources/employees/:id`) — NOT `/detail/:id`
> - FORBIDDEN: `/employees/list`, `/employees/detail/:id`
> - Other sections (dashboard, approve, import) = module route + `/{section-kebab}` (normal)

**FORBIDDEN:**
- Deterministic/sequential/fixed GUIDs → ALWAYS use `Guid.NewGuid()`
- Missing translations (must have fr, en, it, de)
- Empty seed classes with no seeding logic
- PascalCase in route URLs → always kebab-case
- Missing NavigationApplicationSeedData → menu invisible
- **Short routes without `/` prefix** → `"humanresources"` must be `"/human-resources"`
- **Routes without parent hierarchy** → `"employees"` must be `"/human-resources/employees"`

---

## Layer 2 — Frontend (parallel with I18n)

> **Detailed patterns:** See `references/smartstack-frontend.md` for complete code templates.

**Pages:** `src/pages/{AppPascal}/{Module}/`
**Components:** `src/components/{Module}/`

| Action | Tool |
|--------|------|
| API client | MCP `scaffold_api_client` |
| Routes | MCP `scaffold_routes` (outputFormat: `clientRoutes`) |
| Complex pages | /ui-components skill + `smartstack-frontend.md` patterns |
| Validate routes | MCP `validate_frontend_routes` |

**Layout mapping:** Configured per application in the routing configuration.

### Lazy Loading (MANDATORY)

ALL page components MUST be lazy-loaded using `React.lazy()`:

```tsx
const EmployeesPage = lazy(() =>
  import('@/pages/HumanResources/Employees/EmployeesPage')
    .then(m => ({ default: m.EmployeesPage }))
);

// Route element — ALWAYS wrap with Suspense
element: <Suspense fallback={<PageLoader />}><EmployeesPage /></Suspense>
```

### Page Structure Pattern

All pages MUST follow: hooks → useEffect(load) → loading state → error state → content.

```tsx
// 1. Hooks at top
const { t } = useTranslation(['{module}']);
// 2. State
const [loading, setLoading] = useState(true);
// 3. useCallback + useEffect for data loading
// 4. if (loading) return <Loader2 spinner />
// 5. if (error) return <error UI with retry>
// 6. return <content with CSS variables>
```

### Components & CSS

**Components:** SmartTable, SmartFilter, EntityCard, SmartForm, StatCard (NEVER raw HTML)
**CSS:** Variables ONLY — hardcoded Tailwind colors are **BLOCKING** in POST-CHECK 9:

| Instead of | Use |
|-----------|-----|
| `bg-white` | `bg-[var(--bg-card)]` |
| `bg-gray-50` | `bg-[var(--bg-primary)]` |
| `text-gray-900` | `text-[var(--text-primary)]` |
| `text-gray-500` | `text-[var(--text-secondary)]` |
| `border-gray-200` | `border-[var(--border-color)]` |
| `bg-blue-600` | `bg-[var(--color-accent-500)]` |
| `hover:bg-blue-700` | `hover:bg-[var(--color-accent-600)]` |
| `text-red-500` | `text-[var(--error-text)]` |

**Loader:** `Loader2` from `lucide-react` for spinners, `PageLoader` for Suspense fallback

### Section Routes (when module has sections)

If the module defines `{sections}`, generate frontend routes for EACH section as children of the module route:

```tsx
// Section routes are nested inside the module's children array
{ path: '{section-kebab}', element: <Suspense fallback={<PageLoader />}><{Section}Page /></Suspense> },
{ path: '{section-kebab}/create', element: <Suspense fallback={<PageLoader />}><Create{Section}Page /></Suspense> },
{ path: '{section-kebab}/:id', element: <Suspense fallback={<PageLoader />}><{Section}DetailPage /></Suspense> },
{ path: '{section-kebab}/:id/edit', element: <Suspense fallback={<PageLoader />}><Edit{Section}Page /></Suspense> },
```

Section pages live in `src/pages/{AppPascal}/{Module}/{Section}/`.

### FK Fields in Forms (CRITICAL)

Any entity property that is a FK Guid (e.g., `EmployeeId`, `DepartmentId`) MUST use the `EntityLookup` component — NEVER a `<select>` dropdown, NEVER a `<input type="text">`. Users cannot type GUIDs manually, and `<select>` fails at scale (no search, loads all options).

```tsx
// CORRECT — EntityLookup for FK field (ONLY acceptable pattern)
<EntityLookup
  apiEndpoint="/api/human-resources/employees"
  value={formData.employeeId}
  onChange={(id) => handleChange('employeeId', id)}
  label={t('module:form.employee', 'Employee')}
  mapOption={(item) => ({ id: item.id, label: item.name, sublabel: item.code })}
  required
/>

// WRONG — plain text input for FK GUID
<input type="text" value={formData.employeeId} placeholder="Enter employee ID" />

// WRONG — <select> dropdown for FK field (even with API-loaded options)
<select value={formData.departmentId} onChange={(e) => setFormData({...formData, departmentId: e.target.value})}>
  <option value="">Select...</option>
  {departments.map(d => <option key={d.id} value={d.id}>{d.name}</option>)}
</select>
```

**Backend requirement:** Each target entity's GetAll endpoint MUST accept `?search=` parameter. See `smartstack-api.md` Service Pattern.

See `references/smartstack-frontend.md` section 6 for the full `EntityLookup` component definition and usage patterns.

**FORBIDDEN:**
- `src/pages/{Module}/` (flat, missing App)
- `import axios` → use `@/services/api/apiClient`
- `<table>` → use SmartTable
- `<input type="text">` for FK Guid fields → use `EntityLookup`
- `<select>` for FK Guid fields → use `EntityLookup` (even with API-loaded options)
- Placeholder "Enter ID" or "Enter GUID" → use `EntityLookup`
- Hardcoded Tailwind colors (`bg-white`, `text-gray-900`) → use CSS variables
- Static page imports in route files → use `React.lazy()`
- `<Suspense>` without `fallback` prop
- Only fr/en → MUST have 4 languages
- `t('key')` without namespace prefix → use `t('ns:key', 'fallback')`
- Hardcoded user-facing strings in JSX → use `t()`

---

## Layer 2 — I18n

> **Template:** See `references/smartstack-frontend.md` Section 2 for complete JSON template.

4 JSON files per module namespace: fr, en, it, de — identical key structures.

**Location:** `src/i18n/locales/{lang}/{module}.json`

**Required keys:** `title`, `description`, `actions`, `labels`, `columns`, `form`, `errors`, `validation`, `messages`, `empty`

**Usage pattern:**
```tsx
const { t } = useTranslation(['{module}']);
t('{module}:title', 'Module Title')           // ALWAYS with fallback
t('{module}:actions.create', 'Create entity') // ALWAYS with namespace prefix
```

---

## Layer 2b — Documentation (after frontend pages exist)

> **After frontend pages are created, generate module documentation.**

| Action | Tool |
|--------|------|
| Generate doc-data.ts + page wrapper | `/documentation` skill (type: user) |
| Verify DocToggleButton in pages | POST-CHECK 24 |

**Output files:**
- `src/pages/docs/business/{app}/{module}/doc-data.ts` — data-driven documentation
- `src/pages/docs/business/{app}/{module}/index.tsx` — page wrapper using `DocRenderer`
- `src/i18n/locales/fr/docs-{app}-{module}.json` — French doc translations

**DocToggleButton (MANDATORY):** Every list/detail page must include `DocToggleButton` in its header.
See `references/smartstack-frontend.md` section 7 for the component pattern.

---

## Layer 3 — Tests (sequential)

| Action | Tool |
|--------|------|
| Unit tests (domain) | MCP `scaffold_tests` (target_layer: domain) |
| Unit tests (app) | MCP `scaffold_tests` (target_layer: application) |
| Integration tests (api) | MCP `scaffold_tests` (target_layer: api, type: integration) |
| Security tests | MCP `scaffold_tests` (type: security) |
| Coverage check | MCP `analyze_test_coverage` |
| Scenarios | MCP `suggest_test_scenarios` |

**Target:** >= 80% coverage, 100% pass rate.
**Fix CODE, not tests.**

---

## Planning Template — Per-File Plan Format

> **Used by step-02 when creating the execution plan.** Each entity MUST include:

```yaml
Entity: {EntityName}
  - tenantMode: strict | optional | scoped | none
  - codePattern: auto-generated strategy (if applicable)
  - fkFields: [{field, targetEntity}] (if applicable)
  - acceptance criteria: [AC1, AC2, ...]
```

For EACH file in the plan, specify HOW it will be created/modified:

**Layer 0 — Domain + Infrastructure (sequential):**

| # | File | Action | Tool |
|---|------|--------|------|
| 1 | Domain/Entities/.../Entity.cs | create | MCP scaffold_extension |
| 2 | Infrastructure/.../EntityConfiguration.cs | create | MCP scaffold_extension |
| 3 | Infrastructure/Migrations/ | create | MCP suggest_migration + dotnet ef |

**Layer 1 — Application + API + Seed Data (parallel):**

| # | File | Action | Tool |
|---|------|--------|------|
| 4 | Application/Services/.../Service.cs | create | MCP scaffold_extension |
| 5 | Application/DTOs/.../Dto.cs | create | MCP scaffold_extension |
| 6 | Api/Controllers/.../Controller.cs | create | /controller skill or MCP scaffold_extension |
| 7 | Seeding/Data/NavigationApplicationSeedData.cs | create | Reference Layer 1 Seed Data (once per app) |
| 7b | Seeding/Data/ApplicationRolesSeedData.cs | create | Reference Layer 1 Seed Data (once per app) |
| 7c | Infrastructure/Services/CodeGeneration/ | create | Reference code-generation.md (if codePattern != manual) |
| 8 | Seeding/Data/.../NavigationModuleSeedData.cs | create | Reference core-seed-data.md (4 langs) |
| 8b | Application/Authorization/Permissions.cs | create | MCP generate_permissions |
| 9 | Seeding/Data/.../PermissionsSeedData.cs | create | MCP generate_permissions |
| 10 | Seeding/Data/.../RolesSeedData.cs | create | Reference Layer 1 Seed Data |
| 10b | Seeding/{App}SeedDataProvider.cs | create | Reference core-seed-data.md (IClientSeedDataProvider + DI) |

**Layer 1 — Frontend (parallel):**

| # | File | Action | Tool |
|---|------|--------|------|
| 11 | src/pages/{App}/{Mod}/ListPage.tsx | create | /ui-components skill |
| 11b | src/pages/{App}/{Mod}/CreatePage.tsx | create | /ui-components skill (FK: EntityLookup) |
| 11c | src/pages/{App}/{Mod}/EditPage.tsx | create | /ui-components skill (FK: EntityLookup) |
| 12 | src/services/api/{module}Api.ts | create | MCP scaffold_api_client |
| 13 | src/routes/{module}.tsx | create | MCP scaffold_routes |
| 14 | src/i18n/locales/{lang}/{module}.json | create | Reference smartstack-frontend.md (4 languages) |

**Layer 2b — Documentation (after frontend):**

| # | File | Action | Tool |
|---|------|--------|------|
| 14b | src/pages/docs/business/{app}/{module}/doc-data.ts | create | /documentation skill |
| 14c | src/pages/docs/business/{app}/{module}/index.tsx | create | /documentation skill |

**Layer 3 — Tests (sequential):**

| # | File | Action | Tool |
|---|------|--------|------|
| 15 | tests/.../EntityTests.cs | create | MCP scaffold_tests |
| 16 | tests/.../ServiceTests.cs | create | MCP scaffold_tests |

**FK Field Guidance:** If step-01 identified `fkFields[]`, every Create/Edit page MUST use `EntityLookup` for those fields (see `smartstack-frontend.md` section 6).

---

## Parallelization Strategy (Agent Teams)

If NOT economy_mode AND Layer 1 has both backend and frontend work:

**Create agent teams to execute Layer 1 backend and frontend in parallel.**

See `references/agent-teams-protocol.md` for team creation, teammate spawning, task coordination, and shutdown.

---

## Delegate Mode Fast Path

When `/ralph-loop` invokes `/apex -d {prd_path}`, PRD tasks already define the scope.

Map each PRD task to a layer based on `task.category`:
- `domain` → Layer 0
- `infrastructure` → Layer 0
- `application` → Layer 1
- `api` → Layer 1
- `seedData` → Layer 1
- `frontend` → Layer 2
- `test` → Layer 3

For each task: infer file_path, action, and tool from category. SKIP user checkpoint. Jump to "Estimated Commits" section.
