kmlee1 and Claude Opus 4.7
943957562f
feat( #90 ): IMP-56 u20 BottomActions wiring to /api/connect + /api/export (replace placeholder toasts + standalone HTML download + cel mirror connect; pure builders exported for vitest)
...
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 20s
Stage 2 final unit for Step 22 (user edit + export). u20 wires the previously
placeholder bottom-action footer to the u18 /api/connect and u19 /api/export
middlewares living in Front/vite.config.ts:
- BottomActions.tsx
• drops the dead `serializeSlidePlan` import (TS2305 blocker since u14;
project-wide `tsc --noEmit` now exits 0)
• exports three pure builders for vitest (no jsdom / RTL devDep needed):
buildConnectRequest(run_id, slug) -> POST /api/connect {run_id, slug}
buildExportRequest(run_id) -> POST /api/export {run_id}
buildDownloadFilename(run_id) -> "<run_id>.html"
• handleExport: POST -> blob -> a[download] click chain; toast on
success / failure / network error.
• handleConnect: derives slug via deriveUserOverridesKey(uploadedFile.name)
and PUTs to u18 cel mirror; reports assets_copied count.
• both buttons disable when runMeta is null so the UI cannot fire
requests with an undefined run_id.
- Home.tsx
• mounts <BottomActions/> in the footer with
{slidePlan, runMeta, uploadedFile, isLoading, onGenerate}.
• removes 2 of 3 placeholder `toast.info('… 준비 중입니다.')` buttons
(LeftMdxPanel MDX-edit placeholder remains — out of u20 scope).
• adds handleTextEdit (u15 wire to text_overrides axis) and
handleStructureEdit (u15 wire to structure_overrides axis) to satisfy
the SlideCanvas props introduced earlier in the u-series.
- imp90_bottom_actions.test.ts (new)
• 11 vitest specs locking the builder URL + JSON shape against u18/u19
middleware contracts. Verified 11/11 pass.
Stage 4 verification (all PASS):
• u20 vitest: 11/11
• u18/u19 endpoint vitest: 31/31
• npx tsc --noEmit: exit 0 (carry-forward TS2305 resolved)
• backend pytest (u1~u9 + u17 print mode, 9 files): 185/185
Out of scope:
• LeftMdxPanel.tsx:333 MDX-edit placeholder toast (separate unit)
• #1 / #72 / #74 / #79 / #80 / #81 / #93 closed dependencies (no re-impl)
• AI-generated HTML structure (Phase Z regression guard)
• frame swap via structure_overrides (locked to slot_order + hidden_slots)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-26 02:31:38 +09:00
kmlee1 and Claude Opus 4.7
4e281a20d8
feat( #93 ): IMP-55 u1~u12 frontend manual section swap detection (manual_section_assignment bool axis + drag-only marker gate + dual-axis persistence + backend manual-true gate)
...
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 9s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-25 08:27:09 +09:00
kmlee1 and Claude Opus 4.7
9062931863
feat( #74 ): IMP-45 u1~u8 slide-level CSS override (frontmatter slide_overrides.css + --override-slide-css/--slide-css-file + idempotent Step 13 injector)
...
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 22s
u1 KNOWN_AXES tuple gains slide_css entry in src/user_overrides_io.py
(snake_case parity with image_overrides); round-trip test extends
to 6 axes.
u2 src/mdx_normalizer.py surfaces nested slide_overrides.css from the
MDX frontmatter into the normalize_mdx_content return dict; absent
key -> {}, non-string css drops. 4 unit cases in tests/test_mdx_normalizer.py
(present / absent / non-string / title-only).
u3 src/slide_css_injector.py NEW (88 lines) mirrors the
inject_image_overrides_style contract from src/image_id_stamper.py:
marker pair <!--IMP45-SLIDE-CSS:OPEN--> / <!--IMP45-SLIDE-CSS:CLOSE-->,
idempotent re-injection, </head> > <body> > document-start three-tier
fallback, empty/None -> unchanged. 8 fixtures in
tests/test_slide_css_injector.py mirror test_image_id_stamper.py.
u4 run_phase_z2_mvp1 accepts override_slide_css: Optional[str] = None;
None -> frontmatter slide_overrides.css fallback. Step 13 calls
inject_slide_css after image override injection and before the
final.html disk write, so CLI/CI/regression renders observe the same
backend artifact.
u5 argparse adds mutually-exclusive --override-slide-css TEXT (inline
CSS, <style> wrapper optional) and --slide-css-file PATH (UTF-8 read,
fail-closed sys.exit(2) on missing path / decode error / both flags
present). Resolved string is forwarded as override_slide_css kwarg.
6 cases in tests/test_phase_z2_cli_overrides.py (inline / file / both
/ missing / non-utf8 / neither).
u6 samples/mdx_batch/04.mdx frontmatter gains slide_overrides.css
block (verbatim of the former MDX04_DEFAULT_OVERRIDE_CSS constant,
no sample/frame gate). Subprocess smoke in
tests/test_phase_z2_slide_css_smoke.py verifies the marker pair and
CSS substring land in final.html.
u7 Front/client removes the sample/frame-gated frontend-only injection:
Home.tsx drops the MDX04_DEFAULT_OVERRIDE_CSS constant and the
sample==="04"+frame==="process_product_two_way" branch (-28 lines);
SlideCanvas.tsx drops the iframe contentDocument.head injection of
that prop (-14 lines). Live preview now reads backend final.html only.
u8 tests/regression/fixtures/89a_pre_baseline_sha.json 04.mdx entry
resyncs to the live SHA ddb6bf2f... / 28042 bytes (overwrites the
earlier 5-byte-drift d02c76fd... / 28047). Other entries untouched.
Note: 01.mdx baseline drift (ad6f16a3... / 29089 -> live f26a7fac...
/ 29084) predates this branch and is split to a follow-up issue per
the closed-issue fresh validation rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-25 03:26:03 +09:00
kmlee1 and Claude Opus 4.7
e0c39f1bc1
feat( #73 ): IMP-44 u1~u5 layout override unknown-key guard + frontend zone_geometries validation
...
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 23s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-24 12:12:24 +09:00
kmlee1 and Claude Opus 4.7
5deeb97cf6
feat( #71 ): IMP-42 u1~u5 silent fail chain diagnostics (assert + invalid-char detector + DIAG log)
...
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 24s
Stage 4 binding scope — diagnostic-only, fail-loud, sample-agnostic
(RULE 0 / AI-isolation contract). No production behavior change beyond
fail-loud raises on previously-silent failure classes.
u1 src/phase_z2_pipeline.py:2747-2772 — render_slide precondition assert
(template_id non-empty str + slot_payload dict), placed after the
`__empty__` short-circuit at 2740 to preserve empty-zone grid behavior.
u2 src/phase_z2_pipeline.py:2681-2710 — _scan_rendered_html_for_invalid_path_chars
helper covering src / href / url(...) values for backslash, &, '.
Invoked on partial render (2778) and slide_base assembly (2798).
u3 src/phase_z2_pipeline.py:2638-2676,2733,5509 — _emit_diag_zones_shape
shape-only [DIAG] JSON at Step 12 slot_payload emit and Step 13
render_slide entry. No env gate — silence is the bug.
u4 Front/client/src/pages/Home.tsx:388-392 — unconditional [DIAG raw overrides]
console.log on handleGenerate boundary, after flushUserOverrides() and
immediately before runPipeline.
u5 tests/phase_z2/test_phase_z2_diag_smoke_general.py — 32-frame general
smoke driven by load_frame_contracts() registry (not literal MDX 03/04/05),
parametrizes u1/u2/u3 across the full frame_contracts.yaml top-level.
Tests (Stage 4 verification PASS):
- u1 8 passed, u2 14 passed, u3 12 passed, u4 5 passed, u5 97 passed.
- Backend full regression tests/phase_z2/ 499 passed in 110.84s.
- Frontend full regression 182 passed in 1.10s.
Out of scope (separate axes):
- Path normalization / as_posix migration.
- Autoescape policy change.
- build_layout_css refactor (Stage 1 category-error rejection).
- Recovery / auto-fix on detected invalid path.
- MDX content / frame-selection / zone-composition change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-24 08:28:54 +09:00
kmlee1
6f1c7367e0
feat( #79 ): IMP-51 image_overrides axis (u1~u11 backend stamp+CLI+CSS inject + frontend drag/resize+persistence + tests)
2026-05-22 21:54:38 +09:00
kmlee1 and Claude Opus 4.7
9388e25e76
feat( #80 ): IMP-52 user_overrides.json persistence (u1~u10 backend + frontend + tests)
...
4-axis MDX-stem keyed persistence so layout / zone_geometries / zone_sections / frames
survive across `/api/run` sessions. Auto-restore on MDX reopen; CLI > file precedence
on backend pipeline entry; 300ms-debounced PUT flushed before Generate.
u1 src/user_overrides_io.py — load/save/validate_key (MDX-stem regex), 4-axis schema,
miss={}, corrupt warning+{}, atomic tmp+rename, foreign-key preserve.
u2 src/phase_z2_pipeline.py — post-argparse fallback fills only missing axes.
u3 Front/vite.config.ts — GET /api/user-overrides/:key (200 {} on miss, 400 traversal).
u4 Front/vite.config.ts — PUT /api/user-overrides/:key, 4-axis allowlist, partial merge.
u5 Front/client/src/services/userOverridesApi.ts — typed get/save + flushUserOverrides
with 300ms debounce and mutated-axis partial payloads.
u6 Front/client/src/pages/Home.tsx + slidePlanUtils.ts — restore on MDX upload (non-frame
axes immediately, frames remapped post-loadRun unit_id → region.id).
u7 Home.tsx — persist on 4 mutation handlers (section drop, layout select, zone resize,
frame select); zone_sizes and Generate excluded.
u8 tests/test_user_overrides_io.py — round-trip, unknown-key passthrough, missing/corrupt,
invalid keys (26 tests).
u9 tests/test_user_overrides_pipeline_fallback.py — per-axis fill, CLI-wins, no-file noop,
corrupt warning+skip (16 tests).
u10 Home.tsx + user_overrides_write.test.ts — await flushUserOverrides() before runPipeline
in handleGenerate try-block head; source-pattern regression assertions (20 → 22 tests).
Backend pytest 42/42 green. Frontend vitest 113/113 green (endpoint 42 / restore 21 /
service 28 / write 22). HEAD baseline ee97f4f; no spillover to phase_z2 templates /
families / frames / pipeline orchestration outside the IMP-52 surface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-22 11:47:11 +09:00
kmlee1 and Claude Opus 4.7
2ef02f5f18
feat( #76 ): IMP-47B u11 frontend human_review surfacing (hunk-split from IMP-41)
...
- AiRepairStatus interface mirrors backend step20 u8 schema
- formatAiRepairHumanReviewMessage(): pure helper for the three failure axes
(error / coverage_violated / unsupported_kind) — null on success/no-AI
- Home.tsx: toast.error(aiReviewMsg) after run completion
- FramePanel.tsx: reject-click window.confirm guard ("frame 유지 + AI 재구성")
- imp47b_human_review_toast.test.tsx: 6 vitest cases (null/false/3 axes/other)
Verification (frontend node_modules junction from main worktree):
- vitest imp47b_human_review_toast.test.tsx: 6/6 passed
- vitest full suite: 19/19 passed (imp41_application_mode 13 + u11 6, zero regression)
Hunk-split rationale:
- stash@{0} (imp47b-frontend-u11-pre-rebase, captured before IMP-41 merged)
contained inline IMP-41 helpers alongside u11 changes
- HEAD already has IMP-41 helper-based implementation (buildBadgeTitle /
mergeApplicationCandidates from services/applicationMode.ts, f358604 )
- This commit adds ONLY the u11 surface on top of HEAD's IMP-41 baseline
- No IMP-41 hunk regression: buildBadgeTitle / mergeApplicationCandidates /
applicationMode forwarding preserved verbatim
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 00:34:32 +09:00
kmlee1 and Claude Opus 4.7
15ef7c65e9
fix( #75 ): IMP-47A mdx03 frontend execution stabilization (u1~u4)
...
u1: SlideCanvas iframe sandbox += allow-scripts (allow-same-origin preserved)
→ embedded-mode script in slide_base.html now applies html.embedded
→ standalone CSS reset deactivates inside iframe; no clipping
u2: designAgentApi.loadRun merges candidate_evidence + v4_all_judgments
+ v4_candidates via Map<template_id|id|frame_id> dedup,
LABEL_PRIORITY (use_as_is<light_edit<restructure<reject) then
confidence desc, capped TOP_N_FRAMES=6
u3: Home.handleGenerate useCallback deps = [uploadedFile, slidePlan,
userSelection, pendingZones, pendingLayout] (5-tuple, stale-closure fix)
u4: tests/manual/imp47a_e2e.md — mdx03 manual e2e spec (5 axes)
Frontend-only. Backend src/ untouched. No template/catalog edits.
Determinism preserved (no LLM in frontend merge logic).
Baseline: pytest -q tests → 623 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-21 14:56:56 +09:00
kmlee1 and Claude Opus 4.7
0fb168befc
feat(IMP-10): D-1 — filtered_section_reasons UI (read-only)
...
Surface step20_slide_status.json.data.filtered_section_reasons in the
frontend Home header. Verbatim mirror of backend payload — no enum
redefinition, no translation, no auto-classification.
Units:
- u1: FilteredSectionReason interface mirroring src/phase_z2_pipeline.py
:2217-2278 (10 fields incl. override-uncovered source/position variant).
- u2: RunMeta extension + loadRun() mapping with ?? [] back-compat defaults.
- u3: Header badge + <details> disclosure adjacent to existing status
badge; hidden when filtered_section_ids.length === 0; renders all 10
schema fields + filter_reasons[] verbatim.
Scope:
- Frontend-only, read-only. No backend / sync script / Kei·AI panel
changes. Files: Front/client/src/services/designAgentApi.ts (+20),
Front/client/src/pages/Home.tsx (+25).
Refs: gitea issue #10 (IMP-10 D-1 filtered_section_reasons UI)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-17 19:43:13 +09:00
kmlee1 and Claude Opus 4.7
ab2764c8d0
feat(IMP-08): U3 — frontend wire (zoneSections override)
...
Wires the frontend drag/drop zone assignment through to the backend
--override-section-assignment CLI flag.
PipelineOverrides gains an optional zoneSections field
(Record<string, string[]>) carrying canonical ordinal section ids
(e.g., "top": ["04-2-sub-1"]).
Vite middleware /api/run accepts overrides.zoneSections and forwards
each non-empty zone as `--override-section-assignment ZONE=sid[,sid]`.
Empty arrays and non-string sids are filtered to avoid bogus
assignments from a partially-built UI state.
Home.tsx builds the override with a diff-vs-default guard per Codex
Stage 3 R3 B3 fix : createInitialUserSelection seeds zone_sections with
the auto plan, so a literal copy would pollute backend assignment-source
provenance even on a fresh re-render. The diff compares each zone's
section list against sourcePlan.zones[].section_ids and only emits zones
that differ. Toast summary now reports zoneSections=N when forwarded.
Smoke verification : python -m src.phase_z2_pipeline samples/mdx_batch/04.mdx
test_imp08_smoke --override-section-assignment primary=04-2-sub-1 produces
section_assignment_plan with assignment_source=cli_override and
v4_selector_trace.candidates populated via the U1 alias resolver
(04-2-sub-1 -> 04-2.1 V4 entry).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-15 22:36:16 +09:00
kmlee1
0f0d3fa91f
feat(frontend): add Front/ — Vite/React frontend with backend pipeline integration
...
Mirror of design_agent_front/design-agent/ for shipping alongside backend.
Vite plugin (vitePluginPhaseZApi) endpoints :
- POST /api/run — spawn `python -m src.phase_z2_pipeline` with overrides
- GET /api/sample-mdx?mdx=03/04/05 — fixed sample MDX
- GET /frame-preview/{n} — figma preview thumbnails
- GET /data/runs/{run_id}/{path} — pipeline artifacts (final.html, step*.json, ...)
Env toggle forward (보고용) :
PHASE_Z_ALLOW_RESTRUCTURE / PHASE_Z_ALLOW_REJECT / PHASE_Z_MAX_RANK=32
Components :
- LeftMdxPanel (03/04/05 fix list + section tree)
- SlideCanvas (iframe + slideOverrideCss prop for inline CSS inject)
- FramePanel (label priority + confidence sort)
- LayoutPanel
README with mermaid diagrams covering the 5-step demo flow.
node_modules / dist / .manus-logs / .env excluded via .gitignore.
2026-05-14 14:48:42 +09:00