0fb168befcfd95017f3fd89bec04c156dae3a1b3
13
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1fb973297f |
feat(IMP-09): PR 2 — 2-D dynamic dispatch for 5 preset families
Stage 3 lock implementation: extend build_layout_css dispatch beyond
the horizontal-2 / vertical-2 1-D dynamic paths. T / inverted-T /
side-T-left / side-T-right / 2x2 now flow through a 2-D track solver
instead of the fr_default sink, with length-locked heights_px (R) +
widths_px (C) on every return path (default and override).
PR 2 scope (u1~u5):
- u1: _aggregate_zone_signals_per_track — per-row + per-col virtual
zones via max(weight) + max(min_height_px) of single-span zones,
falling back to all-span when a track has none.
- u2: _build_grid_dynamic_2d default builder — feeds virtual zones
into compute_zone_layout + compute_zone_layout_cols; emits
computation="2d_dynamic_aggregated", dynamic_rows=True,
dynamic_cols=True.
- u3: _override_to_grid_tracks override builder — single-span
aggregation (max h per row, max w per col), normalize, multiply
by avail_h/avail_w, last-element diff absorb; emits
computation="user_override_geometry"; falls back to u2 when
total_h or total_w == 0.
- u4: build_layout_css dispatcher wiring — topology in
{T, inverted-T, side-T-left, side-T-right, 2x2} routes to
_build_grid_dynamic_2d (default) or _override_to_grid_tracks
(override); legacy [override-warning] stderr removed for the
5 presets; step08 trace gains a 2-D-aware print line that fires
before the dynamic_rows / dynamic_cols branches.
- u5: PR 1 lock test test_top_1_bottom_2_fr_default_populates_geometry
renamed to test_top_1_bottom_2_dynamic_2d_populates_geometry and
flipped to PR 2 reality (computation="2d_dynamic_aggregated",
dynamic_rows=True, dynamic_cols=True).
Fixtures: 10 build_layout_css (5 presets × {default, override}) +
5 retry_gate *_dynamic_2d.yaml locking the retry gate skip reason
"dynamic_cols (2-D topology) ... IMP-09 lock" for the 5 presets.
Tests: python -m pytest -q tests = 104 passed (Stage 2 baseline
10 RED → GREEN, 0 regressions). Kei archive
(build_containers_type_b / page_structure) untouched —
rg "build_containers_type_b|page_structure" src/phase_z2_pipeline.py
returns 0 hits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
201099e53b |
feat(IMP-09): PR 1 — col-axis solver + per-zone geometry mapper + retry gate
Stage 3 round 4 lock implementation: extend build_layout_css beyond
the horizontal-2-only dynamic path. Every layout_css return now
carries length-locked col-axis keys (widths_px, width_ratios,
dynamic_cols) matching the parsed css_areas grid (R rows, C cols),
so 2-D layouts (T / 2x2 in PR 2) and the unified
_compute_per_zone_geometry mapper can plug in without further
contract churn.
PR 1 scope:
- _parse_css_areas + _parse_fr_string + _compute_per_zone_geometry
(unified — 1-D and 2-D from the same code path)
- compute_zone_layout_cols (vertical-2 weight-only solver)
- _build_fr_default / _build_rows_dynamic / _build_cols_dynamic
(populate widths_px/heights_px on every return path)
- build_layout_css override branch keeps the warn-and-fallthrough
legacy for unsupported presets (PR 2 promotes to strict raise)
- retry gate in _attempt_zone_ratio_retry skips when dynamic_cols=True
or dynamic_rows=False, with explicit retry_skipped_reason
- Step 8 artifact gains zone_widths_px_planned /
zone_col_ratios_planned (top-level) + zone_width_px_planned /
zone_col_ratio_planned (per-zone)
- debug_zones width injection via _compute_per_zone_geometry
(replaces the legacy row-only zip)
Tests: tests/phase_z2/ — 47 new cases (parse / fr-string / cols solver /
per-zone geometry / build_layout_css contract / retry gate +
6 build_layout_css YAML fixtures + 3 retry_gate fixtures).
Verification: python -m pytest -q tests = 89 passed (was 42).
horizontal-2 grid CSS strings (areas/cols/rows) byte-identical to
legacy; only additive col-axis keys are introduced.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
8f6cffc2a7 |
fix(IMP-08): Stage 5 R2 — aligner force-drill on sub-id override targets
Codex #1 (Stage 5) reproduced a smoke regression on the actual checkout : when V4 carries the parent exact key (e.g., `04-2`) AND the drag/drop override targets a sub-id (`primary=04-2-sub-1`), the aligner kept the parent at parent granularity and emit `['04-1', '04-2']`, so the override flag failed with `unknown section_id(s) ['04-2-sub-1']`. Fix : `align_sections_to_v4_granularity` gains an optional `override_target_section_ids` keyword. From each canonical `${parent}-sub-N` target it derives the parent id and adds it to a `force_drill_parents` set. Sections in that set are drilled into sub-sections regardless of whether V4 carries the parent exact key. Top-level override targets (no derived parent) do not trigger force-drill, so backward-compat is preserved for parent-granularity overrides. The call site in `run_phase_z2_mvp1` collects sub-ids from `override_section_assignments` and forwards them to the aligner. Generalization (RULE 0) : - Trigger is the override schema (`X-sub-N`), not a specific MDX / section / frame id. Applies to all 32-frame MDX uniformly. - Decision is deterministic on the override target shape, independent of V4 yaml content. - Default (no override) path is unchanged byte-for-byte. Side fixes (forward-only RULE 1 cleanup, no history rewrite) : - `align_sections_to_v4_granularity` docstring rewritten in English (overwrites the Korean docstring committed in |
||
|
|
5191acad85 |
feat(IMP-08): U2 — aligner canonical sub-id + N-R5 decimal alias guard
align_sections_to_v4_granularity now emits canonical sub-section ids
of the form ${section_id}-sub-${ordinal} (e.g., "04-2-sub-1"), matching
the frontend drag/drop schema. Each drilled sub-section populates
heading_number (decimal "2.1" / integer "1" / None for undecorated)
and v4_alias_keys for legacy V4 keys.
N-R5 decimal-only alias guard : v4_alias_keys is populated only when
heading_number matches re.fullmatch(r"\d+\.\d+", ...). Integer-only
H3 headings (e.g., MDX 05's "### 1", "### 2") and bare H3 headings
produce no alias to avoid sibling-parent V4 collisions (RULE 0
generalization — applies to all 32-frame MDX, not MDX 05-specific).
The drill regex is broadened from r"^###\s+(\d+\.\d+)\s+..." to
r"^###\s+(?:(\d+(?:\.\d+)?)\s+)?(.+?)$" so integer-only and bare H3
headings are now recognised as sub-sections; they previously failed
the regex and were silently kept under the parent section.
Tests : 7 new cases (MdxSection default 4-positional callers, V4 exact
passthrough, decimal drill with alias, integer-only no-alias guard,
bare H3 no-alias, no-H3 passthrough, end-to-end aligner -> resolver
round-trip with legacy V4 alias). 15/15 in test_phase_z2_subsection_schema
+ 14 override + 8 fallback baseline = 37/37 PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a422d72c0b |
feat(IMP-08): U1 — schema helper + V4 alias resolver (4 lookup sites)
Adds sub-section schema fields (heading_number / v4_alias_keys /
sub_sections) to MdxSection with defaults so existing 4-positional
constructions remain valid. Introduces _resolve_v4_section_key helper
that resolves a V4 mdx_sections key in exact > alias > None order with
no parent/sibling promotion (axis 7 hybrid lock).
Rewires four runtime V4 lookup sites (lookup_v4_match,
lookup_v4_match_with_fallback, lookup_v4_all_judgments,
lookup_v4_candidates) to accept an optional alias_keys kwarg and go
through the resolver. U1 callers pass empty alias lists so behaviour
is byte-identical to the previous exact-match path; U2 will populate
aliases from MDX heading_number metadata.
Closure callers in run_phase_z2 build section_alias_by_id from
MdxSection.v4_alias_keys and forward into lookup_fn /
candidates_lookup_fn / lookup_v4_all_judgments (Step 7-A trace) and
into _select_template_for_overrides single-section selector.
Step 9 candidate report (post-decision diagnostic) is marked with an
inline English exemption comment per N-R6 — runtime selection goes
through _resolve_v4_section_key, the report path stays a direct
dict-shape lookup to avoid debug_zones schema plumbing.
derive_parent_id now recognises canonical ordinal ids
("03-1-sub-2" -> "03-1") first and keeps the legacy decimal fallback
("04-2.1" -> "04-2") for V4 alias compatibility.
Tests : 8 synthetic cases in tests/test_phase_z2_subsection_schema.py
covering derive_parent_id ordinal/decimal/none and the resolver
exact/alias/no-promote/miss cases. 30/30 PASS combined with the 14
override + 8 fallback baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
52ccb7fc8b |
fix(IMP-06): Stage 4 blocker-fix — render_records + plan-aware traces
Three Codex #13 blockers in a single coherent commit. Blocker 1 (units None hazard) — drop None placeholders from `units` list. Replace with a separate `render_records` layer built AFTER frame_overrides apply. units = canonical renderable list (list[CompositionUnit] only); render_records = canonical per-position view including empty / collision- skipped / cli_override entries. Downstream loops (Step 6 print, frame_ overrides, zones_data/debug_zones, Step 9 application_plan, compute_slide_ status covered loop) no longer need None guards. Blocker 2 (no integration test) — add end-to-end pipeline integration test: `--override-section-assignment top=03-2` on sample 03 MDX produces zones_data[top].source_section_ids = ['03-2'], debug_zones[top].assignment _source = 'cli_override', debug_zones[bottom].v4_template_id = '__empty__' (override_collision whole-skip), step20 filtered_section_ids contains '03-1', and filtered_section_reasons carries a section_assignment_override _uncovered entry. Proves the render path — not only comp_debug — reflects the CLI override. Blocker 3 (Step 9/20 not plan-aware) — surface plan-aware additive fields in both render-path debug_zones/zones_data and Step 9 application_plan units: position, assignment_source, section_assignment_override, replaced_auto_unit, skipped_collided_auto_units, uncovered_section_ids, skipped_reason. compute_slide_status appends Codex #10 Catch O list-shaped filtered_section_reasons entries for override-uncovered sections and folds them into filtered_section_ids so full_coverage is re-evaluated post-override. Exact-id-only collision semantics enforced (Codex #14/#15/#16/#17): S3 and S3-1 are distinct ids; no prefix hierarchy, no parent cascade. Three new section-id invariant tests added (parent-like vs child-like, exact duplicate collision detected, distinct ids coexist). Test : 24 pytest pass (9 helper + 9 case + 3 invariant + 1 case 9b + 1 integration + 1 from v4_fallback baseline) ; smoke 11/11 PASS. Register `integration` pytest marker in pyproject.toml. |
||
|
|
b81e564f65 |
feat(IMP-06): Stage 4 part 1 — replaced_auto_unit field + comment fix
Refs #6 Stage 4 split per Codex #10 acceptance: this commit lands the schema + trace refinements required before the render-path rewiring. The actual units/zones_data/Step 9/Step 20 plan-driven materialization remains in Stage 4 part 2 (follow-up commit) so each commit is reviewable on its own and regression-safe. - _build_position_assignment_plan: add replaced_auto_unit field. Populated only when the explicitly overridden position already held an auto unit AND that auto unit had different source_section_ids than the override. Documents a same-position override replacement as a distinct audit fact, separate from skipped_collided_auto_units which captures cross-position whole-skips per the locked collision policy. - Backfill replaced_auto_unit = None on the empty/collision/auto branches for schema-stable consumers. - Update the override-application comment near the helper invocation so it no longer claims the helper "reorders units"; Stage 4 part 2 will be the commit that wires the plan into the actual render path. - Helper unit tests: assert replaced_auto_unit shape in the collision scenario and add a dedicated case that distinguishes same-sections (template swap via --override-frame -> None) from different-sections same-position replacement (populated, reason="same_position_override_replacement"). No AI, no calculate_fit, no full planner rerun, no frontend, no sample hardcoding. plan_composition() signature preserved. helper remains pure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d596fabde0 |
feat(IMP-06): zone-section assignment override CLI + plan helper (trace-only)
Refs #6 Backend / CLI / composition path only — frontend bridge remains #38. - Add `--override-section-assignment ZONE_ID=section_id[,section_id]` to the Phase Z entry parser. Parse-time hard errors for malformed payloads, empty zone id, empty section list, duplicate zone id, and duplicate section across zones (a section may belong to at most one zone). - Add `_build_position_assignment_plan` helper (pure function, resolved `positions` injected). Builds a per-position assignment plan with the Codex-locked template_id ladder: (1) `--override-frame` exact unit_id wins, (2) exact existing auto unit reuse, (3) single-section direct-executable V4 selector via `lookup_v4_match_with_fallback(..., raw_content=section.raw_content)`, (4) ad-hoc multi-section override without exact auto + without explicit override-frame yields `skipped_reason='ad_hoc_merged_no_template'`. - Lock the collision policy: explicit override wins per position, sections appear in at most one position, overlapping auto units are skipped whole (no split, no cascade, no replan), uncovered sections from the previous same-position auto unit are recorded in `uncovered_section_ids`. - Additive trace fields on each plan entry: `previous_source_section_ids`, `skipped_collided_auto_units`, `uncovered_section_ids`, `v4_selector_trace`, `section_assignment_override`. Top-level `comp_debug["section_assignment_plan"]` + `comp_debug["section_assignment_summary"]` so Step 9 / debug artifacts can derive from a single source of truth. - Wire `run_phase_z2_mvp1(override_section_assignments=...)` after final layout preset resolution: validate ZONE_IDs against active layout positions and validate section_ids against aligned sections (fail-fast). The plan is attached to `comp_debug` for downstream artifacts. Actual `zones_data` / unit-list rewiring is deferred to a follow-up commit so this change stays regression-safe; trace artifacts already surface override intent and collision impact. - Add 9 helper unit tests with fully synthetic MOCK_ ids (no real catalog / no v4_full32_result.yaml): non-conflicting auto retention, collision whole-skip + uncovered tracing, template ladder steps 1/2/4, unit_id naming convention, previous_source_section_ids position history, empty-position case, summary aggregation invariants. No AI, no `calculate_fit`, no full planner rerun, no frontend, no sample hardcoding, no `restructure`/`reject` silent promotion. `plan_composition()` signature is preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
23d1b25144 |
test(IMP-05): tighten Step 9 candidate evidence guard
Refs #5 Replace the hand-built Case 7 payload assertion with a temporary production-source guard. The test now fails if Step 9 stops emitting candidate_evidence, breaks the fallback_chain compat alias, or removes the alias intent comment. This is intentionally temporary because Step 9 application-plan unit assembly is inline. Follow-up IMP-32 should extract a helper and replace this source-string guard with a direct helper test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
21476ae000 |
fix(IMP-05): complete V4 fallback evidence and dedup qualifiers
Refs #5 - Add runtime template_id dedup in lookup_v4_match_with_fallback with first-occurrence reservation; duplicate ranks become audit evidence, not new fallback candidates. - Add Step 9 candidate_evidence as the primary per-unit evidence field while keeping fallback_chain as a compat alias for legacy readers. - Add Step 20 fallback_selection_count and selection_paths derived from comp_debug.v4_fallback_summary with defensive defaults; top-level overall enum unchanged. - Tighten synthetic fallback tests for duplicate handling (rank-1 reject A + rank-2 use_as_is A + rank-3 distinct B → rank-3 wins) and add tests for candidate_evidence + alias equality and Step 20 qualifier presence with defensive defaults. - Verify with pytest (10 passed) and smoke_frame_render --self-check (11/11 partials, IMP-04 F17 calibration intact). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
15c5b9ae00 |
IMP-05 deterministic V4 candidate bridge — pre-render rank-2/3 fallback + trace schema + dedup invariant test
round 55~73 review-loop lock per Codex #11 final + Claude #13 6-axis L1~L9. Scope (deterministic only) : - pre-render rank-2/3 fallback via lookup_v4_match_with_fallback (selector only, no calculate_fit migration, no AI, no full planner rerun, no layout topology change, no abort behavior change) - Step 9 informative candidate_evidence schema (additive) — v4_label / phase_z_status / catalog_registered / filtered_for_direct_execution / route_hint / decision / reason - Step 20 qualifier fields (additive) — fallback_used / fallback_selection_count / selection_paths[] — top-level enum unchanged - restructure / reject candidates preserved as non-direct evidence with route hints (design_reference_only / ai_adaptation_required) — deferred actual handlers IMP-29/IMP-31 - catalog 1:1 invariant test (separate file tests/test_catalog_invariant.py) — fails fast if template_id/frame_id 1:1 mapping ever breaks - 6 behavior tests fully synthetic with MOCK_ prefix (no real catalog IDs, no v4_full32_result.yaml dependency) — monkeypatch get_contract + compute_capacity_fit (selector has no DI, function signature unchanged) Deferred to follow-up issues : - IMP-30 first-render invariant + abort bypass (zero-unit + section status filter) - IMP-29 frontend zone-level override (deterministic only) - IMP-31 AI-assisted frame-aware adaptation Guardrails locked : no calculate_fit / no AI / no frontend / no full rerun / no layout topology / no abort behavior change / no 1-2 sample hardcoding. Tests : 8/8 pass (6 selector behavior + 2 catalog invariant). Smoke regression : 11/11 partials pass (IMP-04 F17 calibration intact). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
85c680f02a |
docs + V4 catalog + samples + Phase Q legacy 보존
전체 26 files (20 추가 + 6 수정), 10507 insertions. Phase Z 문서 : - docs/architecture/PHASE-Z-CHANGE-LOG.md (신설) — axis-by-axis 의사결정 history (newest-on-top). Step 7-A 부터 6 entry 박힘 + 2026-05-08 / 2026-05-08 #2 (compat 매트릭스 폐기 / 6-B 폐기 / F14 표현 정정 / label gate policy 분리). - docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md (수정) — Step 5/6/9 Gap note append (구조 무변, append-only). 6-B 폐기 사실 + Refinement F. - docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md (수정) — snapshot date 2026-05-08 갱신. §3 핵심 missing item 5 (Step 5/6/9 boundary axis breakdown + 폐기 기록). §6 한 줄 갱신 — 다음 axis 후보 A~F. Project root docs : - PLAN.md / PROGRESS.md / README.md (수정) — 토큰 체계 / 폴더 구조 / 설계 문서 / 역할 분리 반영. - IMPROVEMENT-REDESIGN.md (신설) — Phase Z 설계 핵심 문서. - PROCESS_OVERVIEW.html (신설) — 파이프라인 개요 시각. - docs/tasks/* (신설) — Phase Z task 문서. V4 catalog (Phase Z runtime 필수 의존성) : - tests/matching/v4_full32_result.yaml (신설, 4888 줄) — V4 매칭 결과 32 frame × 10 MDX section. lookup_v4_match() / lookup_v4_candidates() 가 본 파일 read. Phase Z runtime 이 *없으면 즉시 abort* — clone 후 즉시 동작 가능 보장. Samples : - samples/mdx_batch/04.mdx (신설) — MDX04 기본 sample. - samples/mdx/04. DX 지연 요인.mdx (신설) — MDX04 원본. Phase Q legacy 보존 (별 axis "Phase Q audit & salvage" 영역) : - src/block_matcher_tfidf.py / catalog_blocks.py / frame_extractor.py / pipeline_v2.py — Phase Q (옛 파이프라인) src 신규 untracked 파일들. Phase Z runtime 와 의존성 0. Phase Q audit axis 에서 검토 예정. - scripts/eval_block_matcher.py / fetch_all_frame_screenshots.py / match_17_units_my_matcher.py / match_mdx_strict.py / match_mdx_to_frames_tfidf.py / ocr_augment_texts.py / run_pipeline_v2.py / previews/ — Phase Q 작업 시 사용한 옛 script. 같이 보존. - run_mdx03_pipeline.py (수정) — Phase Q 진입점 (no flag) + Phase Z 진입점 (--phase-z2 flag) 동시 wrapper. Phase Z 만 사용 시 `python -m src.phase_z2_pipeline samples/mdx_batch/03.mdx <run_id>` 직접 호출. 비-scope : - tests/matching/ (v4_full32_result.yaml 외 ~63MB) — V4 진화 history / reports / DECK / ATTACH. Phase Q audit axis 에서 검토. - tests/pipeline/ (~15MB) — pipeline data. Phase Q audit 영역. - templates/catalog/blocks.yaml — 옛 block catalog. Phase Q audit. - templates/phase_z2/frames/ — 옛 frame partial 위치. Phase Q audit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c42e65fc7e |
Initial commit: Kei Design Agent
콘텐츠를 시각적으로 구조화된 슬라이드 HTML로 변환하는 독립 에이전트. 아키텍처 (4단계 파이프라인): 1. Kei 실장 (Opus) — 콘텐츠 유형 분류 + 블록 배치 2. 디자인 팀장 (Sonnet) — 레이아웃 컨셉 (블록 배치 + 페이지 수) 3. 텍스트 편집자 (Sonnet) — 슬롯 텍스트 정리 (핵심 유지) 4. CSS Grid 렌더러 — HTML 조립 블록 템플릿 7종: comparison, card-grid, relationship, process, quote-block, conclusion-bar, comparison-table 기술 스택: FastAPI + Anthropic API + Jinja2 + CSS Grid Pretendard Variable 한국어 폰트 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |