From 80dc0abc8175e103a4e835e755b57db6db07a5e5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 23:19:14 +0900 Subject: [PATCH 01/22] docs: refresh exact-head product gap audit --- docs/product-technical-gap-baseline.md | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 21086eaa0..8c32ee413 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -412,3 +412,43 @@ the existing whole-image fallback. - Integration status: PR #320 is not protected-main truth; exact stack heads, formal review, terminal Checks, and authorized post-merge image evidence remain required. + +## Current exact-head audit: 2026-08-20 continuation + +The protected GitHub state was re-read after the embedding and visual-region +checkpoints. These are gate observations, not merge claims. A blank review +decision means no independent approval was observed; `UNSTABLE` and `BLOCKED` +are not release evidence. + +| PR | Base -> head | Exact head | Review/check state | +|---|---|---|---| +| #258 | `main` -> `feat/analysis-run-name-evidence-lineage` | `49804b0fef503be1697b8be61919b022b615ef2f` | `REVIEW_REQUIRED`, `BLOCKED`; no independent approval observed | +| #323 | `main` -> `fix/tepp-request-contract-validation` | `1a27efec6863cd3439a4c6023e1c625ce4d7abf2` | `REVIEW_REQUIRED`, `BLOCKED`; required Checks queued | +| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `a6a1d8fe8b17ad095e507f5d16b93c984e6de5db` | `UNSTABLE`; Full test and frontend Checks queued | +| #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | +| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `a4627d6e1d04b4782a696c74d67303e1143038e0` | `UNSTABLE`; Full test and frontend Checks queued | +| #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | + +The current implementation checkpoints are local/branch evidence only: +LineageWeave embedding model discovery is recorded in ADR 0118, and visual +locator validation is stacked in #324. Exact-head OpenCode review requests were +issued for #258, #322, #323, #324, and upstream #789. No protected branch was +approved, force-pushed, or merged from this audit. + +This update supersedes neither the historical PR table nor the closure +criteria above; it supplies the current gate snapshot needed before the next +review -> fix -> Checks -> merge decision. + +## Locator-bound validation checkpoint: 2026-08-20 + +The partial-region path now rejects non-finite, zero-sized, negative, and +out-of-bounds locator boxes before crop or persistence. Valid panels remain +independently searchable; if every returned box is invalid, the existing +parent-image fallback preserves an honest image-level outcome. + +- Decision record: ADR 0104 +- Implementation: PR #324, stacked on PR #320 +- Local evidence: normalization module branch coverage `100%`; focused image, + persistence-edge, and normalization tests `52 passed`. +- Integration status: PR #324 is not protected-main truth; its exact current + head, formal review, terminal Checks, and browser evidence remain required. From ec47fbfac5a02ed58980dace6180da5af6e9f5a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 23:21:35 +0900 Subject: [PATCH 02/22] test: cover visual region fallback branches --- ...l-visual-regions-retain-parent-evidence.md | 4 + tests/test_post_content_normalization.py | 95 ++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/docs/adr/0104-partial-visual-regions-retain-parent-evidence.md b/docs/adr/0104-partial-visual-regions-retain-parent-evidence.md index 18c0db189..f6cf859ce 100644 --- a/docs/adr/0104-partial-visual-regions-retain-parent-evidence.md +++ b/docs/adr/0104-partial-visual-regions-retain-parent-evidence.md @@ -15,6 +15,10 @@ only the panels would instead lose text outside them. - Keep every valid, bounded locator region even when the collection does not cover the full image. +- Before cropping or persistence, discard locator boxes that are non-finite, + zero-sized, negative, or extend outside the normalized image bounds. If no + bounded region remains, use the parent-sized fallback rather than treating + malformed provider output as buyer evidence. - Describe each retained region independently and persist its coordinates and status as before. - For a partial collection, also describe the original parent image once so diff --git a/tests/test_post_content_normalization.py b/tests/test_post_content_normalization.py index b9bed2b9d..9ef59ea38 100644 --- a/tests/test_post_content_normalization.py +++ b/tests/test_post_content_normalization.py @@ -11,7 +11,8 @@ import base64 from threading import Lock -from lineageweave.image_content import ImageDescription, ImageRegion +from lineageweave.chunking import Chunk +from lineageweave.image_content import ImageDescription, ImageRegion, NullImageContentClient from lineageweave.llm_context import current_llm_metadata, use_llm_metadata from lineageweave.post_content_normalization import normalize_post_body @@ -79,6 +80,19 @@ def locate_regions(self, image_bytes: bytes, mime_type: str) -> tuple[ImageRegio ) +class _LocatorFailureVisionClient(_FakeVisionClient): + def locate_regions(self, image_bytes: bytes, mime_type: str) -> tuple[ImageRegion, ...]: + raise RuntimeError("synthetic locator outage") + + +class _PartialRegionFailureVisionClient(_FakeVisionClient): + def locate_regions(self, image_bytes: bytes, mime_type: str) -> tuple[ImageRegion, ...]: + return (ImageRegion(0.25, 0.25, 0.25, 0.25),) + + def describe(self, image_bytes: bytes, mime_type: str) -> ImageDescription: + raise RuntimeError("synthetic region and parent outage") + + def test_plain_text_passes_through_unchanged() -> None: result = normalize_post_body("Just a plain business record, no markup here.") assert result.text == "Just a plain business record, no markup here." @@ -151,6 +165,85 @@ def test_image_regions_are_cropped_and_described_as_independent_evidence() -> No assert "panel text" in result.text +def test_image_without_ocr_uses_caption_only_and_preserves_image_result() -> None: + b64 = base64.b64encode(_PNG_1X1).decode("ascii") + description = ImageDescription(extracted_text="", caption="a blank chart", tags=()) + + result = normalize_post_body( + f'', + vision_client=_FakeVisionClient(description), + ) + + assert result.text == "[image: a blank chart]" + assert result.image_results[0].status_code == "described" + + +def test_unavailable_vision_channel_keeps_an_explicit_image_outcome() -> None: + b64 = base64.b64encode(_PNG_1X1).decode("ascii") + + result = normalize_post_body( + f'', + vision_client=NullImageContentClient(), + ) + + assert result.text == "[image: content unavailable]" + assert result.image_results[0].status_code == "unavailable" + + +def test_available_client_with_missing_image_bytes_keeps_unavailable_outcome() -> None: + from lineageweave.post_content_normalization import _describe_image_chunk + + result, description, placeholder = _describe_image_chunk( + Chunk(text="", unit_type="image", index=0, label="image/png", image_data=None), + _FakeVisionClient(ImageDescription(extracted_text="", caption="unused", tags=())), + ) + + assert result.status_code == "unavailable" + assert description is None + assert placeholder == "[image: content unavailable]" + + +def test_locator_failure_falls_back_to_parent_image_evidence() -> None: + b64 = base64.b64encode(_PNG_1X1).decode("ascii") + description = ImageDescription(extracted_text="parent", caption="whole image", tags=()) + + result = normalize_post_body( + f'', + vision_client=_LocatorFailureVisionClient(description), + ) + + assert result.image_results[0].status_code == "described" + assert result.image_results[0].regions[0].region == ImageRegion(0.0, 0.0, 1.0, 1.0) + + +def test_partial_locator_with_no_successful_description_fails_closed() -> None: + b64 = base64.b64encode(_PNG_1X1).decode("ascii") + + result = normalize_post_body( + f'', + vision_client=_PartialRegionFailureVisionClient( + ImageDescription(extracted_text="unused", caption="unused", tags=()) + ), + ) + + assert result.image_results[0].status_code == "failed" + assert result.text == "[image: content unavailable]" + + +def test_unknown_chunk_kinds_are_not_leaked_into_buyer_text(monkeypatch) -> None: + from lineageweave import post_content_normalization + + monkeypatch.setattr( + post_content_normalization, + "chunk_by_dom", + lambda _body: [Chunk(text="hidden", unit_type="unknown", index=0)], + ) + + result = normalize_post_body("
ignored by the synthetic chunker
") + + assert result.text == "" + + def test_image_analysis_preserves_post_scoped_llm_metadata() -> None: b64 = base64.b64encode(_PNG_1X1).decode("ascii") html = ( From 647899483bcfb44ebdacd415e14ee0a9bfd810cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 23:24:37 +0900 Subject: [PATCH 03/22] docs: record current audit head --- docs/product-technical-gap-baseline.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 8c32ee413..d9b11240f 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,6 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `a6a1d8fe8b17ad095e507f5d16b93c984e6de5db` | `UNSTABLE`; Full test and frontend Checks queued | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `a4627d6e1d04b4782a696c74d67303e1143038e0` | `UNSTABLE`; Full test and frontend Checks queued | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `ec47fbfac5a02ed58980dace6180da5af6e9f5a3` | `UNKNOWN`; Full test, frontend, and Devin Review pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 39acad3909e926a1925b82e59f35fdd7a7080e26 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 23:27:38 +0900 Subject: [PATCH 04/22] docs: repair stacked audit traceability --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index e51120c6a..38949b9aa 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `a6a1d8fe8b17ad095e507f5d16b93c984e6de5db` | `UNSTABLE`; Full test and frontend Checks queued | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `3a335ad493a260c5f623797288138472a15210cb` | `UNSTABLE`; Full test and frontend Checks queued | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `ec47fbfac5a02ed58980dace6180da5af6e9f5a3` | `UNKNOWN`; Full test, frontend, and Devin Review pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `ecc6c477` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From df941f74e479b244cc093a50abb2f829808251b6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 23:29:05 +0900 Subject: [PATCH 05/22] docs: refresh stacked PR exact heads --- docs/product-technical-gap-baseline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 38949b9aa..729816f1e 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -424,9 +424,9 @@ are not release evidence. |---|---|---|---| | #258 | `main` -> `feat/analysis-run-name-evidence-lineage` | `49804b0fef503be1697b8be61919b022b615ef2f` | `REVIEW_REQUIRED`, `BLOCKED`; no independent approval observed | | #323 | `main` -> `fix/tepp-request-contract-validation` | `1a27efec6863cd3439a4c6023e1c625ce4d7abf2` | `REVIEW_REQUIRED`, `BLOCKED`; required Checks queued | -| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `a6a1d8fe8b17ad095e507f5d16b93c984e6de5db` | `UNSTABLE`; Full test and frontend Checks queued | +| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `UNSTABLE`; Full test and frontend Checks queued; Devin Review pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | -| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `3a335ad493a260c5f623797288138472a15210cb` | `UNSTABLE`; Full test and frontend Checks queued | +| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `71f0940cb3881b2f5452ae79fa45f033dff56a9d` | `UNSTABLE`; Full test and frontend Checks queued; fresh Devin Review pending | | #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `ecc6c477` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | From d2c20380f42f83d480e5b74c71d465eb5c6088d3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 20 Aug 2026 23:34:22 +0900 Subject: [PATCH 06/22] docs: record audit refresh head --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 729816f1e..7ca78b632 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `UNSTABLE`; Full test and frontend Checks queued; Devin Review pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `71f0940cb3881b2f5452ae79fa45f033dff56a9d` | `UNSTABLE`; Full test and frontend Checks queued; fresh Devin Review pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `ecc6c477` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `df941f74e479b244cc093a50abb2f829808251b6` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 26ed4cf691604e6302d12e46cdf95c57d39b74bc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 01:36:59 +0900 Subject: [PATCH 07/22] docs: refresh current visual stack state --- docs/product-technical-gap-baseline.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index e40ce08d7..203540cc3 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -424,9 +424,9 @@ are not release evidence. |---|---|---|---| | #258 | `main` -> `feat/analysis-run-name-evidence-lineage` | `49804b0fef503be1697b8be61919b022b615ef2f` | `REVIEW_REQUIRED`, `BLOCKED`; no independent approval observed | | #323 | `main` -> `fix/tepp-request-contract-validation` | `1a27efec6863cd3439a4c6023e1c625ce4d7abf2` | `REVIEW_REQUIRED`, `BLOCKED`; required Checks queued | -| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `UNSTABLE`; Full test and frontend Checks queued; Devin Review pending | +| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | -| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `71f0940cb3881b2f5452ae79fa45f033dff56a9d` | `UNSTABLE`; Full test and frontend Checks queued; fresh Devin Review pending | +| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `UNSTABLE`; Full test and frontend Checks queued; fresh Devin Review pending | | #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `df941f74e479b244cc093a50abb2f829808251b6` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | From 0d5538220830eab6cd2823dd67ff8113ffcbf945 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 01:38:04 +0900 Subject: [PATCH 08/22] docs: record visual stack audit head --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 203540cc3..e505c9534 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `UNSTABLE`; Full test and frontend Checks queued; fresh Devin Review pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `df941f74e479b244cc093a50abb2f829808251b6` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `26ed4cf691604e6302d12e46cdf95c57d39b74bc` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 885a4e8d4bc46a10b0ac17340cfd8d7d23bb3dca Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 03:05:27 +0900 Subject: [PATCH 09/22] docs: align visual stack gate states --- docs/product-technical-gap-baseline.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index e505c9534..b1c71d161 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -425,9 +425,9 @@ are not release evidence. | #258 | `main` -> `feat/analysis-run-name-evidence-lineage` | `49804b0fef503be1697b8be61919b022b615ef2f` | `REVIEW_REQUIRED`, `BLOCKED`; no independent approval observed | | #323 | `main` -> `fix/tepp-request-contract-validation` | `1a27efec6863cd3439a4c6023e1c625ce4d7abf2` | `REVIEW_REQUIRED`, `BLOCKED`; required Checks queued | | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | -| #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `UNSTABLE`; stacked visual evidence change | -| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `UNSTABLE`; Full test and frontend Checks queued; fresh Devin Review pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `26ed4cf691604e6302d12e46cdf95c57d39b74bc` | `UNKNOWN`; base synchronized; required Checks and fresh review pending | +| #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | +| #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `0d5538220830eab6cd2823dd67ff8113ffcbf945` | `UNSTABLE`; required Checks queued; existing review is non-approval | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 66e3e557c333423f2db0dac9bd16373b360a0034 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 03:09:52 +0900 Subject: [PATCH 10/22] fix: preserve semantic footnote structure --- .../0102-semantic-source-unit-boundaries.md | 4 ++ lineageweave/chunking.py | 72 +++++++++++++++---- tests/test_chunking.py | 18 ++++- 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/docs/adr/0102-semantic-source-unit-boundaries.md b/docs/adr/0102-semantic-source-unit-boundaries.md index d4a80ea26..22c68f44c 100644 --- a/docs/adr/0102-semantic-source-unit-boundaries.md +++ b/docs/adr/0102-semantic-source-unit-boundaries.md @@ -18,6 +18,10 @@ must not become embedding text. - Treat `ol`/`ul` container depth as explicit indentation and persist `li` as its own DOM semantic unit. +- Preserve semantic footnote labels from HTML/Word markers such as + `role="doc-footnote"`, footnote containers, `MsoFootnoteText`, and Word + footnote reference links; a footnote remains a searchable unit, not a list + item inferred only from its leading glyph. - For markup-free input, split at authored blank paragraphs and list markers; continuation lines remain in the preceding item after visual alignment is removed. diff --git a/lineageweave/chunking.py b/lineageweave/chunking.py index 92dc1c451..c8e922989 100644 --- a/lineageweave/chunking.py +++ b/lineageweave/chunking.py @@ -68,6 +68,8 @@ "ol", "ul", "li", + "footnote", + "endnote", "tr", "blockquote", "h1", @@ -100,6 +102,27 @@ _FOOTNOTE_START = re.compile(r"^[*†‡](?=\S)") +def _is_footnote_block(tag: str, attrs: list[tuple[str, str | None]]) -> bool: + """Recognize semantic footnote markup emitted by HTML and Word exports.""" + if tag.casefold() in {"footnote", "endnote"}: + return True + values = " ".join( + value or "" + for name, value in attrs + if name.casefold() in {"class", "id", "role", "data-role"} + ).casefold() + return "footnote" in values or "endnote" in values + + +def _is_footnote_reference(attrs: list[tuple[str, str | None]]) -> bool: + """Recognize Word footnote reference links inside an enclosing paragraph.""" + return any( + ("ftn" in (value or "").casefold() or "footnote" in (value or "").casefold()) + for name, value in attrs + if name.casefold() in {"href", "id", "name"} + ) + + def normalize_semantic_text(text: str) -> str: """Remove visual hanging-indent breaks without changing source content.""" lines = text.replace("\r\n", "\n").replace("\r", "\n").split("\n") @@ -128,7 +151,11 @@ def _source_indent_width(text: str) -> int: def _length_to_indent_units(value: str) -> int: """Convert common CSS/XML lengths to a comparable eight-pixel unit.""" - match = re.fullmatch(r"\s*([+-]?(?:\d+\.?\d*|\.\d+))\s*(px|pt|em|rem|in|cm|mm|%)?\s*", value, re.I) + match = re.fullmatch( + r"\s*([+-]?(?:\d+\.?\d*|\.\d+))\s*(px|pt|em|rem|in|cm|mm|%)?\s*", + value, + re.IGNORECASE, + ) if match is None: return 0 amount = float(match.group(1)) @@ -170,7 +197,7 @@ def _declared_indent_width(tag: str, attrs: list[tuple[str, str | None]]) -> int for match in re.finditer( r"(?:^|;)\s*(?:margin-left|padding-left|padding-inline-start|text-indent)\s*:\s*([^;]+)", style, - re.I, + re.IGNORECASE, ): width += _length_to_indent_units(match.group(1)) # A real editor (Word paste, Outlook compose) declares indentation with @@ -179,7 +206,9 @@ def _declared_indent_width(tag: str, attrs: list[tuple[str, str | None]]) -> int # every nested
  • in a real body used only the shorthand, so its # indentation silently read as 0 and every nesting level collapsed flat # (live bug, 2026-08-19). - for match in re.finditer(r"(?:^|;)\s*(?:margin|padding)\s*:\s*([^;]+)", style, re.I): + for match in re.finditer( + r"(?:^|;)\s*(?:margin|padding)\s*:\s*([^;]+)", style, re.IGNORECASE + ): width += _length_to_indent_units(_shorthand_left_value(match.group(1))) for name, value in attrs: if name in {"w:left", "w:start", "w:firstline"} and value: @@ -305,7 +334,7 @@ class _BlockTextExtractor(HTMLParser): def __init__(self) -> None: super().__init__() - self._stack: list[tuple[str, list[str], str | None, int]] = [] + self._stack: list[tuple[str, list[str], str | None, int, bool]] = [] self._unscoped_buffer: list[str] = [] # Each entry is ("text", str, tag_name, style) or # ("image", (mime_type, bytes), "", None) -- a single sequence in @@ -326,14 +355,19 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None self._stack[-1][1].append("\n") return if tag == "w:ind" and self._stack: - tag_name, buffer, style, indent_width = self._stack[-1] + tag_name, buffer, style, indent_width, is_footnote = self._stack[-1] self._stack[-1] = ( tag_name, buffer, style, indent_width + _declared_indent_width(tag, attrs), + is_footnote, ) return + if tag == "a" and self._stack and _is_footnote_reference(attrs): + tag_name, buffer, style, indent_width, _ = self._stack[-1] + self._stack[-1] = (tag_name, buffer, style, indent_width, True) + return if tag in _TABLE_CELL_TAGS: if self._stack and self._stack[-1][0] in _TABLE_ROW_TAGS and self._stack[-1][1]: self._stack[-1][1].append(" | ") @@ -345,12 +379,17 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None return if tag in _DOM_BLOCK_TAGS: if self._stack and self._stack[-1][1]: - tag_name, buffer, style, _ = self._stack[-1] + tag_name, buffer, style, _, is_footnote = self._stack[-1] declared_width = sum(entry[3] for entry in self._stack) - self._finish_block(tag_name, buffer, style, declared_width) + self._finish_block(tag_name, buffer, style, declared_width, is_footnote) buffer.clear() style = next((value for name, value in attrs if name == "style" and value), None) - self._stack.append((tag, [], style, _declared_indent_width(tag, attrs))) + is_footnote = _is_footnote_block(tag, attrs) or any( + entry[4] for entry in self._stack + ) + self._stack.append( + (tag, [], style, _declared_indent_width(tag, attrs), is_footnote) + ) def handle_startendtag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: """Handle self-closing block tags without losing XML indentation state.""" @@ -362,11 +401,16 @@ def handle_endtag(self, tag: str) -> None: """Close the relevant text state when an HTML end tag is encountered.""" if tag in _DOM_BLOCK_TAGS and self._stack and self._stack[-1][0] == tag: declared_width = sum(entry[3] for entry in self._stack) - tag_name, buffer, style, _ = self._stack.pop() - self._finish_block(tag_name, buffer, style, declared_width) + tag_name, buffer, style, _, is_footnote = self._stack.pop() + self._finish_block(tag_name, buffer, style, declared_width, is_footnote) def _finish_block( - self, tag_name: str, buffer: list[str], style: str | None, declared_width: int + self, + tag_name: str, + buffer: list[str], + style: str | None, + declared_width: int, + is_footnote: bool = False, ) -> None: """Emit one block buffer, including a block closed only at EOF.""" raw_text = "".join(buffer) @@ -374,7 +418,7 @@ def _finish_block( text = normalize_semantic_text(raw_unit) if text: indent_width = declared_width + source_indent - label = "footnote" if _FOOTNOTE_START.match(text) else tag_name + label = "footnote" if is_footnote or _FOOTNOTE_START.match(text) else tag_name self._finished.append( ( "text", @@ -405,8 +449,8 @@ def finished(self) -> list[tuple[str, object, str, str | None, int, int]]: """Return the normalized records collected from the HTML fragment.""" while self._stack: declared_width = sum(entry[3] for entry in self._stack) - tag_name, buffer, style, _ = self._stack.pop() - self._finish_block(tag_name, buffer, style, declared_width) + tag_name, buffer, style, _, is_footnote = self._stack.pop() + self._finish_block(tag_name, buffer, style, declared_width, is_footnote) if not self._finished: fallback = normalize_semantic_text("".join(self._unscoped_buffer)) if fallback: diff --git a/tests/test_chunking.py b/tests/test_chunking.py index 7d2f3883a..2faadd384 100644 --- a/tests/test_chunking.py +++ b/tests/test_chunking.py @@ -4,9 +4,9 @@ ConversationTurn, chunk_by_conversation_turn, chunk_by_dom, - chunk_by_source_body, chunk_by_paragraph, chunk_by_sentence, + chunk_by_source_body, normalize_semantic_text, ) @@ -112,6 +112,22 @@ def test_chunk_by_dom_labels_markerless_footnotes() -> None: ] +def test_chunk_by_dom_labels_html_and_word_footnote_markup() -> None: + html = ( + "

    Body text

    " + '
    1. HTML footnote body

    ' + '

    1 Word footnote body

    ' + ) + + chunks = chunk_by_dom(html) + + assert [(chunk.label, chunk.text) for chunk in chunks] == [ + ("p", "Body text"), + ("footnote", "HTML footnote body"), + ("footnote", "1 Word footnote body"), + ] + + def test_chunk_by_dom_word_table_rows_also_group_cells() -> None: html = "1Acme Corp" chunks = chunk_by_dom(html) From d86af3bd3456328e7828047efdc4d3e3e6aa471f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 03:26:40 +0900 Subject: [PATCH 11/22] docs: record footnote structure checkpoint --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index b1c71d161..055467351 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `0d5538220830eab6cd2823dd67ff8113ffcbf945` | `UNSTABLE`; required Checks queued; existing review is non-approval | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `66e3e557c333423f2db0dac9bd16373b360a0034` | `UNSTABLE`; semantic HTML/Word footnote units preserved; required Checks and fresh independent approval pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 2ee9e6524e75a10d218ce3243272d17940ef0d08 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 03:56:16 +0900 Subject: [PATCH 12/22] fix: classify OOXML footnote containers --- lineageweave/chunking.py | 4 +++- tests/test_chunking.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lineageweave/chunking.py b/lineageweave/chunking.py index c8e922989..97951e6f8 100644 --- a/lineageweave/chunking.py +++ b/lineageweave/chunking.py @@ -70,6 +70,8 @@ "li", "footnote", "endnote", + "w:footnote", + "w:endnote", "tr", "blockquote", "h1", @@ -104,7 +106,7 @@ def _is_footnote_block(tag: str, attrs: list[tuple[str, str | None]]) -> bool: """Recognize semantic footnote markup emitted by HTML and Word exports.""" - if tag.casefold() in {"footnote", "endnote"}: + if tag.casefold().rsplit(":", 1)[-1] in {"footnote", "endnote"}: return True values = " ".join( value or "" diff --git a/tests/test_chunking.py b/tests/test_chunking.py index 2faadd384..019977381 100644 --- a/tests/test_chunking.py +++ b/tests/test_chunking.py @@ -128,6 +128,18 @@ def test_chunk_by_dom_labels_html_and_word_footnote_markup() -> None: ] +def test_chunk_by_dom_labels_ooxml_footnote_containers() -> None: + chunks = chunk_by_dom( + "OOXML footnote body" + "OOXML endnote body" + ) + + assert [(chunk.label, chunk.text) for chunk in chunks] == [ + ("footnote", "OOXML footnote body"), + ("footnote", "OOXML endnote body"), + ] + + def test_chunk_by_dom_word_table_rows_also_group_cells() -> None: html = "1Acme Corp" chunks = chunk_by_dom(html) From 5176dde1124ec04401d71c04373e7300744c3db2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 04:10:25 +0900 Subject: [PATCH 13/22] fix: distinguish footnote citations from definitions --- docs/adr/0102-semantic-source-unit-boundaries.md | 5 +++-- lineageweave/chunking.py | 11 ++++++++--- tests/test_chunking.py | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/adr/0102-semantic-source-unit-boundaries.md b/docs/adr/0102-semantic-source-unit-boundaries.md index 22c68f44c..92bfe9457 100644 --- a/docs/adr/0102-semantic-source-unit-boundaries.md +++ b/docs/adr/0102-semantic-source-unit-boundaries.md @@ -20,8 +20,9 @@ must not become embedding text. its own DOM semantic unit. - Preserve semantic footnote labels from HTML/Word markers such as `role="doc-footnote"`, footnote containers, `MsoFootnoteText`, and Word - footnote reference links; a footnote remains a searchable unit, not a list - item inferred only from its leading glyph. + footnote-definition backlink pairs; a footnote remains a searchable unit, + not a list item inferred only from its leading glyph. A body citation must + remain part of its enclosing body paragraph. - For markup-free input, split at authored blank paragraphs and list markers; continuation lines remain in the preceding item after visual alignment is removed. diff --git a/lineageweave/chunking.py b/lineageweave/chunking.py index c8e922989..891b96533 100644 --- a/lineageweave/chunking.py +++ b/lineageweave/chunking.py @@ -115,11 +115,16 @@ def _is_footnote_block(tag: str, attrs: list[tuple[str, str | None]]) -> bool: def _is_footnote_reference(attrs: list[tuple[str, str | None]]) -> bool: - """Recognize Word footnote reference links inside an enclosing paragraph.""" - return any( - ("ftn" in (value or "").casefold() or "footnote" in (value or "").casefold()) + """Recognize a Word footnote-definition backlink, not its body citation.""" + values = { + name.casefold(): (value or "").casefold() for name, value in attrs if name.casefold() in {"href", "id", "name"} + } + href = values.get("href", "") + anchor_values = (values.get("id", ""), values.get("name", "")) + return "ftnref" in href and any( + "ftn" in value and "ftnref" not in value for value in anchor_values ) diff --git a/tests/test_chunking.py b/tests/test_chunking.py index 2faadd384..a93691fdd 100644 --- a/tests/test_chunking.py +++ b/tests/test_chunking.py @@ -128,6 +128,20 @@ def test_chunk_by_dom_labels_html_and_word_footnote_markup() -> None: ] +def test_chunk_by_dom_does_not_label_body_footnote_citation_as_footnote() -> None: + html = ( + '

    Body cites [1].

    ' + '

    [1] Footnote definition.

    ' + ) + + chunks = chunk_by_dom(html) + + assert [(chunk.label, chunk.text) for chunk in chunks] == [ + ("p", "Body cites [1]."), + ("footnote", "[1] Footnote definition."), + ] + + def test_chunk_by_dom_word_table_rows_also_group_cells() -> None: html = "1Acme Corp" chunks = chunk_by_dom(html) From d4408c67a563244f3595ec77d82c71d727eaf21a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 04:44:12 +0900 Subject: [PATCH 14/22] docs: record footnote citation guard --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 055467351..a8803fe9a 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `66e3e557c333423f2db0dac9bd16373b360a0034` | `UNSTABLE`; semantic HTML/Word footnote units preserved; required Checks and fresh independent approval pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `c743215cab19f6ebc4498e8162166fdb72c67f39` | `UNSTABLE`; semantic HTML/Word/OOXML footnote units preserved and body citations remain body text; required Checks and fresh independent approval pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 704d32ef7f34ed010bc1ea284bfea8c3bd724eb6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 04:44:15 +0900 Subject: [PATCH 15/22] docs: record fresh runtime aggregate evidence --- docs/product-technical-gap-baseline.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index a8803fe9a..74e166f46 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -465,3 +465,25 @@ coverage. Frontend lint, `134 passed` frontend tests, production build, and Storybook build also passed locally. GitHub's two required PR Checks are still queued and no formal approval is bound to this exact head, so this is not a merge or release claim. + +## Fresh runtime aggregate evidence: 2026-08-21 KST + +The local Compose runtime was healthy for the backend, frontend, Keycloak, +contextual-orchestrator, PostgreSQL, and Valkey at the observed development +endpoints. A bounded PostgreSQL catalog projection recorded the following +aggregate counts without exporting source text or identifiers: + +| Relation | Rows observed | +|---|---:| +| `source_post` | 43,839 | +| `post_summary_role` | 179 | +| `post_summary_person_mention` | 17 | +| `post_summary_action` | 88 | + +Within `post_summary_action`, 30 rows had a requester assignment, 45 had a +processor assignment, all 88 retained evidence text, and 85 were bound to a +project. These figures demonstrate bounded persistence in the current local +runtime; they do not prove protected-main equivalence, complete-corpus +correctness, authorization coverage, or release readiness. Re-run the same +aggregate projection against the authorized deployment before treating it as +buyer-facing evidence. From 5c5b71cfd22d7d90b2d5480cf9f074ddfb0f57da Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 05:16:27 +0900 Subject: [PATCH 16/22] docs: align runtime evidence head --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 74e166f46..e2558db7a 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `c743215cab19f6ebc4498e8162166fdb72c67f39` | `UNSTABLE`; semantic HTML/Word/OOXML footnote units preserved and body citations remain body text; required Checks and fresh independent approval pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `704d32ef7f34ed010bc1ea284bfea8c3bd724eb6` | `UNSTABLE`; semantic HTML/Word/OOXML footnote units preserved, body citations remain body text, and fresh runtime aggregate evidence is recorded; required Checks and fresh independent approval pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 4f87b109e6b423dd3429ec226403c63dfc6eac87 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 05:44:07 +0900 Subject: [PATCH 17/22] docs: record embedding provenance guard --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index e2558db7a..c0e18c183 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -424,7 +424,7 @@ are not release evidence. |---|---|---|---| | #258 | `main` -> `feat/analysis-run-name-evidence-lineage` | `49804b0fef503be1697b8be61919b022b615ef2f` | `REVIEW_REQUIRED`, `BLOCKED`; no independent approval observed | | #323 | `main` -> `fix/tepp-request-contract-validation` | `1a27efec6863cd3439a4c6023e1c625ce4d7abf2` | `REVIEW_REQUIRED`, `BLOCKED`; required Checks queued | -| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `7b710453d27286c307986fb3b0bad4ac27d7c8af` | `CLEAN`; Full test and frontend Checks SUCCESS; Devin no issues; independent approval pending | +| #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `1126cfa026876d2427a6f6cf6001eaa8ac609ad5` | `BLOCKED`; per-batch embedding model provenance reset and regression covered; required Checks and fresh independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | | #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `704d32ef7f34ed010bc1ea284bfea8c3bd724eb6` | `UNSTABLE`; semantic HTML/Word/OOXML footnote units preserved, body citations remain body text, and fresh runtime aggregate evidence is recorded; required Checks and fresh independent approval pending | From 6d32e8d8198c0de7d6536a3813ab70772f2a86d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 05:44:28 +0900 Subject: [PATCH 18/22] docs: align stacked audit head --- docs/product-technical-gap-baseline.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index c0e18c183..ae3a49860 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -427,7 +427,7 @@ are not release evidence. | #322 | `fix/stale-summary-buyer-continuity` -> `feat/orchestrator-owned-embedding-consumer` | `1126cfa026876d2427a6f6cf6001eaa8ac609ad5` | `BLOCKED`; per-batch embedding model provenance reset and regression covered; required Checks and fresh independent approval pending | | #320 | `codex/normalize-source-indent-semantics` -> `codex/preserve-partial-image-regions` | `41d164c570fe232cc1e38a766439e4093d80cb84` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | | #324 | `codex/preserve-partial-image-regions` -> `fix/validate-partial-image-regions` | `fdd62a6f8317c93f9ba5fc27393cfb26c69e584a` | `CLEAN`; Full test and frontend Checks SUCCESS; independent approval pending | -| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `704d32ef7f34ed010bc1ea284bfea8c3bd724eb6` | `UNSTABLE`; semantic HTML/Word/OOXML footnote units preserved, body citations remain body text, and fresh runtime aggregate evidence is recorded; required Checks and fresh independent approval pending | +| #325 | `fix/validate-partial-image-regions` -> `docs/current-gap-audit` | `4f87b109e6b423dd3429ec226403c63dfc6eac87` | `UNSTABLE`; semantic HTML/Word/OOXML footnote units preserved, body citations remain body text, fresh runtime aggregate evidence is recorded, and #322 provenance guard is tracked; required Checks and fresh independent approval pending | | #789 | `main` -> contextual-orchestrator embedding capability branch | `3a80d91b8c879e57d30ab87af664546b8712fb15` | `REVIEW_REQUIRED`, `BLOCKED`; upstream Checks queued | The current implementation checkpoints are local/branch evidence only: From 9dc8c7d143841a1e93459d0a5d35d6332184be0c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 10:32:48 +0900 Subject: [PATCH 19/22] docs: map buyer-reported product gaps --- docs/product-technical-gap-baseline.md | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 9b878b82a..6868a17c6 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -574,3 +574,46 @@ runtime; they do not prove protected-main equivalence, complete-corpus correctness, authorization coverage, or release readiness. Re-run the same aggregate projection against the authorized deployment before treating it as buyer-facing evidence. + +## Buyer-reported gap mapping: 2026-08-21 + +The following requirements are mapped from an authorized buyer report. The +report's post URLs and record identifiers are intentionally omitted from this +repository. Each row is a product contract to verify, not a claim that the +listed active PR has shipped on protected `main`. + +| Buyer-observed gap | Contract to close | Relevant evidence | Current state and next proof | +|---|---|---|---| +| Numeric footnotes and `li`/`oi` nesting are misclassified | Preserve a footnote unit and list depth from HTML, Word, and OOXML source evidence; visual whitespace alone cannot create hierarchy | ADR 0102/0103; PR #302 head `1a317f24f3e5905a208fdbaf273acba0d458b272`; PR #319 | Branch-local tests cover the reported shapes; run the exact stack on protected `main` and browser-check the buyer popup | +| Malformed tables lose row/column structure | Persist table rows as semantic units, keep surrounding prose, and render a valid accessible table | PR #302 head `1a317f24f3e5905a208fdbaf273acba0d458b272` | Local backend/frontend evidence exists; add a real-stack fixture with malformed closing tags and verify row order | +| Indentation is wrong or inferred from authoring alignment | Rank explicit source widths, preserve unresolved evidence, and use orchestrator adjudication only when the source does not decide | ADR 0103; PR #319; PR #324 head `53c2b2553d19be6a0573294a2a9e9e693cdc4d2f` | Parser contracts are covered locally; verify mixed HTML/CSS/OOXML fixtures and persisted decision sources in PostgreSQL | +| Two projects are mixed into one event stream | Bind event actions and project labels only to a same-post project mention; retain unbound status when evidence is ambiguous | ADR 0111/0112; PR #308 head `90b967d1ef9e4bad362b87c4c4ec3973f2a706fd` | Project binding is branch-local; acceptance still needs two-project source-backed data with aggregate, non-identifying counts | +| Partner/customer/supplier roles and 5W1H are incomplete | Keep actor type, affiliation, role, direction, time, place, method, and reason as separate nullable evidence fields; never infer a relationship from a display label alone | ADR 0006-0010, 0026-0027, 0052, 0084; FR-06/FR-11 | Existing ontology contracts cover parts of the model; a corpus acceptance run must report bound, ambiguous, and absent fields separately | +| Image tables are flattened and visual regions are shallow | Preserve OCR rows, parent-image placement, bounded region coordinates, region evidence, tags, and separate searchable embeddings; fallback must remain explicit | ADR 0077, 0104, 0110; PR #303 head `ba71bc16a1ec796dd6b8cd22236b9185589a4328`; PR #307; PR #309; PR #320 | The OCR colon-containing multiline loss was fixed and tested on #303; region decomposition remains unproven until authorized runtime evidence shows meaningful non-full-image boxes | +| Markdown generated from image OCR is not rendered as a table | Parse only a bounded Markdown table shape, preserve prose, escape pipe characters, and expose header cells with accessible table semantics | PR #303 head `ba71bc16a1ec796dd6b8cd22236b9185589a4328` | Frontend tests/build pass locally; verify the same persisted OCR projection through the browser journey | +| Acronyms, canonical names, translations, and external corroboration are disconnected | Persist normalized aliases and language links separately from entity identity; attach SearXNG corroboration as provenance with source, time, and status | ADR 0008, 0009, 0005; PR #316; PR #327 | Active branches are proposals; require exact-head checks and aggregate alias/corroboration outcomes before claiming search parity | +| A PM mention lacks a person and affiliated organization | Represent person, team, organization, title, and affiliation as separate nodes/edges; preserve same-name ties and do not auto-create on ambiguity | ADR 0006-0010, 0026-0027; PR #258 | The schema boundary exists; buyer acceptance needs a bound/ambiguous/unavailable projection with no real names in repository artifacts | +| Major events, R&R, requester/processor, and Git-like DAG are incomplete | Persist event evidence, requester/processor assignments, project scope, and directed parent/branch lineage with source navigation | ADR 0100, 0084; PR #287; PR #308; PR #330 | Action/project work is branch-local; verify the complete popup and Event Lineage graph in a browser against authorized aggregate evidence | +| Who/what/how/payment details are missing | Add evidence-bearing fields for actor, action, method, payer, payee, amount/currency, and payment basis; keep unknown values null | ADR 0006, 0011, 0052, 0084 | This remains an open schema/product gap; write an ADR and migration only after an anonymized acceptance fixture defines the evidence contract | +| Superscript/subscript mathematical units are not semantically explicit | Preserve MathML-compatible structure and a searchable normalized expression while retaining source presentation and unit semantics | ADR 0011, 0065, and the existing standards register | Open gap; first add a research-grounded ADR and parser contract for a synthetic `m³`/subscript fixture, then implement the smallest verified boundary | + +### Evidence and research boundary + +The implementation decisions above remain governed by the linked ADRs. Their +APA 7th bibliographies and open-access research register are maintained in +[`docs/lineage-bi-research-notes.md`](lineage-bi-research-notes.md) and the +individual ADRs; this checkpoint adds no provider-quality claim beyond those +sources. W3C PROV-O, W3C Organization, W3C Time, and the paper-grounded +contextual-orchestrator policy remain the normative boundaries. A local test, +active PR, queued Check, or private aggregate observation is never promoted to +protected-main or release evidence. + +### Exact-head gate snapshot + +At this checkpoint the relevant active heads above have no independent formal +approval and their required Checks are non-terminal or otherwise gated. The +review loop remains: re-fetch the branch and dependency head, inspect current +review findings, apply a minimal root-cause fix when needed, re-run local and +hosted Checks, and merge only after normal protected-repository approval and +post-merge SHA checks succeed. No self-approval, administrative bypass, force +push, or synthetic runtime success is acceptable. From 19b4958ea99b20dc7a4fa60e44e352c2b3a8767d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 10:41:40 +0900 Subject: [PATCH 20/22] docs: record exact heads from review loop --- docs/product-technical-gap-baseline.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 6868a17c6..91c80bc32 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -617,3 +617,14 @@ review findings, apply a minimal root-cause fix when needed, re-run local and hosted Checks, and merge only after normal protected-repository approval and post-merge SHA checks succeed. No self-approval, administrative bypass, force push, or synthetic runtime success is acceptable. + +| Audited PR | Current head at this loop | Local evidence | Protected gate | +|---|---|---|---| +| #303 image evidence | `ba71bc16a1ec796dd6b8cd22236b9185589a4328` | Backend `747 passed, 16 skipped`; frontend `139 passed`, lint, Vite, and Storybook passed | No approval; required Checks queued | +| #323 TEPP/SearXNG boundary | `061e62130e3d6fc3e6bb3a5c0d941a0c7aac85cd` | Focused TEPP/relation/start tests `50 passed`; compileall and diff check passed | No approval; required Checks queued | +| #325 gap baseline | `9dc8c7d143841a1e93459d0a5d35d6332184be0c` | Documentation diff check passed | No approval; required Checks queued | +| #340 Naruon provider contract | `1e792a761f96e2184394a15f112cc947c7661c41` | Contract tests `11 passed`; module coverage `100%`; compileall and diff check passed | No approval; required Checks queued | + +These four rows are exact-head observations from the current review loop. They +do not establish that any behavior is present on protected `main`; re-fetch all +heads and dependency bases before the next review or merge decision. From 64ce5fbac4ed9c6233ecaab475d6702080a8e7e2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 10:49:00 +0900 Subject: [PATCH 21/22] docs: track metric script gap PR --- docs/product-technical-gap-baseline.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 91c80bc32..3cad6334e 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -624,6 +624,7 @@ push, or synthetic runtime success is acceptable. | #323 TEPP/SearXNG boundary | `061e62130e3d6fc3e6bb3a5c0d941a0c7aac85cd` | Focused TEPP/relation/start tests `50 passed`; compileall and diff check passed | No approval; required Checks queued | | #325 gap baseline | `9dc8c7d143841a1e93459d0a5d35d6332184be0c` | Documentation diff check passed | No approval; required Checks queued | | #340 Naruon provider contract | `1e792a761f96e2184394a15f112cc947c7661c41` | Contract tests `11 passed`; module coverage `100%`; compileall and diff check passed | No approval; required Checks queued | +| #344 metric script semantics | `922a38405e3f89779a0a70974a6ad1f8f2bb4793` | Backend focused `74 passed`; frontend focused `29 passed`, lint, and Vite build passed | Stacked on #303; no approval; required Checks queued | These four rows are exact-head observations from the current review loop. They do not establish that any behavior is present on protected `main`; re-fetch all From 659bf4d56783769c4e550c7177bdeb5e216ab9e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 21 Aug 2026 02:08:43 -0700 Subject: [PATCH 22/22] docs: record current exact-head gap checkpoint (#335) * docs: record current exact-head gap checkpoint * docs: retain current buyer stack roots * docs: record current exact-head review gates * docs: refresh current queue roots * docs: record buyer-stack restack * docs: record MCP key boundary closure --- docs/product-technical-gap-baseline.md | 226 ++++++++++++++++++++++++- 1 file changed, 220 insertions(+), 6 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 3af885367..9283f343b 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,12 +1,12 @@ # Product & Technical Gap Baseline -**Snapshot:** 2026-08-21 05:46 (Asia/Seoul) +**Snapshot:** 2026-08-21 11:57 (Asia/Seoul) **Protected-main baseline:** `origin/main`, product version `2.12.5` -**Audited PR head:** #258 at `b83be708a9dc705df7485e1b18e779439bfb7b71` (current exact branch head; protected-main runtime evidence remains pending) -**Active PR update:** Hosted Full test, frontend, PROV-O, CodeQL, SAST, supply-chain, -and security Checks are successful on the current #258 head; Devin Review is -failed and the OpenCode coverage check remains pending. Formal approval and -protected-main acceptance are still required. +**Audited PR head:** #258 at `99244658bc7edb7cf0c71cce2e3dcc59ff891b2b` (current exact branch head; protected-main runtime evidence remains pending) +**Active PR update:** At this snapshot, PR #258 has one failed check (`Devin Review`), +fourteen queued checks, seven skipped scheduler jobs, and successful CodeRabbit; +no formal approval or protected-main acceptance is present. The current queue +inventory below is a point-in-time gate record, not a merge or release claim. **Purpose:** connect the normative ADRs and research evidence to product requirements, technical contracts, implementation evidence, and active PRs. An active PR is proposed work, not shipped behavior. @@ -593,6 +593,138 @@ correctness, authorization coverage, or release readiness. Re-run the same aggregate projection against the authorized deployment before treating it as buyer-facing evidence. +## Current continuation checkpoint: 2026-08-21 08:39 KST + +This section supersedes the older PR snapshot above for the PRs explicitly +re-audited in the current continuation loop. GitHub state is authoritative; +local tests below are branch-local evidence and are not merge evidence. + +| PR | Exact head | Base | Current gate | Current evidence | +|---|---|---|---|---| +| #270 authenticated MCP Global Ask | `1881a3cc402d99d8494bd9b936be9099b43ca3e7` | `feat/event-lineage-node-keeps-gnb-focus-v2170` | BLOCKED; review decision empty | Local MCP/auth/Global Ask regression set: 45 passed; import-order correction pushed | +| #325 product/technical baseline | `d80d691cd8ed780a8fb0072199304f595b1ea75e` | `fix/validate-partial-image-regions` | BLOCKED; REVIEW_REQUIRED | This document, ADR 0102, and chunking changes are proposed, not on protected main | +| #328 member locale bootstrap | `d0e159872147c7d7bd8bbf042c5552041eb44a4a` | `fix/oidc-deep-link-locale` | BLOCKED; REVIEW_REQUIRED | Local Frontend locale/deep-link set: 82 passed; TypeScript and lint passed | +| #329 buyer-safe image evidence | `b5b08071ab869854da696566343e97feb04add20` | `fix/validate-partial-image-regions` | BLOCKED; REVIEW_REQUIRED | Local image/normalization/persistence set: 54 backend tests and 13 PostBody tests passed | +| #330 lineage DAG interaction coverage | `e14dd956ad2493c42a16076a2adc095e0df5733b` | `codex/normalize-source-indent-semantics` | BLOCKED; REVIEW_REQUIRED | Frontend regression-only PR; hosted gate and independent review remain required | +| #331 OIDC post deep-link regression | `72e842bad482b73974d8ab4f09d2385582c300d6` | `fix/member-locale-bootstrap-race` | BLOCKED; REVIEW_REQUIRED | Deep-link stack remains proposed and must be checked at its exact head | +| #333 Keyverse-authenticated MCP API keys | `236b83b5af9632f83457dcc822b792dc239bcc7a` | `feat/analysis-run-name-evidence-lineage` | BLOCKED; review decision empty | Remote agent added malformed-revoke coverage; hosted Checks restarted | +| #334 MCP API-key authentication | `89f19eb1378ac785b80ea344d6f4e6e2bbe4a312` | `agent/authenticated-mcp-global-ask` | BLOCKED; REVIEW_REQUIRED | Depends on #333 migration 0051; local full backend suite: 825 passed, 16 skipped | + +### Current closure order + +1. Revalidate each exact head after any remote-agent push; never use the older + hash as merge evidence. +2. Merge #258 and its dependent buyer-surface stack only through the repository's + required independent review and terminal Checks. Do not treat local evidence, + a skipped review, or a queued workflow as approval. +3. Deploy #333's normalized `mcp_api_key` resource before enabling the API-key + authentication path in #334. OIDC remains the fallback identity path when + the key table is not installed. +4. After the relevant stack reaches protected main, run the real browser journey: + login screen first, locale preference restoration, GNB navigation, source + post popup, semantic image evidence, and MCP authorization. Record only + aggregate non-identifying evidence here. + +### Newly explicit product gaps + +- The MCP key lifecycle and MCP bearer verifier are separate PRs and are not yet + jointly deployable on protected main. +- The locale and OIDC deep-link fixes are separate dependent PRs; local tests do + not prove that a logged-in browser session preserves `?post=` on the deployed + stack. +- Buyer-safe image captions are covered locally, but region-level visual evidence + and buyer rendering still require post-merge browser evidence. +- The older aggregate runtime table remains historical. It must not be cited as + proof that the current PR heads or protected main contain these changes. + +### Queue roots carried forward from the prior checkpoint + +The current root entries from the preceding queue audit were revalidated before +this update and remain proposed, not shipped: + +| PR | Exact head | Current gate | +|---|---|---| +| #258 buyer evidence board and ontology surface | `41036e2cd8095c5e7b9c333fd72c542cb676ef5e` | BLOCKED; REVIEW_REQUIRED | +| #309 persisted buyer image-region overlays | `d8a938cd6e7e72b8bc0a7b11149afcfcc7820270` | BLOCKED; REVIEW_REQUIRED | + +This continuation checkpoint supersedes the earlier #332 documentation-only +snapshot by retaining its root-head evidence and adding the later MCP, locale, +image-caption, and DAG gate state above. + +## Current exact-head continuation: 2026-08-21 09:09 KST + +The review/fix loop re-fetched the independent roots and the status-clock +dependent stack after concurrent branch updates. The following are the only +current hashes used as merge evidence in this loop: + +| PR | Exact head | Base | Local evidence | Hosted gate | +|---|---|---|---|---| +| #258 buyer evidence board and ontology surface | `41036e2cd8095c5e7b9c333fd72c542cb676ef5e` | `main@2feba74b75863810869cde680b19032a93fba413` | Python `718 passed, 16 skipped`; cleanup branch coverage `100%`; focused suite `18 passed` | required workflows queued; no formal approval; Devin review failure remains unresolved as a review gate | +| #323 TEPP request and search evidence boundaries | `3b57e1cad490b47496d0c25553d28a0c1e3e2ca3` | `main@2feba74b75863810869cde680b19032a93fba413` | Python `570 passed, 16 skipped, 4 warnings`; boolean contract-version regression added | Tests, Semgrep, and Security Scan queued; Devin is a comment-only review, not formal approval | +| #327 Searxng corroboration token precision | `e6ef7cc53bcfef1e3dd61705b9ab243251860730` | `main@2feba74b75863810869cde680b19032a93fba413` | Python `573 passed, 16 skipped`; focused relation suite `25 passed`; isolated line/branch coverage `100%` | required workflows queued; comment-only reviews; no formal approval | +| #326 Python-ahead status write clock | `f9c53e7c18a696260d60bfcdd7c0af5e07c1dda6` | `#327@e6ef7cc53bcfef1e3dd61705b9ab243251860730` | stacked Python `578 passed, 16 skipped, 4 warnings`; clock boundary tests `5 passed`; additive `0030` fixture path exercised | required workflows queued after the new exact head; no formal approval | + +Claude's #323 review found no confirmed correctness, security, data-loss, or +authorization defect. The proposed SHA-format concern was checked against +TEPP's current published request schema and dismissed because `snapshot_id` +is specified as non-blank text, not as a SHA. The confirmed boolean type-test +gap was closed in #323. Claude's #326 review found no high-severity defect; +the valid CodeRabbit upgrade-path finding was closed by running migration +`0030` in the PostgreSQL fixture and testing 59 seconds, exactly one minute, +and two minutes. + +These results are branch-local observations and hosted queue/review state; +they are not protected-main or release evidence. The next merge candidate is +#258 only after its exact current head has independent formal approval, +resolved review threads, and terminal required Checks. #327 is an independent +root that must be merged before #326; #323 can proceed independently. A queued +workflow is active work, not a blocker or a pass. + +## Restack continuation: 2026-08-21 09:23 KST + +PR #258 advanced normally after the ADR 0083 pin correction. Its current head +is now `4bb234476ca26aacdd645f3c495a161a2c441790`. The semantic-unit child +PR #302 was merged normally with that current base and now has exact head +`8e1bd783fa2cb3e565983fc3d7b9092d394ff814`; its local validation is Python +`740 passed, 16 skipped, 4 warnings`, frontend `137 passed`, lint/build/ +Storybook passed, and chunking coverage remains 100%. + +The #302 restack carries #258's reviewed immutable orchestrator pin and ADR +regression check. Hosted Checks and independent formal approval remain +required for both exact heads; no merge or protected-main claim is made. + +## Current queue refresh: 2026-08-21 09:21 KST + +The live queue now contains 45 open pull requests. The following branches were +opened or advanced after the preceding checkpoint and therefore must be +included in the next exact-head audit; this document does not treat any of +them as merge-ready: + +| PR | Exact head | Base | Gate at refresh | +|---|---|---|---| +| #335 current exact-head gap checkpoint | `858f7e4913824b9899710bc5b1e51bc49b43ce52` | `docs/current-gap-audit@d80d691cd8ed780a8fb0072199304f595b1ea75e` | BLOCKED; REVIEW_REQUIRED; required Checks queued | +| #337 Naruon calendar event projection contract | `974cf8b4a5618a43b17584ab762af6630ee4acd0` | `feat/calendar-open-focus-event-lineage-v2140@221cc94db3780e82114ef553729c7a00da554532` | BLOCKED; REVIEW_REQUIRED; required Checks queued | +| #339 TEPP canonical Project history recovery | `26b83f06899a2ad416be746d9a6fb13042bb7659` | `feat/project-history-timeline-v2184-r3@cfc125cb65f26ed7e834976dbff12b6b9790b59c` | BLOCKED; REVIEW_REQUIRED; required Checks queued | + +The queue count and gate fields are a point-in-time GitHub observation. Before +reviewing or merging any row, fetch its branch again, compare the exact head +with the review and all required Checks, and confirm the full dependency stack. + +## Security-boundary continuation: 2026-08-21 09:40 KST + +PR #333's MCP key lifecycle was re-reviewed with Claude and its confirmed +medium metadata leak was fixed. Exact current head is +`065d14f5022f052d8b096f4388a62cb227d12d9e`, based on #258's current +`4bb234476ca26aacdd645f3c495a161a2c441790`. The key table and application +now persist/display only the constant `lw_mcp_` family prefix, while the +random secret remains one-time creation output; the buyer's date-only expiry +is converted to the local calendar day's end. + +Post-fix validation is Python `725 passed, 16 skipped, 4 warnings`, frontend +`132 passed`, MCP panel `3 passed`, lint/build/Storybook passed, and diff check +passed. These are branch-local results. #333 remains gated until exact-head +hosted Checks and independent formal approval are terminal-successful; #334 +must not enable API-key authentication before migration `0051` is deployed. ## Buyer-reported gap mapping: 2026-08-21 The following requirements are mapped from an authorized buyer report. The @@ -647,6 +779,88 @@ push, or synthetic runtime success is acceptable. These four rows are exact-head observations from the current review loop. They do not establish that any behavior is present on protected `main`; re-fetch all heads and dependency bases before the next review or merge decision. +## Live exact-head inventory: 2026-08-21 11:57 KST + +GitHub reported 48 open pull requests and 13 open issues at this snapshot. The +following inventory records every open PR head and its advertised base SHA so +the next loop can re-fetch the exact branch before review, repair, Checks, or a +protected merge. A blank or non-terminal GitHub mergeability value is not +treated as merge-ready. The `#335` base branch also requires special care: +GitHub's pull-request payload still advertised `c0b8f533`, while the fetched +`docs/current-gap-audit` branch resolved to `64ce5fba`; the branch ref, not a +stale payload, is the source for the next restack. + +| PR | Head branch @ exact head | Advertised base branch @ SHA | +|---:|---|---| +| #346 | `feat/uiux-standard-guide-v3` @ `73d808113d2a1980dc20bb040c661c9a1cf74324` | `main` @ `2feba74b75863810869cde680b19032a93fba413` | +| #345 | `fix/otel-session-telemetry` @ `228ac9e6c54a0f7dc917b2ed392ee98feb02d466` | `fix/buyer-safe-image-captions` @ `9b7ef93a4708993c7d5af28c67c28b227f59437a` | +| #344 | `feat/math-semantic-units` @ `efcf16920d33b72242db664273a7b16dbd3218fa` | `feat/image-evidence-markdown-semantics` @ `d8e8ede425d6b7373b678776e5ccaeef83f7cec5` | +| #343 | `feat/external-lineage-integration-contract` @ `cbc65a903cf46e863ea66bb601a97b9051e408dc` | `main` @ `2feba74b75863810869cde680b19032a93fba413` | +| #342 | `feat/project-history-ask-surfaces-v2200` @ `bd9e965e3943ea19a115d53c0a8f39a0f70968d6` | `feat/tepp-project-history-recovery-v2210` @ `43262dc76622928fdf90b922653949b4ac7c6631` | +| #340 | `feat/lineage-provider-contract-v1` @ `1e792a761f96e2184394a15f112cc947c7661c41` | `main` @ `2feba74b75863810869cde680b19032a93fba413` | +| #339 | `feat/tepp-project-history-recovery-v2210` @ `43262dc76622928fdf90b922653949b4ac7c6631` | `feat/project-history-timeline-v2184-r3` @ `cfc125cb65f26ed7e834976dbff12b6b9790b59c` | +| #337 | `feat/naruon-calendar-projection-contract` @ `44517b30d76dc2ac66c496b9b3cf6436b7955cd0` | `feat/calendar-open-focus-event-lineage-v2140` @ `221cc94db3780e82114ef553729c7a00da554532` | +| #335 | `docs/current-gap-audit-current-checkpoint` @ `c43edff228878361a8d09b793aec4e7c85537d93` | `docs/current-gap-audit` @ `c0b8f5330ff3940b7a8907756a8ca4e5549dfde9` | +| #331 | `feat/locale-deep-link-regression` @ `72e842bad482b73974d8ab4f09d2385582c300d6` | `fix/member-locale-bootstrap-race` @ `d0e159872147c7d7bd8bbf042c5552041eb44a4a` | +| #330 | `feat/lineage-dag-regression` @ `f9df5ead44a2f2b1fd3b578bfd20f2fad15bb8aa` | `codex/normalize-source-indent-semantics` @ `e3f00eaae9255f5f56eaa5d93b6fa2ea6ea3e8c5` | +| #329 | `fix/buyer-safe-image-captions` @ `9b7ef93a4708993c7d5af28c67c28b227f59437a` | `fix/validate-partial-image-regions` @ `53c2b2553d19be6a0573294a2a9a9e693cdc4d2f` | +| #328 | `fix/member-locale-bootstrap-race` @ `d0e159872147c7d7bd8bbf042c5552041eb44a4a` | `fix/oidc-deep-link-locale` @ `3a32312b9cf9e368c58d7df5efb0c699dfe73152` | +| #327 | `fix/searxng-corroboration-token-precision` @ `e6ef7cc53bcfef1e3dd61705b9ab243251860730` | `main` @ `2feba74b75863810869cde680b19032a93fba413` | +| #326 | `fix/analysis-run-status-write-clock-v2126` @ `f9c53e7c18a696260d60bfcdd7c0af5e07c1dda6` | `fix/searxng-corroboration-token-precision` @ `e6ef7cc53bcfef1e3dd61705b9ab243251860730` | +| #325 | `docs/current-gap-audit` @ `64ce5fbac4ed9c6233ecaab475d6702080a8e7e2` | `fix/validate-partial-image-regions` @ `53c2b2553d19be6a0573294a2a9a9e693cdc4d2f` | +| #324 | `fix/validate-partial-image-regions` @ `53c2b2553d19be6a0573294a2a9a9e693cdc4d2f` | `codex/preserve-partial-image-regions` @ `cf7331ae25544f660ecad11a4fc965f9cef107f1` | +| #323 | `fix/tepp-request-contract-validation` @ `eb1fc2a473ea2401a7cd259f08a22c6e257438ef` | `main` @ `2feba74b75863810869cde680b19032a93fba413` | +| #322 | `feat/orchestrator-owned-embedding-consumer` @ `1c46edad6832e766f3a6f54d45a88b1a173dda78` | `fix/stale-summary-buyer-continuity` @ `17ff91195c921f3967bd22fb15dd58764519f45a` | +| #320 | `codex/preserve-partial-image-regions` @ `cf7331ae25544f660ecad11a4fc965f9cef107f1` | `codex/normalize-source-indent-semantics` @ `e3f00eaae9255f5f56eaa5d93b6fa2ea6ea3e8c5` | +| #319 | `codex/normalize-source-indent-semantics` @ `e3f00eaae9255f5f56eaa5d93b6fa2ea6ea3e8c5` | `codex/post-structure-case-fixes` @ `1faed2f680fa6d7bbe946a1a884522757d1639d6` | +| #318 | `feat/verified-organization-label-evidence` @ `8ad157b43d0d33515e719860d32c7f14aabe5623` | `feat/multilingual-organization-label-search` @ `78434ce251cedd3d1dceb168603d9f2bc06f3438` | +| #317 | `codex/post-structure-case-fixes` @ `1faed2f680fa6d7bbe946a1a884522757d1639d6` | `codex/fix-mixed-body-indentation-311` @ `e38df6256f03db06a9fe8dd07a8ab212540ea4c9` | +| #316 | `feat/multilingual-organization-label-search` @ `78434ce251cedd3d1dceb168603d9f2bc06f3438` | `feat/global-ask-public-claim-verification-v2200` @ `41ad3b758618354457ff11641b52d1def290d1d1` | +| #314 | `codex/fix-mixed-body-indentation-311` @ `254c2b131740cbdf94c4ce89707d5298553fcfbd` | `fix/stale-summary-buyer-continuity` @ `17ff91195c921f3967bd22fb15dd58764519f45a` | +| #311 | `fix/stale-summary-buyer-continuity` @ `17ff91195c921f3967bd22fb15dd58764519f45a` | `fix/project-bound-summary-actions` @ `46ca53333963a725e9d38eef020800bba6ebb1ec` | +| #309 | `feat/buyer-image-region-overlays` @ `75047741371c969d4e2114a34ddf9385d8412e96` | `fix/buyer-image-evidence` @ `fbecd77358c95ebaea02b4a87e32b795c70d5e15` | +| #308 | `fix/project-bound-summary-actions` @ `90b967d1ef9e4bad362b87c4c4ec3973f2a706fd` | `fix/buyer-image-evidence` @ `fbecd77358c95ebaea02b4a87e32b795c70d5e15` | +| #307 | `fix/buyer-image-evidence` @ `fbecd77358c95ebaea02b4a87e32b795c70d5e15` | `fix/oidc-deep-link-locale` @ `4e40e267f0e255f55e923ace97ece1e9963e8640` | +| #306 | `fix/oidc-deep-link-locale` @ `dab3994ee49f299e86c4543a8c33845fe8d92eb8` | `feat/analysis-run-name-evidence-lineage` @ `4bb234476ca26aacdd645f3c495a161a2c441790` | +| #303 | `feat/image-evidence-markdown-semantics` @ `d8e8ede425d6b7373b678776e5ccaeef83f7cec5` | `feat/buyer-evidence-gap-structure` @ `1a317f24f3e5905a208fdbaf273acba0d458b272` | +| #302 | `feat/buyer-evidence-gap-structure` @ `1a317f24f3e5905a208fdbaf273acba0d458b272` | `feat/analysis-run-name-evidence-lineage` @ `99244658bc7edb7cf0c71cce2e3dcc59ff891b2b` | +| #301 | `feat/global-ask-knowledge-cutoff-v2230` @ `d51093c1cacd2250c9fa758877ee8fb6e6688ccd` | `feat/event-lineage-node-keeps-gnb-focus-v2170` @ `2ff882642565bae3f5443c40dc4d0f9328a2653a` | +| #298 | `feat/bounded-async-lineage-llm-rebuild-v2220` @ `5c5544ed6ffbc2d6c76d62add794dc4d585ebd05` | `feat/global-ask-public-claim-verification-v2200` @ `139cd24cbdc5282230ce0619617d113914efa7d6` | +| #287 | `feat/event-lineage-channel-evidence-v2210` @ `c01dedf654ef33beb9a2117a5b02b064c85ff89d` | `feat/global-ask-public-claim-verification-v2200` @ `139cd24cbdc5282230ce0619617d113914efa7d6` | +| #286 | `feat/mcp-browser-admission-v2131` @ `8be7fbb763eb256367828461b10ed39d716783e2` | `agent/authenticated-mcp-global-ask` @ `e1c31db3387ec051e6327332d373293242b9e5eb` | +| #285 | `feat/project-history-timeline-v2184-r3` @ `68ca6cb63ef8915418eb62fb356cbab010d9e751` | `feat/event-lineage-node-keeps-gnb-focus-v2170` @ `2ff882642565bae3f5443c40dc4d0f9328a2653a` | +| #276 | `feat/global-ask-public-claim-verification-v2200` @ `139cd24cbdc5282230ce0619617d113914efa7d6` | `feat/gnb-event-lineage-focus-keyman-v2190` @ `259b3b0d073eaa4c050ee5459a95ebb815a43f4f` | +| #275 | `feat/evidence-bound-event-intelligence-v2183` @ `68974f5c71d0499fac1a52595880e803199a306b` | `agent/authenticated-mcp-global-ask` @ `e1c31db3387ec051e6327332d373293242b9e5eb` | +| #270 | `agent/authenticated-mcp-global-ask` @ `e1c31db3387ec051e6327332d373293242b9e5eb` | `feat/event-lineage-node-keeps-gnb-focus-v2170` @ `bcdc4594abe467627c71378adeceb61624d02d67` | +| #266 | `feat/gnb-event-lineage-focus-keyman-v2190` @ `259b3b0d073eaa4c050ee5459a95ebb815a43f4f` | `feat/event-lineage-node-keeps-gnb-focus-v2170` @ `bcdc4594abe467627c71378adeceb61624d02d67` | +| #264 | `feat/event-lineage-node-keeps-gnb-focus-v2170` @ `bcdc4594abe467627c71378adeceb61624d02d67` | `feat/ask-agent-open-focus-event-lineage-v2160` @ `457e7e121adb79424f382a9868a84f6fb6e402f2` | +| #263 | `feat/ask-agent-open-focus-event-lineage-v2160` @ `457e7e121adb79424f382a9868a84f6fb6e402f2` | `feat/customer-master-open-focus-event-lineage-v2150` @ `cc0a8907b74bfa2d9757e321a91fd06bff39e442` | +| #262 | `feat/customer-master-open-focus-event-lineage-v2150` @ `cc0a8907b74bfa2d9757e321a91fd06bff39e442` | `feat/calendar-open-focus-event-lineage-v2140` @ `6c4d48dfd9eccae81f4809adf52cad51eb4c394b` | +| #261 | `feat/calendar-open-focus-event-lineage-v2140` @ `6c4d48dfd9eccae81f4809adf52cad51eb4c394b` | `feat/board-weekly-voc-open-event-lineage-v2130` @ `b7625c3dd3c6dce6f6a933f0479740a3006450e8` | +| #260 | `feat/board-weekly-voc-open-event-lineage-v2130` @ `b7625c3dd3c6dce6f6a933f0479740a3006450e8` | `feat/analysis-run-name-evidence-lineage` @ `99244658bc7edb7cf0c71cce2e3dcc59ff891b2b` | +| #258 | `feat/analysis-run-name-evidence-lineage` @ `99244658bc7edb7cf0c71cce2e3dcc59ff891b2b` | `main` @ `2feba74b75863810869cde680b19032a93fba413` | +| #192 | `feat/related-node-plural-next-action` @ `5b1f6da236fd46a6effffd251aad804d75738c3c` | `feat/analysis-run-name-evidence-lineage` @ `4bb234476ca26aacdd645f3c495a161a2c441790` | + +The inventory is refreshed before every merge decision. It intentionally does +not assert that an open PR is merge-ready; review approval, all required +terminal Checks, exact dependency heads, and post-merge SHA verification remain +independent gates. + +## Live queue delta: 2026-08-21 12:03 KST + +The next read found the same aggregate queue size (48 open PRs and 13 open +issues), but PR #346 is now closed and a replacement UI stack is open as PR +#347. The exact current #347 head is +`dd7156dadf62d5eff79def3aff2108f7d33e7e7d`, based on `main` at +`2feba74b75863810869cde680b19032a93fba413`; GitHub still reports its +mergeability as non-terminal. PR #345 remains at +`228ac9e6c54a0f7dc917b2ed392ee98feb02d466`, #344 at +`efcf16920d33b72242db664273a7b16dbd3218fa`, #342 at +`bd9e965e3943ea19a115d53c0a8f39a0f70968d6`, #339 at +`43262dc76622928fdf90b922653949b4ac7c6631`, and #335 at +`c43edff228878361a8d09b793aec4e7c85537d93`. These are queue observations; +none is a protected merge or release claim. + ### Provider-error checkpoint Provider failures are not buyer evidence. The API and browser boundaries must