842a46144c
feat( #87 ): IMP-87 u1~u5 empty_shell honesty gate + BLOCKED exit
...
EMPTY_SHELL_NO_CONTENT overall enum + 3-marker detection (frame_template_id="__empty__"
OR label="empty_shell" OR merge_type="empty_shell") routes empty-placeholder-only
slides to BLOCKED CLI exit 1 + red final_status.html, blocking fake PASS reports
(feedback_artifact_status_naming). Coverage accounting split: legacy covered_section_ids
preserved + new content_rendered_section_ids / empty_shell_section_ids. mdx05 Case B
(zero V4 evidence) honestly classified instead of synthesizing fabricated rank-1 reject
frames. IMP-30 u6/u7 stale empty-shell PASS assertions inverted (29 tests). IMP-85 smoke
parametrize: mdx05 removed from exit-0 list + dedicated BLOCKED exit test added (4 tests).
No production behavior change for chain_exhausted Case A; no AI route activation; no
mdx-id hardcoding. 53 targeted + 76 adjacent Phase Z tests PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-23 20:40:54 +09:00
c53722ad0b
feat( #86 ): IMP-86 u1~u5 placeholder zones_data + invariant guard
...
Mapper FitError handler now appends a __empty__ placeholder to zones_data
and a matching debug_zone so the surviving cardinality stays in sync with
the active layout preset's grid rows. A pre-build_layout_css invariant
guard fails fast with preset/positions/count diagnostics if drift recurs.
Per-record telemetry (adapter_needed, mapper_fit_error, provisional) is
exposed on both placeholder records; authoritative slide_status.adapter_
needed_units schema is unchanged.
Closes mdx03 reject override regression: Step 12 AI router now reachable
without heights_px ValueError; default-path behavior unaffected.
u1 — FitError placeholder zones_data + debug_zone (src/phase_z2_pipeline.py)
u2 — pre-build_layout_css invariant guard (src/phase_z2_pipeline.py)
u3 — horizontal-2 normal+placeholder helper unit (test_compute_per_zone_geometry.py)
u4 — mdx03 reject override → Step 12 integration + default regression
u5 — placeholder telemetry surface (adapter_needed/mapper_fit_error/provisional)
Tests:
- u3 helper: 7 passed (0.06s)
- u4+u5 integration: 2 passed (7.87s)
- Phase Z2 + AI fallback regression: 544 passed (66.28s)
- Broader sweep (excl. matching/pipeline heavy): 1066 passed (96.12s)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-23 18:25:14 +09:00
cacc5b30db
feat( #85 ): IMP catalog builder invariant + VP runtime gate (u1~u7)
...
- u1: BuilderMissingError(FitError) — narrow exception aligned with pipeline catch
- u2: load_frame_contracts catalog invariant + VP skip + CatalogInvariantError
- u3a: audit CLI I1~I3 (partial existence / declared builder / registry membership)
- u3b: audit CLI I4 (slot_payload refs vs declared/generated payload keys)
- u4: lookup_v4_candidates VP filter (lookup_v4_all_judgments raw telemetry untouched)
- u5: catalog invariant regression coverage + temp non-VP failure fixtures
- u6: mdx04 VP routing fixture tests (sw_dependency_four_problems excluded from live)
- u7: tests/conftest.py env isolation + mdx03/mdx04/mdx05 subprocess smoke
Targeted 74 PASS (12.31s). Full regression 1063 PASS (87.70s). Audit CLI clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-23 16:56:38 +09:00
d9d338416a
feat( #62 ): IMP-46 cache fingerprint forwarding u1~u4 (router kwarg + step12 forward + 8 scenarios)
2026-05-23 08:53:22 +09:00
f3ef4d917c
feat( #64 ): IMP-35 details_popup_escalation u1~u10 + Stage 3 R7 anchor re-pin
...
Land the production + test surface for the Step 17 cascade POPUP terminal
(DETERMINISTIC -> POPUP -> AI_REPAIR -> USER_OVERRIDE) per Stage 2 plan R2.
u11 (baseline-red invariance gate) was already landed in 7c93031 ahead of
this commit; this commit completes u1~u10 plus the Stage 3 R7 follow-up
anchor re-pin for test_imp17_comment_anchor.py.
Implementation units (Stage 2 R2 contract):
u1 frame_reselect_insufficient failure_type + post-frame remeasure (q4)
- src/phase_z2_failure_router.py, src/phase_z2_pipeline.py
u2 NEXT_ACTION_BY_FAILURE row + impl_status flip
- src/phase_z2_failure_router.py
u3 Router details_popup_escalation MISSING->IMPLEMENTED + executor stub
- src/phase_z2_router.py
u4 step17.py AI split-decision contract (POPUP cascade_stage +
route_for_label + skip_reason); API gated
- src/phase_z2_ai_fallback/step17.py
u5 Step 17 POPUP gate executor; popup_escalation_plan + has_popup marker
- src/phase_z2_pipeline.py, src/phase_z2_ai_fallback/step17.py
u6 Composition popup binding -- yaml strategy -> zone payload
- src/phase_z2_composition.py
u7 Pipeline composer -> render_slide wiring
(popup_html / preview_text / has_popup)
- src/phase_z2_pipeline.py
u8 slide_base.html <details>/<summary> popup wrapper
- templates/phase_z2/slide_base.html
u9 display_strategies.yaml inline_preview + popup metadata
- templates/phase_z2/regions/display_strategies.yaml
u10 MDX preservation invariant: popup=full source / body=summary or subset
(asserted by tests/phase_z2/test_popup_mdx_preservation.py)
u11 (already in 7c93031 ) -- baseline-red invariance gate
Stage 3 R7 follow-up (anchor re-pin, test-only):
- tests/orchestrator_unit/test_imp17_comment_anchor.py
Pre-anchor additions in src/phase_z2_pipeline.py (u1 / u5 / u7) shifted
the restructure/reject route-hint comments 578/579 -> 586/587. Re-pinned
the two guard tests (and docstring re-pin lineage 564 -> 570 -> 578 ->
586). Production code untouched.
Verification (Stage 4 R1):
pytest -q tests/orchestrator_unit/test_imp17_comment_anchor.py
-> 2 passed / 0.02s
pytest -q <10 IMP-35 unit files in tests/phase_z2 + tests/phase_z2_ai_fallback>
-> 136 passed / 15.94s
Baseline-red invariance gate
(tests/test_imp47b_step12_ai_wiring.py +
tests/test_phase_z2_ai_fallback_config.py)
-> 4 failed / 6 passed; FAILED set === IMP35_BASELINE_RED_NODE_IDS
(frozen registry from 7c93031 ). Contract holds.
Codex Stage 4 R1 = YES (independent verify).
Guardrails honored:
- MDX content preservation: popup carries full source, body holds
summary or subset only (CLAUDE.md 자세히보기 원칙;
feedback_phase_z_spacing_direction -- capacity expanded, no margin shrink).
- AI isolation contract: Step 17 POPUP gate is deterministic; AI hook
surface is split-decision contract only, API call gated.
- No hardcoding: escalation thresholds derived from existing overflow
detector outputs; preview_chars deterministic from container px.
- 1 commit = 1 decision unit: u1~u10 land together as the planned
production surface; u11 was deliberately split into 7c93031 as Stage 3
R7 carve-out, and the R7 anchor re-pin rides with this commit because
it is the direct shift consequence of the u1/u5/u7 pre-anchor additions.
- Scope-locked: .claude/settings.json explicitly excluded
(Stage 4 exit report contract).
Out of scope (per Stage 1 + Stage 2):
- AI_REPAIR API activation (post IMP-35 axis).
- IMP-34 zone resize, IMP-36 responsive fit (chain partners,
separate issues).
- Print-time auto-expand JavaScript for <details>.
- Popup escalation in stages other than Step 17.
- Baseline-red body repair (4 frozen failures) -- separate follow-up
issue; u11 only guards the count.
- frame_reselect algorithm changes (entry point only).
- templates/phase_z2/slide_base.html path rename.
source_comment_ids:
Stage 1: claude_stage1_problem_review_imp35, codex_stage1_verification_imp35_yes
Stage 2: Claude #4 R2 plan, Codex #5 R2 YES
Stage 3: Claude #86 (R7 anchor re-pin), Codex #87 YES
Stage 4: Claude #88 R1, Codex #89 R1 YES
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-23 07:36:57 +09:00
7c93031f9b
feat( #64 ): IMP-35 details_popup_escalation u11 baseline-red invariance gate
...
Add a test-only invariance gate that locks the pre-existing four-test red
baseline so IMP-35 cannot silently grow the red surface while in-flight.
u11 does NOT fix the four reds — Stage 2 follow_up_candidates tracks the
actual repair as a separate issue. u1~u10 production work remains in the
worktree and is explicitly out of this commit per Stage 3 R7 carve-out.
Frozen registry (IMP35_BASELINE_RED_NODE_IDS, set semantics):
1. tests/test_imp47b_step12_ai_wiring.py
::test_mixed_units_classified_by_route_and_provisional_flag
2. tests/test_imp47b_step12_ai_wiring.py
::test_reject_provisional_unit_reaches_router_short_circuit
3. tests/test_imp47b_step12_ai_wiring.py
::test_step12_ai_repair_artifact_writes_json_serialisable_records
4. tests/test_phase_z2_ai_fallback_config.py
::test_ai_fallback_master_flag_default_off
Gate semantics (subprocess pytest, set comparison):
- All 4 node ids resolve to collectible pytest items
(rename / delete is caught up front).
- Broader baseline-area sweep across the two registry files yields
EXACTLY 4 FAILED and 0 ERROR, with FAILED set ≡ registry.
- A new red in the baseline area flips count above 4 OR introduces a
FAILED id outside the registry; either branch fails the gate.
- Cross-lock test ensures registry node ids cannot point outside the
declared area-files inventory.
AI isolation contract (feedback_ai_isolation_contract):
Gate body uses stdlib only (subprocess + re + ast). An AST self-verify
test rejects `anthropic` imports and `route_ai_fallback` references in
this file, structurally preventing AI routing inside the gate.
Stage 4 verification (HEAD c1df656 pre-commit):
pytest -q tests/phase_z2/test_imp35_baseline_red_invariance.py
→ 7 passed in 15.26s.
Baseline area sweep
(tests/test_imp47b_step12_ai_wiring.py +
tests/test_phase_z2_ai_fallback_config.py)
→ 4 failed / 6 passed / 0 errors; FAILED set ≡ registry (identity).
pytest --collect-only on the 4 registered node ids → all 4 resolve.
py_compile clean. Codex R1 = YES (independent verify).
Guardrails honored:
- Scope-locked: test-only file; zero production code in this commit.
- 1 commit = 1 decision unit (u11 only).
- No hardcoding: registry = Stage 2 contract frozen tuple, not
sample-specific literal; gate body has zero magic constants.
- AI isolation: stdlib-only gate, AST self-verify locks isolation.
- baseline-red 4 body repair = separate follow-up issue, not u11 scope.
source_comment_ids: Stage 1 problem-review; Stage 2 plan R2 + Codex R2
YES; Stage 3 Claude #30 + Codex #31 R7 YES; Stage 4 Claude #32 + Codex
#33 R1 YES.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-23 04:13:54 +09:00
c1df656312
feat( #65 ): IMP-36 fit/rotation generalization (u1~u8)
...
Generalize Phase Z frame partial responsive fit / rotation to four canonical
F13/F14/F20/F8 family partials. Surface = 13 canonical partials; 19
builder-only contracts remain explicitly out of scope.
u1 test_imp17_comment_anchor: re-pin L570->L578 (restructure+IMP-17),
L571->L579 (IMP-29 -> IMP-47B supersession). Stage 1 red baseline gate.
u2 frame_contracts.yaml: add rotation_eligible (P1) + body_fit_pattern2 (P2)
bool axes on 13 partial-backed contracts. P1 True: F13/F14/F20/F8 (4).
P2 True: F23 + P1_set (5). F29 columns[1].body_parser column_plain ->
column_with_transform (P3 parity).
u3 test_imp36_fit_rotation_generalization (NEW, 166 lines): static
parametrized assertions for P1 metadata + CQ presence, P1 opt-out
absence, P2 --max-body-lines + clamp + cqh, P2 opt-out absence, 19
builder-only exclusion.
u4 three_parallel_requirements (F13): introduce f13b-root container-name +
container-type:size + @container (aspect-ratio<1.5) rotation;
add inline --max-body-lines + body line-height clamp/cqh/calc.
u5 three_persona_benefits (F14): f14b-root P1 + P2 cqh/jinja body fit.
Persona colors (#285b4a/#445a2f/#743002) and circle SVG aspect 1/1
preserved.
u6 dx_sw_necessity_three_perspectives (F20): f20b-root P1 + P2 cqh/jinja
body fit under IMP-49 partial-fidelity lock.
u7 info_management_what_how_when (F8): f8b-root P1 + P2 cqh/jinja body fit.
u8 test_imp36_overflow_chain_self_fire (NEW, 299 lines): Selenium self-fire
harness for F13/F14/F20/F8 at aspect 1.78 vs 1.0. Asserts line-height
changes, font-size invariance across all 4 frames (no per-frame exempt),
grid columns rotate 3 -> 1, OVERFLOW_CASCADE_ORDER remains 4-tuple.
Stage 4 verification (HEAD 6f1c736 pre-commit baseline):
u1 2/2 PASS, u3 33/33 PASS, u8 9/9 PASS (live Chrome).
Regression sweep tests/phase_z2 + tests/orchestrator_unit 335/335 PASS.
font-size mutations introduced: 0.
Pre-existing red (test_imp47b_step12_ai_wiring x3, ai_fallback_master_flag
default_off x1) verified unchanged via stash swap -> not introduced.
Guardrails honored:
- cqh / clamp / container query only (no shared margin/padding/gap shrink).
- font-size invariant under aspect change (P2 mutates line-height +
--max-body-lines only).
- No cross-frame .fNb__ class borrowing (IMP-49 partial-fidelity lock).
- F14 circle SVG aspect 1/1 untouched; persona colors preserved.
- AI isolation: no HTML structure generation; AI calls remain zone-content.
- 1 turn = 1 step; commit excludes .claude/settings.json and all
out-of-scope untracked worktree per Stage 4 binding contract.
source_comment_ids: Stage 1 #13/#14; Stage 2 #21/#22; Stage 3 #4 + Codex #4
YES; Stage 4 Claude #1 + Codex #3 PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-23 01:18:20 +09:00
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
bd8bcf748b
feat( #81 ): IMP-54 frontend zone editing UI (u1~u4 edit-mode body-drag + emerald highlight + pure drag-math helper + vitest)
...
u1: 4 perimeter edge strips (~8px) + top-left grip chip at zone wrapper
provide an edit-mode pointer-event surface (zIndex 25) so wrapper-level
handleZoneMouseDown becomes reachable in edit mode. Wrapper stays
pointerEvents:none and iframe stays pointerEvents:auto to preserve
text-edit reachability (A8 guardrail). Resize handles (z-30) win in
overlap regions. Iframe pointer-events temporarily forced none during
drag to prevent mouseup leak.
u2: Edit-mode isSelected branch reuses selectedZoneId with emerald visual
(border-emerald-500 / bg-emerald-500/10) distinct from pendingLayout
blue, decorative-only (pointerEvents:none inherits via wrapper rules).
u3: Pure drag math extracted to slideCanvasDragMath.ts — DRAG_THRESHOLD_PX,
crossedDragThreshold(dx, dy) strict Math.hypot > 5, and clampZoneMove
pixel→fraction conversion with x∈[0, 1-w] / y∈[0, 1-h] clamp.
Resize math (makeResizeHandler) untouched.
u4: Vitest coverage (12 tests, 3 describe blocks) on the pure helper:
threshold strict boundary at (3,4)/(5,0)/(0,5), above-threshold,
negative-symmetric, clamp negative→0, max-edge → 1-w / 1-h, per-axis
independence, non-square 500×250 slide-body, return-shape {x,y} only.
Stage 4 verify: pnpm exec vitest run client/src/components/slideCanvasDragMath.test.ts → 12/12 PASS.
Scope: edit-mode UX only. No HTML text modification, no automatic frame swap, no MDX touched.
Depends on: #9 IMP-09 (--override-zone-geometry backend wire), #80 IMP-52 (user_overrides.json zone_geometries persistence).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-22 13:35:34 +09:00
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
ee97f4fc78
feat( #77 ): IMP-48 composition planner re-split on all-reject (u1~u9)
...
Add resplit_all_reject_merges() helper in phase_z2_composition.py that
detects parent_merged / parent_merged_inferred units with label=reject
and rebuilds them as per-section single units using each section's own
rank-1 V4 evidence (no frame swap, MDX raw_content preserved).
Pipeline hook fires once after Step 6 settling chain (u12/u4/empty-shell)
and section_assignment_plan resolution, before Step 6 artifact write.
Guards: beneficial-split rule (>=1 non-reject), coverage equality, layout
cap (>4 abort), max_retry=1, section_assignment_override short-circuit.
Audit: comp_debug["imp48_resplit"] additive payload (applied, split_units,
skipped_units, post_split_unit_count, post_split_layout_preset);
selection_path="resplit_from_merge" telemetry on rebuilt singles;
layout_preset re-derived via select_layout_preset(new_units).
Tests: 39/39 PASS (composition u1~u6: 14 cases; pipeline u7~u9: 25 cases).
Scoped regression 720/6 with 6 failures isolated as pre-existing on
baseline 79f9ea5 (independent of IMP-48). mdx03 golden lock preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-22 05:00:07 +09:00
79f9ea5c92
feat( #78 ): IMP-49 dx_sw_necessity partial Figma provenance fix (u1~u3)
...
Replace eyeballed PROMOTED green hex (#296B55, #123328 ) with verbatim
upstream values from figma_to_html_agent/blocks/1171281198/index.html:
- border + check mark: #1d4d3e (upstream :208 -webkit-text-stroke)
- header gradient: rgb(15, 50, 30) / rgb(60, 52, 34) (upstream :54, :64)
Document .f20b__* as authoring-ordinal namespace (NOT Figma frame_id
1171281198); structural link via data-frame-id attribute. No selector
rename, no catalog edit.
Add focused regression test (tests/test_imp49_partial_figma_provenance.py)
extracting <style>-block hex/rgb/rgba literals and asserting non-whitelisted
literals exist byte-identically in upstream source. Whitelist limited to
neutrals (#fff, #1a1a1a) + shared zone-title token (#000 , #883700 ,
rgba(50,44,30,0.4)).
Scope: dx_sw_necessity_three_perspectives.html only. 19 missing partials,
.fNb__ rename, full 32-contract audit deferred to follow-up axes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-22 02:49:43 +09:00
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
1186ad8ae2
feat( #76 ): IMP-47B reject-as-AI-adaptation activation (u1~u13 backend + tests)
...
- u1~u9: AI fallback infrastructure (router/prompts/schema/validator) + Step 12 hook
- u10: e2e reject chain (writes final.html with AI-repaired slot, full coverage)
- u11: frontend wiring deferred to follow-up commit (split from IMP-41 hunks)
- u12: coverage_invariant guard
- u13: cache save gate (visual_check PASS + user_approved/auto_cache) — Codex #22 verified
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-22 00:19:10 +09:00
f358604fb3
feat( #70 ): IMP-41 application_mode forwarding to FramePanel V4 badge tooltip (u1~u5)
...
Forward backend Step 9 `unit.application_candidates[]` (application_mode /
auto_applicable / delegated_to) onto FrameCandidate and surface the
application_mode as a Korean consequence phrase in the FramePanel V4-label
inline badge tooltip. Deterministic frontend-only refactor; no LLM call,
no V4-label color change, no outer composedTitle change.
u1: types/designAgent.ts — add optional applicationMode / autoApplicable /
delegatedTo on FrameCandidate (legacy fixtures keep undefined).
u2: services/applicationMode.ts (new) — pure helper exporting
ApplicationMode union, APPLICATION_MODE_TOOLTIP_KR (keyed by backend
mode VALUE, NOT V4 label), buildBadgeTitle, mergeApplicationCandidates.
u3: tests/imp41_application_mode.test.ts (new) — 13 Vitest cases pinning
composite output per mode, undefined/unknown→legacy fallback, merge by
template_id, skip missing/empty/non-string keys, first-wins on dupes,
empty/null/non-array input.
u4: services/designAgentApi.ts — bridge consumes mergeApplicationCandidates
and forwards three fields onto FrameCandidate while preserving
LABEL_PRIORITY sort and TOP_N_FRAMES slicing.
u5: components/FramePanel.tsx — V4-label badge `title` now calls
`buildBadgeTitle(candidate.label, candidate.applicationMode)`;
badge color className map preserved verbatim; outer composedTitle
untouched.
Scope-qualified verification (5 files, IMP-41 axis only):
- Vitest: client/tests/imp41_application_mode.test.ts — 13/13 PASS.
- Diff↔Plan parity: 5 files match Stage 2 plan, no scope creep.
- AI-isolation contract honored: tooltip values originate from backend
enum; no frontend re-derivation from V4 label.
- No spacing/font shrink; clipping resolution stays at layout/zone/frame
layer (feedback_phase_z_spacing_direction).
Pre-existing unrelated diagnostics (BottomActions.tsx,
imp47b_human_review_toast.test.tsx) remain open on their own axes and are
not gated by this commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-22 00:17:32 +09:00
90503cadd6
feat( #67 ): IMP-38 V4 max_rank policy formalization (u1~u3, 4 round consensus)
...
- u1: separate templates/phase_z2/catalog/v4_fallback_policy.yaml + load_v4_fallback_policy() loader
(catalog pollution prevention — Codex #1 correction)
- u2: dynamic effective max_rank in lookup_v4_match_with_fallback (3-variable ceiling min,
Codex #2 correction: min(configured, len(judgments_full32))) + 3-tier usable predicate
(status + catalog + optional capacity) + trace 8 fields (requested/default/configured_extended/
judgments_count/effective_extended_ceiling/effective_max_rank/usable_count/policy_applied)
- u3: 2 production call site cleanup (max_rank=3 removed, HEAD baseline) + tracked
Front/vite.config.ts PHASE_Z_MAX_RANK env retired + 4 regression scenarios
verified: 32 passed (IMP-38 focused scope) — IMP-05 L4 dedup / L2 schema preserved,
IMP-30 allow_provisional byte-identical, caller_override backward compat (tests)
Stage cycle (#67 , 7 round Claude + 5 round Codex):
- Stage 1: Claude #1 -> Codex #1 YES + 5 corrections
- Stage 2 r1+r2: Claude #2-#4 -> Codex #2 Q2 -> Codex #3 YES (4 round consensus LOCK 23195)
- Stage 3 U1+U2+U3: Claude #5-#9 -> Codex #6 NO 4to3 correction -> Codex #7 YES -> Codex #8 YES
- Stage 4: Claude #11 -> Codex #9 (anchor attribution nuance) -> Codex #10 readiness -> Codex #11
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-21 22:14:05 +09:00
dceb10129f
feat( #63 ): IMP-34 R1 donor capacity measured bound (u1+u2)
...
Bound donor capacity in plan_zone_ratio_retry by min(static_slack,
max(0, clientHeight-scrollHeight)) when both Step 14 measured fields
are present; fall back to static contract slack when absent. Prevents
the donor from being over-allocated when full-but-not-overflowing,
avoiding a wasted Selenium rerender before cascade falls to
cross_zone_redistribute.
- src/phase_z2_retry.py: planner block L122-157 only; donor filter
(L107-112), slack<=0 gate, base_plan, greedy aggregation untouched.
Adds measured_empty_px + slack_bound_source telemetry to
donor_candidates_considered (additive only).
- tests/phase_z2/test_phase_z2_retry_measured_bound.py: 5-axis
regression (static_fallback / measured<static / measured>=static /
measured==0 excludes / filter+bool guard).
Guardrails honored: V4 rank-1 frame lock preserved, no frame_swap,
no spacing/padding/gap/line-height/font shrink, no content drop,
no MDX 03/04/05 branching, no Step 14 schema mutation. Static
fallback idempotent when measured fields absent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-21 21:37:41 +09:00
a06dd3d4b0
feat( #42 ): IMP-04b catalog extension to 32 frames (u1~u24)
...
Extends frame_contracts.yaml from 11 to 32 contracts to match V4 evidence
(tests/matching/v4_full32_result.yaml unique template_ids), closing the
IMP-04b gap surfaced in IMP-04 (#4 ) Track A milestone.
Scope (Stage 2 24-unit plan):
- u3/u4: WIP partial absorb — app_sw_package_vs_solution (F23),
pre_construction_model_info_stacked (F9). Both promoted from
_WIP_FILES.md to frame_contracts.yaml. WIP allowlist now empty.
- u5~u11: Track A 7 frames (index.html present, contract missing).
- u12~u23: Track B 12 frames (visual_pending: true; family partial
authoring deferred — contract-first per Stage 2 plan).
- u24: BT closure gate. Adds
test_imp04b_closure_gate_v4_coverage_and_wip_empty (catalog ↔ V4
set-equal + WIP==0) and test_vp_exempt_keys_are_contracted_and_disk_absent
(vp ∩ disk == ∅). Relaxes test_contracts_set_equals_disk_families_minus_wip
to (disk - wip) ∪ vp. 32 derived from V4 evidence YAML (no hardcoding).
Closure facts (locked):
contracts = 32, v4_unique = 32, missing = [], extra = [],
wip_count = 0, vp_count = 19, vp ∩ disk = [].
Guardrails honored:
- No calculate_fit migration.
- No AI/Kei API call in per-frame work.
- No 1-2 sample hardcoding (Codex #7 generalization guardrail).
- No production refactor for tests (IMP-32 owns helper extract).
- figma_to_html / V4 / Phase Z 3-layer separation preserved.
- 1 commit = 1 IMP-04b decision unit (bundled u1~u24 per Stage 2
plan; CAT+WIP atomicity for u3/u4 preserved).
Tests: tests/test_family_contract_baseline.py 4/4 PASS.
Cross-ref: IMP-04 (#4 ), IMP-29 (#38 ), IMP-30 (#39 ), IMP-31 (#40 ),
IMP-32 (#41 ), IMP-33 (#61 ), IMP-47A (#75 ).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-21 19:39:16 +09:00
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
c864fe0479
feat( #61 ): IMP-33 AI fallback scaffolding (u1~u11, flag default OFF)
...
Frame-aware AI fallback module scaffolded under src/phase_z2_ai_fallback/
with master flag ai_fallback_enabled=False; normal-path AI call count
remains 0. AI output constrained to builder_options_patch /
partial_overrides / slot_mapping_proposal; MDX / frame_id / raw HTML /
raw CSS mutations rejected at schema layer. IMP-46 cache gate (cache.py)
raises AiFallbackCacheGateError unless visual_check_passed AND
user_approved. Step 12 wires AI repair after IMP-30 provisional payload
only; Step 17 stays blocked behind IMP-34 / IMP-35 prerequisites.
AST isolation guard forbids fallback package from importing Phase Q /
Kei / pipeline runtime symbols. Docs IMP-17 / IMP-31 bound to runtime
module surface via 11-row structural test pin (test_docs_sync.py) so
drift fails CI.
Tests: 116 fallback / 161 phase_z2 regression / 526 scoped full sweep
all passing. Existing pre-IMP-33 fixture issue in scripts/test_phase_t_*
remains untouched (out of scope).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-21 12:46:49 +09:00
c412f1ea75
refactor( #41 ): IMP-32 Step 9 application_plan helper extraction (u1~u5)
...
Pure refactor — extract inline Step 9 per-unit application_plan dict
assembly into module-level private helpers for testability. Replaces
IMP-05 Case 7 inspect.getsource() literal guard with direct helper-call
shape test. Behavior preserved: key set/order, candidate_evidence +
fallback_chain compat alias identity, IMP-06 additive plan fields,
IMP-11 D-2 markers (single _contract = get_contract(c.template_id)
bind + catalog_registered + min_height_px chain).
- u1 _application_candidates_for_unit(unit) at src/phase_z2_pipeline.py
:2829-2853 — APPLICATION_MODE_BY_V4_LABEL mapping (pure extraction)
- u2 _v4_all_judgments_for_unit(v4_all_for_unit) at :2855-2882 —
IMP-11 D-2 chain preserved literally
- u3 _build_application_plan_unit(unit, zone_plan, selection_trace,
plan_record, v4_all_for_unit, layout_preset, layout_candidates_list)
at :2885-2995 — byte-identical per-unit dict (key set + order +
value identity), candidate_evidence / fallback_chain compat alias,
v4_candidates list, v4_all_judgments, application_candidates, IMP-06
additive plan fields
- u4 Step 9 inline loop body at :4620-4658 replaced with helper call;
per-index/per-id lookups (zone_region_plans[i], v4_fallback_traces
.get(...), plan_record_by_unit_id.get(id(unit)), section_alias_by_id,
lookup_v4_all_judgments(...)) stay at call-site
- u5 tests/test_phase_z2_v4_fallback.py Case 7 rewritten to
test_build_application_plan_unit_emits_candidate_evidence_and_alias
— direct helper call with SimpleNamespace duck-typed input; asserts
candidate_evidence list identity (is), fallback_chain compat-alias
identity (is), key order (candidate_evidence before fallback_chain),
and compat-alias comment scoped to inspect.getsource(_build_
application_plan_unit)
Verification: targeted 22 passed, full pytest 408 passed (0 fail/skip),
smoke 11/11 PASS (2 pre-existing baseline SKIPs unchanged).
Cross-ref: IMP-05 (#5 ) commit 23d1b25 Case 7 temporary source guard
(replaced) / Codex #20 + #21 / IMP-11 D-2 marker preserved.
2026-05-21 03:17:27 +09:00
182aa7c47f
docs( #40 ): IMP-31 gate audit + activation reference cross-link
...
- u1: IMP-17-CARVE-OUT.md anchor cite :564 -> :570/:572/:575/:580/:664
- u2: new IMP-31-GATE-AUDIT.md (3-cond AND gate state + 8 issue-body axes)
- u3: backlog row + status-board section 5 cross-ref to audit doc (no verdict dup)
doc-only. no src/ templates/ tests/ touched. src/phase_z2_ai_fallback/ not created.
2026-05-21 01:59:03 +09:00
1efbf672bd
feat( #39 ): IMP-30 first-render invariant + abort bypass (2 paths)
...
Restore first-render invariant: final.html + Step 20 slide_status MUST be
written for every input where Step 0~5 succeed. Two abort paths replaced
with provisional/empty-shell synthesis; MDX content preserved, AI-free.
- u1 V4Match.provisional + lookup_v4_match_with_fallback(allow_provisional)
chain_exhausted -> synthesize rank-1 provisional (opt-in, default-off)
- u2 CompositionUnit.provisional propagation (single / parent_merged /
parent_merged_inferred constructors)
- u3 select_composition_units(allow_provisional_fill=True) last-resort
fill + _candidate_state="selected_provisional"
- u4 pipeline.py path-(a) abort guard replaced with provisional retry +
terminal __empty__ shell (no sys.exit(1))
- u5 zones_data.provisional -> slide_base.html zone--provisional class +
data-provisional + needs-adaptation badge (template-only)
- u6 compute_slide_status additive provisional_first_render_count/_units
(overall enum unchanged per IMP-05 Codex #10 D4)
- u7 regression: tests/test_phase_z2_imp30_first_render.py (28 tests) +
tests/test_phase_z2_v4_fallback.py (+5 cases)
Guardrails verified: MVP1_ALLOWED_STATUSES unchanged, no calculate_fit,
no LLM in fallback path, no MDX 03/04/05 hardcoding.
Anchor sync (Rule 13): tests/orchestrator_unit/test_imp17_comment_anchor.py
re-pinned 564/565 -> 570/571 to track V4Match.provisional shift at
src/phase_z2_pipeline.py:179-184.
Cross-ref: IMP-05 (#5 ) §5 defer + Codex #2 first-render invariant.
2026-05-21 00:40:58 +09:00
b4872ba6ce
feat( #38 ): IMP-29 frontend zone-level evidence bridge (candidate_evidence reader + types + UI)
2026-05-20 21:53:47 +09:00
265d70ed91
refactor( #28 ): IMP-28 L4 _parse_json dedup (4 modules -> src/json_utils)
...
Consolidate duplicate _parse_json helpers from content_editor.py /
design_director.py / kei_client.py (fuller form) and pipeline.py (simple form)
into shared src/json_utils.parse_json (strict superset). All 18 call-sites
preserved via `parse_json as _parse_json` alias import; no behavior change.
- src/json_utils.py (new): shared helper, fenced/plain-fence/bare-brace patterns
+ list-prefix cleanup fallback.
- tests/test_json_utils.py (new): 9 unit tests pinning parser semantics.
- src/content_editor.py / design_director.py: remove local helper +
unused `import json` / `import re`.
- src/kei_client.py / pipeline.py: remove local helper; `json` / `re` retained
(used elsewhere).
Targeted tests 9 passed; full pytest 374 passed (3 pre-existing scripts/
collection errors reproduce on baseline 909bf75 , IMP-28 unrelated).
2026-05-20 20:44:19 +09:00
909bf75edc
refactor( #27 ): IMP-27 K5 catalog loader + _get_block_by_id cleanup
...
Consolidate three duplicated catalog readers and two _get_block_by_id
implementations behind a single shared module (src/catalog.py) that owns
file-read + mtime cache. All caller signatures and return contracts
remain byte-identical.
Units:
- u1 NEW src/catalog.py (76 lines): load_root_catalog / load_blocks /
get_block_by_id / get_catalog_mtime as the sole file-read +
mtime-cache owner.
- u2 src/block_reference.py: _load_catalog delegates to load_blocks
(list[dict] preserved); _get_block_by_id (no-arg) delegates to
catalog.get_block_by_id. Module-level _catalog_cache removed.
- u3 src/block_selector.py: load_catalog delegates to load_root_catalog
(root dict preserved); _get_block_by_id (catalog-injected sig
preserved) delegates to catalog.get_block_by_id. Module-level
_catalog_cache / _catalog_mtime / CATALOG_PATH removed.
- u4 src/renderer.py: _load_catalog_map and
_load_catalog_map_with_variants consume catalog.load_blocks; renderer
projection caches kept local but keyed via
catalog.get_catalog_mtime(). Per-projection invalidation keys
(_CATALOG_MAP_MTIME / _CATALOG_VARIANT_MAP_MTIME) introduced. import
yaml, CATALOG_PATH, legacy _CATALOG_MTIME removed.
- tests NEW tests/test_catalog_shared_loader.py (421 lines, 23 cases):
shared loader + 3 wrappers covering single file-read, contract
preservation, signature preservation, shared cache, private state
absence, mtime invalidation propagation to renderer projections.
Verification:
- pytest tests/test_catalog_shared_loader.py -v: 23/23 PASS in 0.13s.
- pytest tests/ -q --ignore=tests/matching: 365/365 PASS in 38.10s.
- src/fit_verifier.py, src/space_allocator.py, src/pipeline.py and
templates/catalog.yaml unchanged (git diff empty).
Out of scope:
- catalog.yaml schema/path unchanged.
- Catalog direct-read call sites in fit_verifier / space_allocator /
pipeline left for a separate follow-up axis.
- Phase Z 22-step runtime, frame_selection, light_edit/restructure
flows untouched.
Refs: IMP-27 (gitea #27 ), INSIGHT-MAP §5 K5, PHASE-Q-AUDIT §2.10
2026-05-20 19:31:26 +09:00
2896bb691c
docs( #26 ): IMP-26 J3 status pending->deferred + dual-precondition trigger
...
BACKLOG line 93 + INSIGHT-MAP line 150 (verbatim mirror per anchor sync
rule). Trigger axis now requires both Phase R' archive trigger AND
§2.1/§2.2 SoT signature unification to keep guardrail = code-removal-only.
No source files touched.
2026-05-20 18:27:55 +09:00
a71355e005
docs( #25 ): PHASE-Q-AUDIT §1 lens B-1 row candidate-file 칸 정정
2026-05-20 17:52:29 +09:00
b1897c01bc
docs( #24 ): PHASE-Q-AUDIT §1 lens A-2 row candidate-file 칸 정정
...
block_reference.py, block_selector.py 를 간접 reference (catalog 로딩 /
block 검색 패턴) 로 재분류. A-2 main = frame_contracts.yaml + frame_partials
신규 구축 (Phase Q catalog schema ≠ Phase Z) 임을 명시. §2.10 K6 + §3-A
1242 binding SoT 와 정합. IMP-22 / IMP-23 A-3/A-4 lock 패턴 추종.
2026-05-20 17:19:24 +09:00
5d23b747ff
fix(orchestrator): P5b first-line agent header strict + supplement throttle
...
Bug discovered during #24 IMP-24 K6 Stage 2 (2026-05-20):
- Codex r1, r2, r3 started with '=== IMPLEMENTATION_UNITS ===' on first line
(not '[Codex #N] ...'), so detect_agent (P0-1 strict, first-line only)
returned None.
- For non-audit issues, the P5 supplement guard was audit-only gated → silent
loop until Codex r4 happened to use correct format. 4 rounds wasted.
Verified that #21 Stage 4 had the same latent silent loop pattern
('## [Codex #1 ]' first line) — orchestrator looped through ~10 Claude rounds
before random recovery. P5b fix addresses this long-standing bug.
Patch (defensive parser-contract hardening; does not assume single root cause):
1. RULES global gets explicit "FIRST non-empty line MUST be [Claude #N] /
[Codex #N]" rule that OVERRIDES any stage-specific "body MUST contain"
constraint.
2. COMPACT_PLAN_RULE wording clarified: "body" begins AFTER the first-line
agent header. The 'body MUST contain ONLY' set no longer accidentally
permits '=== IMPLEMENTATION_UNITS ===' on line 1.
3. is_codex None supplement guard:
- audit-only gate REMOVED → fires for all issues (#24 latent loop fixed)
- Throttle: max 2 supplements per stage; on 3rd violation, orchestrator
hard-stops the issue with explicit "user action required" message
and exits run_stage cleanly
- Supplement message names both Claude AND Codex (Claude's first-line
violation also breaks downstream via Codex mimicry)
- Body-head 80 chars logged on detection failure (debugging aid)
4. Regression tests (+5 cases in test_orchestrator_core.py):
- TestDetectAgent: '=== IMPLEMENTATION_UNITS ===' first line → None
- TestDetectAgent: [Codex #N] first line + units after → 'codex' OK
- TestDetectAgent: '## ', '📌 **', '**' prefix all → None
- TestRulesAndCompactPlanFirstLineContract: RULES wording has FIRST/OVERRIDES
- TestRulesAndCompactPlanFirstLineContract: COMPACT_PLAN_RULE has carve-out
Cosmetic side effect (accepted): Claude's '📌 **[Claude #N] ...**' or
'## [Codex #N] ...' decoration prefixes will fail detect_agent. Agents
will drop decorations from line 1; line 2+ can still use them.
Out of scope (NOT included to keep regression risk low):
- detect_agent function logic UNCHANGED (P0-1 strict preserved)
- consensus parser UNCHANGED
- stage loop structure UNCHANGED
- git/Gitea retrieval logic UNCHANGED
- audit-only mode P4/P4a guards UNCHANGED
- pre-post comment validation (future axis, larger refactor)
Total: 131/131 pytest pass (126 prior + 5 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 17:01:24 +09:00
447e702520
docs( #23 ): PHASE-Q-AUDIT §1 lens A-3/A-4 html_generator 칸 정정
...
§1 lens A-3 / A-4 candidate-file column에서 bare html_generator.py
token 제거. §2.9 J5 (L979–981) SoT가 두 행 모두 부정확으로 lock —
A-3는 html_generator에 selenium import 부재, A-4는 slide-base 호출
부재 (area HTML만 반환). IMP-22 (2ace54b )의 renderer.py 표기 보존,
IMP-21 (5590ef2 )의 token-drop precedent 추종.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 14:39:11 +09:00
2ace54bce1
docs( #22 ): PHASE-Q-AUDIT §1 lens A-3/A-4 renderer 칸 정정
...
A-3 main = slide_measurer.capture_slide_screenshot; renderer.py 는 간접
(render-path 자료); "selenium 캡처 흔적 추정" 제거.
A-4 = renderer.py (legacy slide-base.html 호출 지점 보유,
embedded/standalone CSS 분기 미구현) 추가. html_generator.py token
양 행 보존 (IMP-23 boundary).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 14:02:53 +09:00
5590ef20b5
docs( #21 ): PHASE-Q-AUDIT §1 lens B-1/B-2 content_editor.py 오기재 제거
...
§1 lens 표 B-1 행(L104) "Phase Q 후보 파일" 칸 — content_editor.py 토큰 제거 (pipeline.py 보존).
§1 lens 표 B-2 행(L105) "Phase Q 후보 파일" 칸 — content_editor.py 토큰 제거 (글벗 fmt_slide.py html_to_slide_mdx 보존).
§2 모듈 리스트 L125 content_editor.py 항목의 (B-1, B-2) axis annotation 제거 (모듈 자체는 §2.6 audit 대상으로 유지).
근거: content_editor.py = slot-fill / Kei editor only (fill_content :73, fill_candidates :335). B-1 (zone-section override) = pipeline.py / composition planner 영역. B-2 (HTML→MDX 역변환) = 글벗 fmt_slide.py html_to_slide_mdx (외부 sibling). 로컬 src/phase_z2_verification_utils.py 는 B-2 검증 utility 만 (extract_text_from_html L64-73 / normalize_for_comparison L89-104 / strip_meta_lines L147-166). §2.6 G2 self-catch (L642-643, L679) 와 정합.
Scope: docs-only, 1 file changed, 3 insertions(+) / 3 deletions(-). src/ templates/ frontend 무변경. IMP-25 (pipeline.py B-1 precision 축) / 외부 fmt_slide.py reference 축 / content_editor archive verdict (§2.6) / PHASE-Q-INSIGHT-TO-22STEP-MAP.md:136 catch record 모두 보존.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 13:23:32 +09:00
134f52d3d3
feat( #58 ): L3 dormant trigger guard -- DORMANT-TRIGGERS.yaml + checker + orchestrator hook
...
P5-1 docs/architecture/DORMANT-TRIGGERS.yaml -- 5 entries (IMP-16/17/18/19 active + IMP-20 followup-linked #55 ).
P5-2 scripts/check_dormant_triggers.py -- standalone, reads registry, scans tree + diff, writes .orchestrator/dormant_alerts.json, exit 0 always.
P5-3 orchestrator.py -- _check_dormant_triggers() helper + Stage 4->5 informational alert branch (skips audit-only, never blocks).
P5-4 tests/orchestrator_unit/test_dormant_triggers.py -- 30 cases (yaml schema, registry contents, checker matching, false-positive guards, manual-evidence skip, orchestrator branch, audit bypass, governance ref).
P5-5 PROJECT-INTENT-AND-GOVERNANCE.md -- single anti-patterns row referencing the L3 registry as binding contract surface.
Tests: pytest -q tests = 337 passed (baseline 307 + 30 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 09:43:14 +09:00
8c1e56366b
docs( #57 ): INTEGRATION-AUDIT-02 doc-sync banner on IMP-16-U2-WIRING-DESIGN
...
IMP-16 = documented:dormant, IMP-07 = documented:no-runtime. Banner is
additive-only (9 lines, +0 deletions); existing L2-L75 contract preserved
byte-identical. Resolves issue #57 .
Refs: INTEGRATION-AUDIT-02-REPORT.md Sections 3, 4, 7
(final decision: NEEDS_DOC_SYNC_FOLLOWUP)
2026-05-20 08:11:17 +09:00
101143e67b
docs( #56 ): INTEGRATION-AUDIT-02 + backlog L51/L67 -- IMP-07 no-runtime / IMP-16 dormant
2026-05-20 07:14:45 +09:00
9389b8425b
fix(orchestrator): P5 audit-anchor-first-line regression guard
...
Bug discovered during #56 INTEGRATION-AUDIT-02 execution (2026-05-20):
- Both Claude and Codex put "Audit anchor: ..." as the FIRST line of every
Gitea comment per the #56 issue body instruction "cite anchor at start
of every stage".
- detect_agent (P0-1 strict, first-line only) then returns None for these
comments because the first line is "Audit anchor:..." not "[Codex #N]"
or "[Claude #N]".
- Result: orchestrator's "is_codex" check (line ~1288) flips false →
"Codex 응답 미감지 — continuing" → infinite Stage 4 loop. #56 reached
Round #14 (>300 comments, ~2 hours wasted token).
Fix path (NOT relaxing detect_agent — that would revive the original #45
pre-P0-1 bug where [Claude #N] citations inside Codex bodies caused
mis-detection):
1. AUDIT_ONLY_NOTE updated to enforce comment format:
- FIRST non-empty line MUST be `[Claude #N] <stage>` or `[Codex #N] <stage>`
- Audit anchor / banners / prefaces MUST appear line 2 or later
- Concrete CORRECT example included
- Explicit warning that violation breaks stage advance
2. is_codex None guard auto-supplements:
- When _audit_mode(title) AND detect_agent returns None, orchestrator
posts a Gitea supplement comment requesting the correct format
- Next round's Claude/Codex see the supplement and correct
- Breaks the infinite loop automatically (no manual ctrl-C needed)
3. Regression tests in TestDetectAgent (test_orchestrator_core.py):
- test_audit_anchor_preface_breaks_detection: confirms P0-1 strict
correctly returns None when anchor is first line
- test_audit_anchor_after_header_works: correct format passes
Total: 96/96 pytest pass (94 prior + 2 P5 regression).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 07:03:12 +09:00
47f072ee05
docs: PROJECT-INTENT-AND-GOVERNANCE master doc
...
프로젝트의 왜 / 무엇을 위해 / 어떻게 라는 질문에 대한 master 답.
이 문서가 있으면 매번 처음부터 framing 설명할 필요 없음.
구조:
1. Destination — Phase Z 22-step + AI zone-fit frame generation
2. Q~Y 검토 = 이미 완료 (과거형). 결과 = INSIGHT-MAP + 28 초기 이슈.
3. INSIGHT-MAP catalog 구조 (§0~§5)
4. IMP 이슈 좌표 체계 (관련 step + source + priority + scope + guardrails)
5. orchestrator 의 disciplined executor 역할 (Claude + Codex 합의)
6. Audit cycle (meta-governance) — 발견은 follow-up 이슈로 분리
7. 도착점 도달 기준 5 항목
8. 자주 헷갈리는 anti-patterns (heritage 보존 X, MDX 최적화 X 등)
9. 핵심 참조 문서 인덱스
10. 한 줄 요약
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 00:56:52 +09:00
8c60f7cc85
docs(IMP-20): frame contract validation reference + cross-link -- documented-axis close
2026-05-20 00:02:18 +09:00
e60aacc3dc
docs(IMP-19): zone ratio reference + cross-link -- documented-axis close
...
Stage 5 commit for IMP-19 (gitea #19 ) — docs-only, no runtime surface.
- new: docs/architecture/IMP-19-ZONE-RATIO-REFERENCE.md (header + A1 consumer
+ A2 producer + A3 Phase Z solver delta + A4 IMP-09 boundary + A5
re-activation gate / GR1-GR4).
- update: PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md — IMP-19 row pending ->
documented + reference doc link; IMP-09 row carries soft back-link to the
IMP-19 reference doc.
- update: PHASE-Q-INSIGHT-TO-22STEP-MAP.md §3 I4 row — prepend IMP-19 anchor
+ reference doc link (step/classification preserved).
Guardrails (Stage 1/2 binding contract): src/ untouched, no role-based
["배경","본심"] hardcoding into Phase Z, IMP-09 solver ownership preserved,
soft-link integrity holds. IMP-19 remains dormant until the A5 gate fires.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 21:28:17 +09:00
02e2ae0afb
docs( #54 ): F-4 legacy annotation + F-5 fixture convention -- AUDIT-01 housekeeping
...
INTEGRATION-AUDIT-01 (#50 ) §10.4 / §10.5 housekeeping carry-over.
F-4: annotate 14 remaining legacy Phase R'/Q sample-text hits across 10
src/ files with inline marker `# [legacy Phase R'/Q example -- INTEGRATION-AUDIT-01 §10.4]`.
Comment-only. No string-literal / regex / sample dict value mutated.
fit_verifier.py L612 marker keeps Phase Z partial-live import graph
(FitAnalysis / RoleFit / redistribute / salvage) byte-precise.
F-5: docs-only addendum -- §10.5.1 in INTEGRATION-AUDIT-01-REPORT.md +
tests/CLAUDE.md fixture convention note. No root tests/fixtures/ dir
created; existing tests/phase_z2/fixtures/ convention preserved. Documents
test-only sample-reference allowance vs src/** runtime prohibition.
Out of scope: Phase Z source 11 hits (phase_z2_content_extractor /
failure_router / mapper / retry), production behavior change, #19 work.
Verified: pytest -q tests/phase_z2/ = 157 PASS. git diff +210/-0
(35 src/docs lines + 175 new tests/CLAUDE.md). No behavioral delta.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 20:23:36 +09:00
8f06a4c99f
docs(IMP-52): reconcile Phase Z family count drift -- F-2 option (c)
...
Audit follow-up F-2 (INTEGRATION-AUDIT-01 §10.2). Phase Z families surface
showed 11 tracked / 11 contracted / 13 on disk. The 2 untracked WIP files
(app_sw_package_vs_solution.html, pre_construction_model_info_stacked.html)
are now declared in _WIP_FILES.md as uncontracted and out-of-scope for the
runtime matcher; promote/remove is gated on #42 . The 11/11 tracked +
contracted baseline is unchanged. A new pytest enforces tracked families ↔
frame_contracts.yaml set-equality modulo the WIP allowlist parsed from
_WIP_FILES.md, so future drift fails fast in CI before #42 expands to 32
frames.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 19:15:04 +09:00
191b6a9d85
docs(IMP-53): resolve audit charter F-1 -- C3 producer path
...
Annotate `INTEGRATION-AUDIT-01-REPORT.md` §5.1 row C3 with an inline
correction pointer noting that the historical charter cites
`src/phase_z2_mapper.py + consumers` but the live `fit_classification`
producer is `src/phase_z2_classifier.py`. Stamp §5.4 F-1 surface-note
and §10.1 F-1 heading as `RESOLVED via IMP-53 (2026-05-19)`.
Documentation-only change. Runtime / templates / catalog / MATRIX /
OVERVIEW untouched. Historical §5.1 C3 quote preserved verbatim per
anchor_sync_rules. pytest -q tests = 303 passed (baseline parity).
Refs IMP-53 (F-1) -- gitea issue #53
2026-05-19 16:42:12 +09:00
2bb0acac19
docs(IMP-51): reconcile Phase Z backlog status with audit-01 (F-3)
...
Per INTEGRATION-AUDIT-01 (#50 ) §6.2 / §9.3 cond.1 / §10.3:
- §1 IMP-02..IMP-11: pending -> implemented (10 rows, BACKLOG_STALE flip)
- §2 IMP-12..IMP-16: pending -> implemented (5 rows, BACKLOG_STALE flip)
- §2 IMP-17: pending -> documented (deferred) (carve-out boundary preserved)
- §2 IMP-18: documented unchanged (AGREE row)
- §2 footnote: IMP-15 child issues note (#45 e9b3d2e / #46 2827622 /
#47 535c484 / #48 614c533 / #49 verification-only) — no standalone rows
Hard gate before #19 Stage 2 planning. Doc-only carve-out:
no src/templates/tests changes. Status strings match audit §6.2 verbatim.
Out-of-audit-scope rows (IMP-01, IMP-19/20, IMP-21..28) preserved.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 16:08:39 +09:00
c37a554fb1
docs(IMP-50): backlog audit completion row for IMP-50
...
Append IMP-50 audit completion row referencing INTEGRATION-AUDIT-01-REPORT
(commit 8c7d693 ) with CONDITIONAL GO for #19 decision.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 14:59:39 +09:00
8c7d6935b1
docs(IMP-50): Phase Z integration audit-01 — report-only carve-out
...
22 closed improvement issues × 22-step Phase Z pipeline audit.
4-axis verification: scope myopia, pipeline step mapping, cross-issue
conflict, backlog ↔ code reality. Decision: CONDITIONAL GO for #19 .
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 14:59:18 +09:00
e32f632464
fix(orchestrator): P4a baseline-diff guard + Stage 5 commit scope
...
P4 had two production issues blocking #50 integration audit deployment:
1. Stage 3 guard had no baseline awareness — flagged ALL forbidden-path
changes including pre-existing dirty WIP. Empirical: 328 such files
already in current working tree (tests/matching/ artifacts etc).
#50 would have hit reject loops immediately without Claude doing
anything wrong.
2. Stage 5 had no commit-scope guard — if Claude ran `git add -A` and
committed user's existing WIP, audit commit would be polluted with
unrelated production changes.
P4a additions:
- _audit_baseline_path / _ensure_audit_baseline / _load_audit_baseline:
snapshot working-tree dirty paths at run_issue entry for audit issues.
Resumed runs preserve existing baseline (no overwrite).
- _check_audit_only_violations(baseline=None): accept baseline set,
subtract from violations — only flags NEW forbidden changes introduced
after audit start.
- _check_audit_commit_scope: verify HEAD commit's file list matches
AUDIT_ALLOWED_COMMIT_GLOBS (INTEGRATION-AUDIT-*.md, BACKLOG.md).
- run_issue: save baseline on audit-mode entry only — no impact on
normal issues.
- Stage 5 (commit-push) YES gate: new guard rejects on out-of-scope
files with remediation prompt (git reset --soft + force-with-lease).
19 new tests:
- baseline subtraction (5): pre-existing removed, None=keep-all,
empty-set=catch-all, full-coverage filter, Windows path normalize.
- baseline persist (5): roundtrip, no-overwrite on resume, missing
fallback, corrupt JSON fallback, non-list fallback.
- commit scope detection (7): report-only allowed, backlog allowed,
src/ rejected, unrelated docs rejected, git error fail-open,
Windows backslash, empty commit pass.
- allowed globs sanity (2): every glob has audit marker, all under
docs/architecture/.
Total: 94/94 pytest pass (75 prior + 19 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 10:29:15 +09:00
4289a500b6
feat(orchestrator): P3 wrapper input/encoding fix + P4 audit-only mode
...
P3 hotfix (2026-05-18 — verified during #46 retry attempt):
- _run_with_tree_kill: encode input only when Popen is in binary mode.
Previously force-encoded str→bytes even with encoding= set, breaking
text-mode stdin pipes with: write() argument must be str, not bytes.
- run_claude path was the only affected call site.
- 3 new C7 regression tests (input+encoding / bytes+binary / auto-encode).
- C3/C6 test fixtures hardened with DEVNULL stdio isolation.
P4 audit-only mode (2026-05-19, prep for #50 integration audit):
- _is_audit_issue: title-based detection for [INTEGRATION-AUDIT*],
[AUDIT-ONLY], or "integration audit" phrase.
- _audit_mode + --audit-only CLI flag: manual override regardless of title.
- AUDIT_ONLY_NOTE injected into context pack across all stages/rounds.
- Stage 3 (code-edit) YES gate: deterministic git status check.
Changes touching src/**, templates/**, tests/** auto-reject Stage 3 YES
and post a supplement-request comment. LLM-independent enforcement.
- 26 new audit-mode tests (title detection, CLI override, forbidden
prefix detection, allowed paths pass, Windows backslash normalization,
quoted paths with spaces, git error fail-open, constants sanity).
Total: 75/75 pytest pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 10:18:28 +09:00
cbbc163860
docs(IMP-18): Phase Z SVG gap report — doc-only carve-out
...
u1: docs/architecture/IMP-18-SVG-GAP-REPORT.md (NEW, 64 lines)
4 axes: Phase R' _preprocess_svg_data source refs (renderer.py:169-207,
svg_calculator.py:15-156); Phase Z 15-partial SVG absence (grep
<svg|viewBox = 0); IMP-04 activation gate; Phase R' read-only guardrail.
u2: docs/architecture/PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md L69
IMP-18 row: status pending -> documented + gap-doc link appended.
Phase R' source (src/renderer.py, src/svg_calculator.py) and 15 Phase Z
partials remain unmodified. IMP-18 is dormant reference axis; activation
gated on IMP-04 registering an SVG-bearing partial.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 09:33:34 +09:00
e10ec36617
feat(IMP-17): AI repair fallback infra carve-out — design-only boundary + 3-cond AND gate
...
u1 — src/phase_z2_pipeline.py:564 route hint comment corrected from
non-existent IMP-31 to IMP-17 (carve-out, AI fallback only, normal path 밖).
Line 565 IMP-29 frontend override reference untouched.
u2 — docs/architecture/IMP-17-CARVE-OUT.md (new) defines:
- allowed scope (Step 12 restructure proposal, Step 16/17 retry fallback)
- forbidden scope (normal-path AI calls, MDX compression, HTML structure)
- 3-condition AND activation gate (User GO ∧ B4 frame_selection evidence
∧ IMP-04 catalog + IMP-05 V4 fallback live)
- pattern shape reference (link-only): content_editor.py:21,318 +
sse_utils.py:16-50 (Phase Q Archive Candidate, no port)
- AI 격리 contract + Kei persona 단절 (permanent)
u3 — PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md:68 IMP-17 row gains
carve-out doc link + 3-cond AND gate pointer.
u4 — PHASE-Q-INSIGHT-TO-22STEP-MAP.md AI repair fallback infra registry
row prefixed with IMP-17 + carve-out link; normal_path=no preserved.
Anchor test: tests/orchestrator_unit/test_imp17_comment_anchor.py asserts
line 564 IMP-17 wording AND line 565 IMP-29 preservation (2 tests pass).
Runtime behavior change: 0. Only delta in executable file is one comment
line. Normal-path AI invocation count remains 0.
Refs: gitea #17
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-19 08:12:43 +09:00