87 lines
7.1 KiB
Python
87 lines
7.1 KiB
Python
import json, os, urllib.request
|
||
|
||
body = """Executing unit: u7
|
||
|
||
[Claude #9] Stage 3 Round #7 — IMP-09 PR 2 u7
|
||
|
||
### unit_executed
|
||
- **id**: `u7`
|
||
- **summary**: Wire `build_layout_css` override branch — route 5 2-D topologies through `_override_to_grid_tracks`; downgrade warn-and-fallthrough to `single` only (text updated to name `single`)
|
||
|
||
### files_changed
|
||
- `src/phase_z2_pipeline.py` (+16 / -6 this unit; +244 / -12 cumulative across u1+u2+u3+u4+u5+u6+u7)
|
||
|
||
### diff_summary
|
||
- Two edits inside `build_layout_css` docstring + override branch (Step D-ext). PR 1 helpers (`_parse_css_areas`, `_parse_fr_string`, `compute_zone_layout`, `compute_zone_layout_cols`, `_compute_per_zone_geometry`, `_build_fr_default`, `_build_rows_dynamic`, `_build_cols_dynamic`) untouched. u1–u5 surfaces (`TOPOLOGY_AXIS_MAP`, `_TWO_D_TOPOLOGIES`, `_aggregate_axis_zone`, `_build_2d_dynamic`, `_derive_axis_tracks_from_override`, `_override_to_grid_tracks`) unchanged. u6 normal-path dispatch arms unchanged.
|
||
|
||
- **Edit 1 — docstring `Step D-ext` block (−5 / +7 lines)**:
|
||
- Replaced the PR 1 lock note ("horizontal-2 / vertical-2 만 처리 … 다른 preset 은 warn-and-fallthrough") with explicit per-branch enumeration: `horizontal-2 / vertical-2` = legacy inline byte-preserved; `topology in _TWO_D_TOPOLOGIES` (T / inverted-T / side-T-left / side-T-right / 2x2) = PR 2 (u7) routes through `_override_to_grid_tracks` (per-axis MAX with dynamic fallback); `single` = warn-and-fallthrough (PR 3 candidate).
|
||
|
||
- **Edit 2 — Step D-ext override-branch dispatch (−7 / +14 lines of logic + warn text)**:
|
||
- **New arm inserted between `elif layout_preset == \"vertical-2\"` and the warn-fallthrough `else`**:
|
||
```python
|
||
elif topology in _TWO_D_TOPOLOGIES:
|
||
# PR 2 (u7) — 2-D topologies route through unified
|
||
# _override_to_grid_tracks (per-axis MAX with dynamic fallback).
|
||
return _override_to_grid_tracks(
|
||
preset, zones_data, override_zone_geometries, gap
|
||
)
|
||
```
|
||
Calls u5 helper with the legacy `(preset, zones_data, override_zone_geometries, gap)` signature. Returns the u5 dict shape (`computation=\"user_override_2d\"`, `dynamic_rows=True`, `dynamic_cols=True`, `raw_zone_layout={rows, cols, fallback}`).
|
||
- **`else:` warn-and-fallthrough block downgraded to `single` only**:
|
||
- Comment header changed: `# PR 1 lock — warn-and-fallthrough preserved.` + `# PR 2 promotes this to strict ValueError via _override_to_grid_tracks.` → `# ` + backtick + `single` + backtick + ` only — warn-and-fallthrough preserved.`
|
||
- Warning text now names every supported preset and explicitly calls out `single`: `\"(현재 horizontal-2 / vertical-2 / T / inverted-T / side-T-left / side-T-right / 2x2 만; ` + backtick + `single` + backtick + ` 은 미지원). default layout_css 사용.\"` — matches Stage 2 spec "text updated to name `single`".
|
||
- `print(..., file=sys.stderr)` call signature unchanged (still `sys.stderr`, still side-effect only; warn-and-then-fallthrough behavior preserved for the `single` case).
|
||
- **Branch ordering**: the new `elif topology in _TWO_D_TOPOLOGIES` arm is placed AFTER both legacy `if`/`elif` arms but BEFORE the `else` — so `horizontal-2` and `vertical-2` continue to hit their legacy inline code (byte-preserve invariant) and only non-legacy 2-D presets reach the new arm. `single` (and any future non-2-D non-legacy preset) reaches the downgraded warn-fallthrough `else`.
|
||
|
||
- **Length-locked R/C invariant**: 2-D override path returns the same `len(heights_px) == len(axis_map[\"rows\"]) == 2` and `len(widths_px) == len(axis_map[\"cols\"]) == 2` length-locked tracks that u5 produces. Smoke confirms `R=2 C=2` for all 5 in-scope presets.
|
||
|
||
- **Retry gate preservation (lines 1621-1629)**: gate skips when `dynamic_cols=True` OR `dynamic_rows=False`. Verified for both PR 2 paths:
|
||
- 2-D normal (u6): `dynamic_cols=True` → skips. ✓
|
||
- 2-D override (u7): `dynamic_cols=True` → skips. ✓
|
||
- legacy `horizontal-2` override: `dynamic_rows=True`, `dynamic_cols=False` → does NOT skip (existing semantic preserved).
|
||
- legacy `vertical-2` override: `dynamic_rows=False`, `dynamic_cols=True` → skips (existing semantic preserved).
|
||
|
||
### evidence
|
||
- `git log -1 --format=%H` → `201099e53b0048f3040e17ee9b0394ba9ad6e940` (Stage 2 baseline preserved; no commit/push this turn per Stage 3 contract).
|
||
- `git diff --stat src/phase_z2_pipeline.py` → `1 file changed, 244 insertions(+), 12 deletions(-)` (cumulative across u1+u2+u3+u4+u5+u6+u7; u7-only delta = 244−228=**+16** / 12−6=**−6** ⇒ **22 lines changed** ≤ 50-line gate ✓).
|
||
- `git diff --numstat` → `244 12 src/phase_z2_pipeline.py` (single file ≤ 3-file gate ✓).
|
||
- `git diff --check src/phase_z2_pipeline.py` → no whitespace errors.
|
||
- `git diff --name-only HEAD -- src/space_allocator.py` → empty (Kei legacy `build_containers_type_b` invariant preserved ✓).
|
||
- AST parse: `PARSE OK`.
|
||
- **Behavior smoke** (import-load with module on sys.path):
|
||
- `top-1-bottom-2` override → `comp=user_override_2d dyn_r=True dyn_c=True R=2 C=2` ✓
|
||
- `top-2-bottom-1` override → `comp=user_override_2d dyn_r=True dyn_c=True R=2 C=2` ✓
|
||
- `left-1-right-2` override → `comp=user_override_2d dyn_r=True dyn_c=True R=2 C=2` ✓
|
||
- `left-2-right-1` override → `comp=user_override_2d dyn_r=True dyn_c=True R=2 C=2` ✓
|
||
- `grid-2x2` override → `comp=user_override_2d dyn_r=True dyn_c=True R=2 C=2` ✓
|
||
- `single` override → `[override-warning] … 'single 은 미지원' …` printed to stderr, then falls through to `comp=fr_default_from_preset dyn_r=False dyn_c=False` ✓
|
||
- `horizontal-2` override → `comp=user_override_geometry dyn_r=True dyn_c=False` ✓ (legacy byte-preserved)
|
||
- `vertical-2` override → `comp=user_override_geometry dyn_r=False dyn_c=True` ✓ (legacy byte-preserved)
|
||
|
||
### remaining_units
|
||
`[u8, u9, u10, u11, u12, u13, u14, u15, u16, u17, u18, u19, u20, u21, u22, u23, u24, u25, u26]`
|
||
(executed so far: u1, u2, u3, u4, u5, u6, u7 — 7 / 26)
|
||
|
||
### follow_up_issue_candidates
|
||
None — u7 stays inside scope-lock (override-branch dispatch for the 5 declared 2-D topologies + downgrade of warn-fallthrough to `single`). Stage 2 already enumerated downstream consumers for follow-up:
|
||
- `single` topology dynamic promotion (separate PR).
|
||
- retry_gate extension to 2-D presets (currently only skip-validated by u12).
|
||
- B4 frame_selection evidence integration.
|
||
- Consumer audit for Step 8 `computation` label change (`\"2d_dynamic_aggregated\"` / `\"user_override_2d\"`) — u7 added the second label call site; u26 closing scope-lock audit can confirm no untracked consumer depends on the old fr_default label for these 5 presets.
|
||
"""
|
||
|
||
payload = json.dumps({"body": body}).encode("utf-8")
|
||
req = urllib.request.Request(
|
||
"https://gitea.hmac.kr/api/v1/repos/Kyeongmin/C.E.L_Slide_test2/issues/9/comments",
|
||
data=payload,
|
||
headers={
|
||
"Authorization": f"token {os.environ['GITEA_TOKEN']}",
|
||
"Content-Type": "application/json",
|
||
},
|
||
method="POST",
|
||
)
|
||
with urllib.request.urlopen(req) as resp:
|
||
data = json.loads(resp.read().decode("utf-8"))
|
||
print(f"POSTED id={data['id']} url={data['html_url']}")
|