HANDOFF — target project: webhook

Only webhook requirements are authoritative. Ignore all archived records for other projects. Updates 1–5 have been applied in order; superseded settings are discarded.

CURRENT SETTINGS
{
  "scope_key": "global",
  "latest_by": "timestamp",
  "tie_policy": "last",
  "delete_wins": false,
  "allow_resurrection": false,
  "amount_mode": "delta",
  "precision": 2,
  "gap_policy": "ignore",
  "audit_duplicate": true,
  "order": "key",
  "max_age": 120,
  "inclusive_age": false
}

FIXED INTERFACE
Implement evaluate(payload) returning:
{
  "entities": [
    {"tenant": ..., "entity": ..., "value": "fixed-point string", "deleted": boolean}
  ],
  "duplicates": [event_id, ...]
}

Input: now is an integer; events contain id, tenant, entity, seq, ts, kind ("set" or "delete"), and amount (nonnegative decimal string). Do not mutate input.

CURRENT ALGORITHM
1. Age filter before deduplication:
   Discard events where now - ts >= 120. Equality is excluded because inclusive_age=false. The contract does not exclude future timestamps.

2. Deduplicate surviving events globally by id, retaining the first encountered event regardless of tenant. Append every discarded duplicate's id to duplicates, preserving encounter order; audit_duplicate=true.

3. Group surviving unique events by (tenant, entity).

4. latest_by="timestamp" means use event.ts as the chosen sort field. Within each group, when events share the same ts, retain only the last encountered event for that timestamp. Process tie-filtered retained events in ascending ts order, not seq order.

5. For each group initialize:
   previous processed seq=0, value=0, deleted=false.

6. gap_policy="ignore":
   Process an event only if event.seq equals previous processed seq + 1. A skipped event changes nothing, including seq. Any processed event updates seq, even a set whose value update is blocked by deletion.

7. Processed delete: set deleted=true; leave value unchanged.
   Processed set: update only if not deleted, since allow_resurrection=false. An allowed set resets deleted=false and adds amount to value, since amount_mode="delta".
   Consequently, once a processed delete occurs, later sets cannot resurrect or change value, but qualifying sets still advance processed seq.

8. delete_wins=false: no additional final deletion override. A gap-skipped delete does not mark the entity deleted.

9. Round the final value once to 2 decimal places using exact ROUND_HALF_UP. Return a fixed-point string with exactly two fractional digits, including trailing zeros. Avoid binary floating-point or intermediate rounding.

10. Sort output entities by (tenant, entity), since order="key". Groups with retained events still produce an entity even if all their events fail the gap filter; their initialized value/deleted state remains "0.00"/false.

FIXED CONTRACT FOR FUTURE SETTING CHANGES
- Updates replace only explicitly supplied keys; other current settings remain unchanged.
- Age filtering discards age > max_age, and also equality unless inclusive_age=true.
- scope_key="tenant" deduplicates by (tenant,id); otherwise by id globally. Keep first. Audit duplicate ids only if audit_duplicate=true.
- latest_by selects seq ("sequence") or ts ("timestamp"); tie_policy selects first or last encountered event at each equal chosen sort-field value.
- gap_policy="accept" has no continuity filter; "ignore" uses the processed-seq rule above.
- allow_resurrection permits a set after deletion; an allowed set resets deleted=false.
- amount_mode="absolute" assigns amount; "delta" adds amount.
- delete_wins=true additionally forces final deleted=true if any tie-filtered retained event is a delete, even if gap-skipped; it never changes value.
- precision controls exact final ROUND_HALF_UP formatting, with no fractional digits when precision=0.
- order="input" uses each group's earliest retained original input index BEFORE tie filtering; order="key" sorts by (tenant,entity).
- duplicates always preserves encounter order.

UNRESOLVED / CONTINUATION
All 12 configuration choices are currently specified. No target-specific unresolved requirement was supplied. Implementation and verification remain to be done; no code or test results are included in this handoff. The next update and later questions are not yet available; do not infer their content.