
    \j                        S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKJ	r	  \
" SS5      r\
" SS5      rS	r\R                  R                  S
5      =(       d$    \R                  R                  S5      =(       d    Sr\	" \5      S-  rSS jrSS jrSS jrSS jrSS jrSS jr\S:X  a  \R2                  " \" 5       5        gg)u  
Phase F.E.stage — stage the F.B per-LB event manifests into the
renderer-accessible v2 dist tree.

Mirrors Phase C.1 / D.1 staging (one JSONL per LB, hex-named, plus a
bake-source sha256 sidecar). Output layout:

  /mnt/wbterminal1/holtburger-dist-v2/events/
    event-bake-source.sha256         # copied verbatim from F.B output
    0xA3AE.events.jsonl              # one per LB in the 13x13 ring
    0xA3AF.events.jsonl
    ...
    0xAFBA.events.jsonl
    README.md                        # schema notes

Input source (frozen, read-only — the F.B bake at commit cc42434):

  /mnt/wbterminal1/tmp/claude-scratch/event-completeness/b/holtburg-ring/

Empty JSONL files are emitted for LBs whose F.B output didn't exist
(no ambient + no entity hooks). Same invariant as Phase D.1's spawn
staging: "every LB queried" is observable from the dist tree.

Run:
  python3 stage-ring-events.py
  python3 stage-ring-events.py --source /path/to/bake/dir
  python3 stage-ring-events.py --out /path/to/events
    )annotationsN)Path            zF/mnt/wbterminal1/tmp/claude-scratch/event-completeness/b/holtburg-ringHOLTBURGER_DISTHOLTBURGER_DIST_V2z /mnt/wbterminal2/holtburger-disteventsc                    SU S 3$ )N0x04X )landblock_ids    /scripts/event-completeness/stage-ring-events.pylb_hexr   <   s    S!""    c                 |    [        5       n [         H'  n[         H  nU R                  US-  U-  5        M     M)     U $ )N   )setRING_X_RANGERING_Y_RANGEadd)outxys      r   ring_lb_setr   @   s8    ECAGGQ!VqL!   Jr   c                  ^ [         R                  " 5       nU R                  S5       m[        U4S jS5       H  nUR	                  U5        M     S S S 5        UR                  5       $ ! , (       d  f       UR                  5       $ = f)Nrbc                 &   > T R                  S5      $ )Ni   )read)fs   r   <lambda>sha256_file.<locals>.<lambda>K   s    !&&/r   r   )hashlibsha256openiterupdate	hexdigest)pathhchunkr"   s      @r   sha256_filer.   H   sb    A	4A137EHHUO 8 
 ;;= 
 ;;=s   )A))
Bc                   U R                  5       (       d  [        SU  35      eUR                  SSS9  [        [	        5       5      n[        U5      SSS0 S.nU H  n[        U5       S3nX-  nX-  nUR                  5       (       a  [        R                  " Xg5        UR                  S5       nUR                  5       n	SSS5        W	R                  S	5      n
U	(       a  U	R                  S	5      (       d  U
S
-  n
US==   S
-  ss'   US==   U
-  ss'   XS   [        U5      '   M  UR                  S5        US==   S
-  ss'   SUS   [        U5      '   M     U S-  nUS-  nUR                  5       (       a:  [        R                  " X5        SUS'   UR                  5       R                   US'   U$ SUS'   SUS'   U$ ! , (       d  f       GN= f)zCopy per-LB JSONLs from `source` into `out_dir`. Emit empty
files for LBs with no F.B output. Copy the bake-source.sha256
sidecar through verbatim. Return per-LB counts for the report.
zsource dir missing: T)parentsexist_okr   )	ring_sizewith_eventsempty_emittedtotal_eventsper_lbz.events.jsonlr   N   
   r3   r5   r6   r   r4   zevent-bake-source.sha256sha256_copiedsha256_sizeF)is_dirFileNotFoundErrormkdirsortedr   lenr   is_fileshutilcopyfiler'   r!   countendswithwrite_bytesstatst_size)sourceout_dirlbsstatslbnamesrc_pathdst_pathr"   rawrC   src_shadst_shas                r   
stage_ringrS   P   s   
 ==??"6vh ?@@MM$M.

CXE *]+=>OOH/ t$ffh %IIe$E3<<..
- A% .!U*!*/(OF2J'
   %/"a'"*+E(OF2J'- 8 11G22G)!%o&||~55m
 L "'o mL= %$s   /F??
G	c                P    SUS    SUS    SU S3nU S-  R                  U5        g )Nu  # Phase F.E — staged event manifests for the 13x13 Holtburg ring

Each `0xXXXX.events.jsonl` file contains the per-LB expected event
manifest baked by Phase F.B (commit `cc42434`). Renderer consumers
fetch one file per LB on demand, mirroring `dist/scenery/` and
`dist/spawns/`.

## Ring

13 x 13 landblocks centred on Holtburg (LB 0xA9B4). 169 LBs total —
identical ring to Phases C.1 (scenery) + D.1 (spawns).

## Schema (per JSONL line)

Three event kinds appear:

### Ambient (`source: "ambient"`)

```jsonc
{
  "source":         "ambient",
  "trigger":        "terrain",
  "terrain_type":   1,
  "scene_type":     0,
  "scene_info_idx": 18,
  "stb_index":      9,
  "stb_id":         "0x2000001B",
  "vertex_indices": [0, 19, 20, ...],  // 81-vertex LB indices
  "ambient_sounds": [
    {"s_type": 70, "volume": 0.25, "base_chance": 0.0,
      "min_rate": 8.27, "max_rate": 8.27, "continuous": true},
    ...
  ]
}
```

- `base_chance == 0 && continuous` → one continuous loop while
  terrain_type is active at the player's vertex.
- `base_chance > 0 && !continuous` → probabilistic roll per
  `[min_rate, max_rate]` interval.

### PhysicsScript particle (`source: "physics_script_particle"`)

```jsonc
{
  "source":           "physics_script_particle",
  "trigger":          "physics_script_particle",
  "default_script_id":"0x3300067A",
  "start_time_s":     0.0,
  "emitter_id":       "0x320002CD",
  "part_index":       0,
  "blocking":         false,
  "anchor":           "entity_origin"
}
```

Each row is one CreateParticle hook in a `PhysicsScript` referenced
from a spawned entity's `default_script_id`. The H2 walker in
`scene3d/entities.js` consumes these at spawn time.

### Anim sound (`source: "anim_sound"`) — DEFERRED

Anim-sound rows are NOT in the F.B bake. The F.B docs flag this as
"channel not yet exercised through synthetic spawn data; awaiting
F.B.5 (wcid -> MotionTableDataId staging)". The F.D validator
reports `anim_sound: 0 observed / 0 expected` for the ring.

## Notes

- **Empty files are intentional.** r4   z of
  r2   a   LBs in the ring produced zero events at bake
  time (no ambient + no entity hooks). The runtime treats an empty
  file as "queried, zero events" (not 404 "not yet baked").
- **`event-bake-source.sha256`** carries the input DAT hashes + the
  bake-tool version. F.E consumers verify their DATs match before
  honouring the manifest, same contract as `scenery/bake-source.sha256`.

## Reproducibility

```sh
python3 stage-ring-events.py
```

Deterministic given the same F.B bake input. Source:
`z` (frozen at commit cc42434).
z	README.md)
write_text)rI   rK   rH   bodys       r   write_readmerW      sV    E$J %*/$:#; <  	 
iUDl {&&t,r   c                 4   [         R                  " [        S9n U R                  S[        [
        S9  U R                  S[        [
        S9  U R                  5       nUR                  R                  5       nUR                  R                  5       n[        SU 35        [        SU 35        [        X#5      n[        X4U5        [        SUS    S	US
    SUS    SUS    SUS    3
5        [        S5        US   (       d  [        S[        R                  S9  gg)N)descriptionz--source)defaulttypez--outz[stage-ring-events] source: z[stage-ring-events] out:    z[stage-ring-events] ring_size=r2   z with_events=r3   z empty_emitted=r4   z total_events=r5   z sha256_copied=r9   z#[stage-ring-events] wrote README.mdui   [stage-ring-events] WARNING: source bake missing event-bake-source.sha256 — consumers can't verify DATs)filer8   r   )argparseArgumentParser__doc__add_argumentDEFAULT_SOURCEr   DEFAULT_OUT
parse_argsrH   resolver   printrS   rW   sysstderr)pargssrcr   rK   s        r   mainrk      s#   G4ANN:~DNANN7KdN;<<>D
++


C
((


C	(
./	(
./s ES!	
({);(< =]+, -/0 1n-. //0		2 
/1!G	

 r   __main__)r   intreturnstr)rn   zset[int])r+   r   rn   ro   )rH   r   rI   r   rn   dict)rI   r   rK   rp   rH   r   rn   None)rn   rm   )r_   
__future__r   r]   r%   osrA   rf   pathlibr   ranger   r   ra   environgetr	   rb   r   r   r.   rS   rW   rk   __name__exitr   r   r   <module>rz      s   : #   	  
 
 T4 T4 )  JJNN$% *	zz~~*+*) 
 ?#h.#8vW-t@ zHHTV r   