# DigiDala — Alpha 50.6.2 Changeset

## Candidate identity

```text
Base: v0.4.0-alpha.50.6.1
Candidate: 0.4.0-alpha.50.6.2
Status: candidate, not committed/tagged/deployed
Date: 2026-09-21
```

## Scope

Alpha 50.6.2 prepares the final Competitive Mandala lifecycle QA without weakening the normal Competitive participation rule.

### 1. Zero-Pix Competitive Mandalas

Competitive Mandala creation and editing now accept a non-negative integer cell price, including `0` Pix.

The existing occupation path already skips the Pix debit when the server-side cell price is zero; the change therefore enables the existing free-occupation behavior for Competitive Mandalas without introducing a separate payment path.

### 2. Competitive QA clone

Added a dedicated test-only script:

```text
scripts/competitive-qa.mjs
```

The script can:

- clone the currently active public Competitive Mandala into an `is_test=1` QA campaign;
- keep QA Competitive campaigns out of the public Competitive queue/navigation;
- create the first QA clone as active and the next QA clone as queued;
- set QA cell price to `0` Pix;
- seed exactly 199 occupied cells on either the left or right half;
- report the one remaining free cell for the manual finishing occupation;
- list active/queued QA Competitive campaigns and their occupation counts;
- remove the QA campaign, archive records, cells, occupations, events and copied artwork after testing.

The 199 seeded cells use a reserved QA-only database user. The normal Competitive rule of one cell per Telegram user per cycle is not changed.

### 3. Test-only Competitive queue activation

The existing Competitive archive lifecycle now activates the next queued campaign within the same `is_test` class as the archived campaign. Public Competitive campaigns continue to advance only to public queued campaigns; QA Competitive campaigns advance only to QA queued campaigns.

## Regression protection

- Existing public Competitive lifecycle coverage remains unchanged.
- A dedicated integration test verifies a zero-Pix QA Competitive campaign with 199 seeded cells reaches 200 cells, records `winner_side`, archives, and activates the next QA Competitive campaign.
- The test also verifies that QA campaigns do not become the public Competitive current campaign.
- API coverage verifies creation at `0` Pix and changing price back to `0` before occupation.

## Automated verification in preparation workspace

```text
Structure: OK
JavaScript syntax: OK
Unit: 10/10
Integration: 45/45
API: 17/17
Total: 72/72
```

Additional QA-script smoke verification was performed in a temporary migrated SQLite database:

```text
create Competitive QA clone → active
create second Competitive QA clone → queued
seed-199 → 199 occupied cells and one free finishing cell
list → correct QA state
cleanup both → no remaining QA campaigns
```

Windows `npm.cmd run check`: pending.
Git commit/tag: pending.
VPS deployment: pending.
Manual Telegram QA: pending after the exact candidate tag is deployed.

## Manual QA after deployment

1. Create two Competitive QA clones from the active public Competitive Mandala.
2. Open the active QA clone through `campaigns-qa-<slug>`.
3. Confirm the cell price is `0` Pix and a free cell can be opened without a Pix debit.
4. Run `seed-199 <qa-slug> left` and reload the QA Mini App.
5. Occupy the final reported free cell through Telegram as a normal user.
6. Confirm the Competitive side reaches 200, the Mandala enters completion, and the current user is the destroyer.
7. Run the normal destruction flow.
8. Verify the Competitive archive, `winner_side`, 200 trace cells and zero total Pix contribution.
9. Verify the second QA Competitive becomes active automatically.
10. Clean up both QA campaigns and verify the QA list is empty.

The existing production rule `one cell per Telegram user per cycle` must remain unchanged throughout the test.
