From 54a3b2943bcfe3a48ecc705fe7fa32d915f6d0be Mon Sep 17 00:00:00 2001 From: Jeongkyu Shin Date: Fri, 14 Aug 2026 00:30:51 +0900 Subject: [PATCH 1/2] chore(docs): guard the docs-* targets and document the manual split The thirteen `docs-*` targets build the MkDocs manual from sources (`docs/en`, `docs/ko`, `docs/shared`, `docs/requirements.txt`, `docs/scripts`) that are maintained in a separate documentation tree and are not part of this repository. Running one here failed partway through: `make docs-install` died inside `uv pip install -r docs/requirements.txt`, and working around that hit a broken symlink and then a site build against a nonexistent `docs_dir`. Nothing said the manual was built elsewhere, so the only way to find out was to run a target and read the failure. All thirteen now depend on a shared `docs-guard` prerequisite. The guard is a presence check on `docs/en`, not an unconditional refusal: where the sources exist the targets run exactly as before, and where they do not the build stops immediately with a message naming what is missing, why the configs' `nav:` entries do not describe this tree, and where to read the published manual. One Makefile stays correct in both trees. Each `##` help string gains a short suffix so `make help` no longer advertises thirteen working targets. The four mkdocs configs are left unchanged. They belong to the tree that owns the manual, so rewriting their `nav:` blocks to point at the top-level `docs/*.md` files here would be wrong for that tree and undone by the next sync. `docs/README.md` gains a "The MkDocs manual" section explaining the split: the top-level `docs/*.md` files are the GitHub-facing documents that live here, the manual is built elsewhere, and the configs' `docs_dir`, `custom_dir`, and `nav:` entries are paths into that other tree. `docs/en/...` and `docs/ko/...` move out of "Expected future layout examples" for the same reason, since they describe a tree that exists rather than a layout this repository is heading toward. The GitHub-facing documents themselves are unchanged. Verified by running all thirteen targets (each stops at the guard with exit 1 and no `uv` or `zensical` invocation), by re-running the guard with a `docs/en` directory present to confirm it passes, and by reading `make help`. Closes #1111 --- Makefile | 55 ++++++++++++++++++++++++++++++++++++++------------ docs/README.md | 23 +++++++++++++++++++-- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 06ef196c5..7d59ac9c9 100644 --- a/Makefile +++ b/Makefile @@ -824,9 +824,38 @@ webpage-deploy: ## Deploy download webpage to GitHub Pages # ============================================================================ # Documentation (Zensical / MkDocs-compatible) # ============================================================================ +# +# The docs-* targets below build the MkDocs manual. Its sources (docs/en, +# docs/ko, docs/shared, docs/requirements.txt, docs/scripts) are maintained in a +# separate documentation tree and are not part of this repository, so every one +# of these targets depends on docs-guard. The guard is a presence check, not an +# unconditional refusal: where the sources exist the targets run exactly as +# before, and where they do not the build stops with an explanation instead of +# an opaque uv, ln, or zensical failure. See docs/README.md for the split. + +DOCS_MANUAL_DIR := docs/en +DOCS_MANUAL_URL := https://mlxcel.lablup.ai/en/manual/ + +.PHONY: docs-guard +docs-guard: + @test -d "$(DOCS_MANUAL_DIR)" || { \ + echo "The MkDocs manual sources are not present in this checkout."; \ + echo ""; \ + echo " '$(DOCS_MANUAL_DIR)' is missing, and so are docs/ko, docs/shared,"; \ + echo " docs/requirements.txt and docs/scripts. They are maintained in a"; \ + echo " separate documentation tree, along with its own copies of mkdocs.yml,"; \ + echo " mkdocs.ko.yml and the two PDF configs. The docs_dir, custom_dir and"; \ + echo " nav: entries in the configs kept here name paths in that tree, not the"; \ + echo " docs/*.md files in this repository, so no docs-* target can build"; \ + echo " anything from this checkout."; \ + echo ""; \ + echo " Read the published manual instead: $(DOCS_MANUAL_URL)"; \ + echo " The documents that do live here are indexed in docs/README.md."; \ + exit 1; \ + } .PHONY: docs-install -docs-install: ## Install documentation dependencies and create shared symlinks +docs-install: docs-guard ## Install documentation dependencies and create shared symlinks (manual sources not in this checkout) @command -v uv >/dev/null 2>&1 || { \ echo "Error: uv is not installed. Install it from https://docs.astral.sh/uv/"; \ exit 1; \ @@ -838,30 +867,30 @@ docs-install: ## Install documentation dependencies and create shared symlinks @echo "Documentation dependencies installed and symlinks created. Run 'make docs-serve' to start the server." .PHONY: docs-serve -docs-serve: ## Serve all docs locally (builds KO first, then serves EN) +docs-serve: docs-guard ## Serve all docs locally, builds KO first then serves EN (manual sources not in this checkout) @echo "Building Korean docs..." uv run zensical build -f mkdocs.ko.yml @echo "Serving English docs..." uv run zensical serve -f mkdocs.yml .PHONY: docs-serve-en -docs-serve-en: ## Serve English docs with live reload +docs-serve-en: docs-guard ## Serve English docs with live reload (manual sources not in this checkout) uv run zensical serve -f mkdocs.yml .PHONY: docs-serve-ko -docs-serve-ko: ## Serve Korean docs with live reload +docs-serve-ko: docs-guard ## Serve Korean docs with live reload (manual sources not in this checkout) uv run zensical serve -f mkdocs.ko.yml .PHONY: docs-build -docs-build: ## Build English docs +docs-build: docs-guard ## Build English docs (manual sources not in this checkout) uv run zensical build -f mkdocs.yml .PHONY: docs-build-ko -docs-build-ko: ## Build Korean docs +docs-build-ko: docs-guard ## Build Korean docs (manual sources not in this checkout) uv run zensical build -f mkdocs.ko.yml .PHONY: docs-build-all -docs-build-all: ## Build all docs (EN + KO) +docs-build-all: docs-guard ## Build all docs, EN and KO (manual sources not in this checkout) @echo "Building English docs..." uv run zensical build -f mkdocs.yml @echo "Building Korean docs..." @@ -869,19 +898,19 @@ docs-build-all: ## Build all docs (EN + KO) @echo "All docs built in site/" .PHONY: docs-build-strict -docs-build-strict: ## Build all docs with strict mode (for CI) +docs-build-strict: docs-guard ## Build all docs in strict mode for CI (manual sources not in this checkout) uv run zensical build -f mkdocs.yml uv run zensical build -f mkdocs.ko.yml .PHONY: docs-pdf-setup -docs-pdf-setup: ## Install Playwright browser for PDF export (one-time setup) +docs-pdf-setup: docs-guard ## Install Playwright browser for PDF export, one-time (manual sources not in this checkout) uv venv --python 3.13 uv pip install -r docs/requirements.txt uv run python -m playwright install chromium @echo "PDF export dependencies ready." .PHONY: docs-pdf-en -docs-pdf-en: ## Export English documentation as PDF +docs-pdf-en: docs-guard ## Export English documentation as PDF (manual sources not in this checkout) @echo "Building English documentation as PDF..." uv run mkdocs build --config-file mkdocs.pdf.yml -d site/en/manual @echo "Fixing PDF internal links..." @@ -889,7 +918,7 @@ docs-pdf-en: ## Export English documentation as PDF @echo "PDF generated: site/en/manual/mlxcel-Manual-en.pdf" .PHONY: docs-pdf-ko -docs-pdf-ko: ## Export Korean documentation as PDF +docs-pdf-ko: docs-guard ## Export Korean documentation as PDF (manual sources not in this checkout) @echo "Building Korean documentation as PDF..." uv run mkdocs build --config-file mkdocs.ko.pdf.yml -d site/ko/manual @echo "Fixing PDF internal links..." @@ -897,12 +926,12 @@ docs-pdf-ko: ## Export Korean documentation as PDF @echo "PDF generated: site/ko/manual/mlxcel-Manual-ko.pdf" .PHONY: docs-pdf -docs-pdf: docs-pdf-en docs-pdf-ko ## Export all documentation as PDF +docs-pdf: docs-guard docs-pdf-en docs-pdf-ko ## Export all documentation as PDF (manual sources not in this checkout) @echo "All PDFs generated:" @echo " - site/en/manual/mlxcel-Manual-en.pdf" @echo " - site/ko/manual/mlxcel-Manual-ko.pdf" .PHONY: docs-clean -docs-clean: ## Remove built docs +docs-clean: docs-guard ## Remove built docs (manual sources not in this checkout) rm -rf site/ @echo "Built docs removed." diff --git a/docs/README.md b/docs/README.md index ab0996ded..603807e55 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,8 @@ This directory is the shared documentation root for public release material. It may contain both: 1. **GitHub-facing Markdown documents** linked directly from the root `README.md`. -2. **MkDocs site content** added under the MkDocs-specific source trees. +2. **MkDocs site content** under MkDocs-specific source trees. None is present + here; see "The MkDocs manual" below. 3. **Git/GitHub workflow documents** for maintainers and contributors. The current top-level files are GitHub-facing documents linked from the root @@ -37,9 +38,27 @@ Current GitHub-facing docs: `adr/` holds numbered Architecture Decision Records, one significant decision per file, immutable once Accepted. See `adr/README.md` for the index. +## The MkDocs manual + +The manual published at is not built from +this directory. Its sources (`docs/en`, `docs/ko`, `docs/shared`, +`docs/requirements.txt`, `docs/scripts`) are maintained in a separate +documentation tree and are not part of this repository. + +The four mkdocs configs at the repository root (`mkdocs.yml`, `mkdocs.ko.yml`, +`mkdocs.pdf.yml`, `mkdocs.ko.pdf.yml`) belong to that tree and are kept here in +sync with it. Read their `docs_dir`, `custom_dir`, and `nav:` entries as paths +into that tree: none of them names a file listed above, and none of the files +listed above appears in a `nav:`. That is deliberate, not drift. The +GitHub-facing documents here are meant to read as plain Markdown on GitHub, and +the manual is a separately authored artifact. + +The `docs-*` Makefile targets build the manual from those sources. In this +repository they stop immediately with an explanation rather than failing partway +through a `uv`, symlink, or site build. Read the published manual instead. + Expected future layout examples: -- `docs/en/...` and `docs/ko/...` for MkDocs/manual pages. - `docs/github/...` for GitHub issue/PR/release workflow notes. - `docs/git/...` for branch, commit, tag, and mirroring procedures. From a8abd35af183a777e785fff8acaa28b1459a1bf7 Mon Sep 17 00:00:00 2001 From: Jeongkyu Shin Date: Fri, 14 Aug 2026 00:33:14 +0900 Subject: [PATCH 2/2] docs: add technical report for PR #1122 Bilingual report covering the (a)/(b) resolution, why the guard is a presence check rather than an unconditional refusal so one Makefile stays correct in both trees, why the four mkdocs configs were left untouched, and the two-direction validation of the guard. --- .../1122-docs-target-guard-20260814.en.md | 122 ++++++++++++++++++ .../1122-docs-target-guard-20260814.ko.md | 122 ++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 TECHNICAL_REPORTS/1122-docs-target-guard-20260814.en.md create mode 100644 TECHNICAL_REPORTS/1122-docs-target-guard-20260814.ko.md diff --git a/TECHNICAL_REPORTS/1122-docs-target-guard-20260814.en.md b/TECHNICAL_REPORTS/1122-docs-target-guard-20260814.en.md new file mode 100644 index 000000000..a69cd5e96 --- /dev/null +++ b/TECHNICAL_REPORTS/1122-docs-target-guard-20260814.en.md @@ -0,0 +1,122 @@ +# Technical Report: PR #1122 - chore(docs): guard the docs-* targets and document the manual split + +**Date**: 2026-08-14 +**Status**: Completed +**Languages**: Make, Markdown +**Risk Level**: Low + +--- + +## Executive Summary + +PR #1122 closes issue #1111. The thirteen `docs-*` Makefile targets build the MkDocs manual from sources that are maintained in a separate documentation tree and are not part of this repository, so every one of them failed partway through with an opaque error. They now share a `docs-guard` prerequisite that stops immediately with an explanation, and `docs/README.md` documents the split instead of leaving it to be inferred from a failed build. + +The guard is a presence check rather than an unconditional refusal, which is the design decision that carries the most weight here: one Makefile stays correct both in this repository and in the tree that does hold the sources. + +--- + +## 1. Problem Statement + +### 1.1 Background + +Issue #1111 asked a maintainer to choose between two readings of the same evidence: **(a)** the manual sources belong in this repository and have not landed yet, or **(b)** the manual is built from a different tree. The fix differs entirely, so the issue explicitly asked for the decision before any diff. + +The answer is **(b)**. `git log --all -- docs/en` is empty, so this is not a deletion regression: the tree has never existed here. The four mkdocs configs at the repository root are copies belonging to the tree that owns the manual, kept in sync with it. + +### 1.2 Existing Issues + +- **Every `docs-*` target failed, and none said why.** `make docs-install` died inside `uv pip install -r docs/requirements.txt`. Working around that hit `ln -s ../shared docs/en/shared` against a nonexistent parent, then a site build against a nonexistent `docs_dir`. A reader had to run a target and interpret the failure to learn that the manual is built elsewhere. +- **`make help` advertised all thirteen as working.** `make help` is the discovery surface for the build system, and the targets appear in four of its sections, since the greps that build those sections match on `build`, `serve`, `doc`, `clean`, and `install`. +- **The `nav:` blocks and the on-disk tree disagreed silently.** The configs list 33 page paths each, none of which exist here, while the GitHub-facing `docs/*.md` files appear in no `nav:`. Nothing recorded that this is intended rather than drift. + +### 1.3 Risk Assessment + +| Risk | Impact | Likelihood | +|---|---|---| +| Contributor burns time debugging a build that cannot work in this tree | Medium | High | +| Someone "fixes" the dangling navs by pointing them at `docs/*.md`, breaking the tree that owns them | High | Low | +| A reader concludes the documentation build is broken rather than absent | Low | Medium | + +--- + +## 2. Technical Review + +### 2.1 Correctness of the Guard + +The guard tests for `docs/en` and, when it is missing, prints the explanation and exits 1. It was verified in both directions: all thirteen targets were run individually and each stopped at the guard with exit 1 before reaching any `uv`, `ln`, or `zensical` command, and the guard was then re-run with a `docs/en` directory present, where it exits 0 and unblocks the targets. + +`docs-guard` carries no `##` string, so it does not appear in `make help`. Because it is `.PHONY` with no prerequisites, make runs it at most once per invocation, so `docs-pdf`, which depends on the guard and on `docs-pdf-en` and `docs-pdf-ko` (each of which also depends on the guard), evaluates it once. + +### 2.2 Compatibility + +No Rust, no CI target, and no GitHub-facing `docs/*.md` document is touched. Acceptance criterion 4 of the issue holds: the only file changed under `docs/` is the index. + +`webpage-build` also consumes `mkdocs.yml` and `mkdocs.ko.yml` and therefore shares the underlying dependency. It is outside the enumerated scope of #1111 and is deliberately left alone rather than silently changed. + +--- + +## 3. Technical Decisions + +### 3.1 Presence Check, Not Unconditional Refusal + +| Option | Pros | Cons | +|---|---|---| +| Unconditional `exit 1` in each target | Simplest to read here | Wrong in the tree that holds the sources; the next sync either breaks that tree's build or reverts this change | +| Delete the thirteen targets and the configs | Removes the dead surface entirely | The configs belong to the tree that owns the manual and would come back on the next sync; deleting them locally guarantees churn | +| **Chosen: shared `docs-guard` presence check** | Correct in both trees at once; explains rather than fails; targets unblock automatically wherever the sources exist | Slightly more Makefile than a hardcoded refusal | + +The decisive property is that the same Makefile is right in both places. A guard that says "the sources are missing" is a true statement wherever it fires and silent wherever it does not, so nothing about it needs to be un-done during a sync. + +### 3.2 Shared Prerequisite Over Thirteen Copies + +Thirteen copies of the same check would drift and would put the same nine-line message in the diff thirteen times. One `.PHONY: docs-guard` with thirteen one-word prerequisite additions keeps the message in a single place and makes the dependency visible on each target line. + +### 3.3 Leave the Four mkdocs Configs Unchanged + +The issue's option (b) contemplated removing the configs or documenting them as no-ops. Neither is right: they are the property of the tree that owns the manual and this repository is kept in sync with it, so a local fork of their `nav:` blocks would be both wrong there and undone here. The explanation goes in `docs/README.md`, where it costs nothing to keep and does not conflict with a sync. + +### 3.4 Reconcile "Expected future layout examples" + +`docs/README.md` listed `docs/en/...` and `docs/ko/...` under "Expected future layout examples", which is what made option (a) look plausible in the first place. Those two entries describe a tree that already exists elsewhere, not a layout this repository is heading toward, so they move into the new section. The other two entries there (`docs/github/...`, `docs/git/...`) are genuinely still future and stay. + +--- + +## 4. Change Summary + +### Statistics + +| Item | Value | +|---|---| +| Files changed | 2 | +| Lines added | +63 | +| Lines deleted | -15 | +| Targets guarded | 13 | + +### Changes by Area + +| Area | File | Summary | +|---|---|---| +| Build system | `Makefile` | `docs-guard` presence check added; all thirteen `docs-*` targets depend on it; each `##` help string gains a caveat suffix | +| Documentation | `docs/README.md` | New "The MkDocs manual" section documenting the split; `docs/en/...` and `docs/ko/...` moved out of "Expected future layout examples"; intro item 2 reconciled | + +### Related Commits + +| Hash | Type | Message | +|---|---|---| +| `54a3b294` | chore | chore(docs): guard the docs-* targets and document the manual split | + +--- + +## 5. Validation and Follow-up + +### Passed + +- All thirteen targets run individually: `docs-install`, `docs-serve`, `docs-serve-en`, `docs-serve-ko`, `docs-build`, `docs-build-ko`, `docs-build-all`, `docs-build-strict`, `docs-pdf-setup`, `docs-pdf-en`, `docs-pdf-ko`, `docs-pdf`, `docs-clean`. Each exits 1 at the guard with the explanatory message and reaches no build command. +- Positive path: `make docs-guard` exits 0 with a `docs/en` directory present. +- `make help` shows all thirteen with the caveat in each of the four sections its greps place them in; `docs-guard` is absent from help. +- `python3 scripts/ci/check_cross_repo_refs.py` passes. + +### Follow-up Candidates + +- `webpage-build` builds from the same two mkdocs configs and has the same unmet dependency. It is not a `docs-*` target and was out of scope for #1111; guarding it the same way would be a small, self-contained follow-up. +- The `(manual sources not in this checkout)` help suffix is a statement about this repository specifically. Unlike the guard, it is not automatically true elsewhere. Anyone syncing the Makefile into the tree that holds the sources should treat the suffix as local. diff --git a/TECHNICAL_REPORTS/1122-docs-target-guard-20260814.ko.md b/TECHNICAL_REPORTS/1122-docs-target-guard-20260814.ko.md new file mode 100644 index 000000000..03511b845 --- /dev/null +++ b/TECHNICAL_REPORTS/1122-docs-target-guard-20260814.ko.md @@ -0,0 +1,122 @@ +# 기술 보고서: PR #1122 - chore(docs): guard the docs-* targets and document the manual split + +**작성일**: 2026-08-14 +**상태**: 완료 +**언어**: Make, Markdown +**위험도**: Low + +--- + +## 요약 + +PR #1122는 이슈 #1111을 해결한다. 13개의 `docs-*` Makefile 타깃은 별도 문서 트리에서 관리되는, 이 저장소에 포함되지 않은 소스로부터 MkDocs 매뉴얼을 빌드한다. 그래서 전부 도중에 불투명한 에러로 실패했다. 이제 모두 `docs-guard` 전제 조건을 공유해 즉시 설명과 함께 멈추고, `docs/README.md`가 이 분리 구조를 문서화한다. 실패한 빌드를 보고 추론하게 두지 않는다. + +가드는 무조건적인 거부가 아니라 존재 여부 검사다. 이것이 여기서 가장 중요한 설계 결정이다. 하나의 Makefile이 이 저장소와 실제로 소스를 가진 트리 양쪽에서 모두 올바르게 동작한다. + +--- + +## 1. 문제 정의 + +### 1.1 배경 + +이슈 #1111은 같은 증거에 대한 두 해석 중 하나를 메인테이너가 골라 달라고 요청했다. **(a)** 매뉴얼 소스가 이 저장소에 속하는데 아직 들어오지 않았다, 또는 **(b)** 매뉴얼이 다른 트리에서 빌드된다. 수정 내용이 완전히 달라지므로, 이슈는 diff를 만들기 전에 결정을 먼저 요구했다. + +답은 **(b)**다. `git log --all -- docs/en`이 비어 있으므로 삭제 회귀가 아니다. 그 트리는 여기 존재한 적이 없다. 저장소 루트의 mkdocs 설정 네 개는 매뉴얼을 소유한 트리의 사본이며, 그 트리와 동기화된 상태로 유지된다. + +### 1.2 기존 문제점 + +- **모든 `docs-*` 타깃이 실패했고, 이유를 말해 주지 않았다.** `make docs-install`은 `uv pip install -r docs/requirements.txt`에서 죽었다. 그걸 우회하면 존재하지 않는 부모 디렉터리를 향한 `ln -s ../shared docs/en/shared`에 걸리고, 그다음에는 존재하지 않는 `docs_dir`을 대상으로 한 사이트 빌드에 걸린다. 매뉴얼이 다른 곳에서 빌드된다는 사실을 알려면 타깃을 실행하고 실패를 해석하는 수밖에 없었다. +- **`make help`가 13개 전부를 동작하는 것처럼 광고했다.** `make help`는 빌드 시스템의 발견 표면이고, 섹션을 구성하는 grep들이 `build`, `serve`, `doc`, `clean`, `install`에 매치되기 때문에 이 타깃들은 네 개 섹션에 나타난다. +- **`nav:` 블록과 디스크 상태의 불일치가 조용히 방치됐다.** 설정들은 각각 33개 페이지 경로를 나열하지만 여기에는 하나도 없고, 반대로 GitHub용 `docs/*.md` 파일들은 어떤 `nav:`에도 없다. 이것이 drift가 아니라 의도라는 기록이 어디에도 없었다. + +### 1.3 위험성 + +| 위험 | 영향도 | 발생 가능성 | +|---|---|---| +| 기여자가 이 트리에서 성립할 수 없는 빌드를 디버깅하며 시간을 소모 | Medium | High | +| 누군가 dangling nav를 `docs/*.md`로 돌려 "고쳐서" 소유 트리를 망가뜨림 | High | Low | +| 독자가 문서 빌드가 부재가 아니라 고장 났다고 판단 | Low | Medium | + +--- + +## 2. 기술적 검토 사항 + +### 2.1 가드의 정확성 + +가드는 `docs/en`을 검사하고, 없으면 설명을 출력한 뒤 exit 1 한다. 양방향으로 검증했다. 13개 타깃을 개별 실행해 각각 `uv`, `ln`, `zensical` 명령에 도달하기 전에 가드에서 exit 1로 멈추는 것을 확인했고, 이어서 `docs/en` 디렉터리를 만들어 둔 상태로 가드를 다시 실행해 exit 0으로 타깃을 통과시키는 것을 확인했다. + +`docs-guard`에는 `##` 문자열이 없으므로 `make help`에 나타나지 않는다. 전제 조건이 없는 `.PHONY` 타깃이므로 make 호출당 최대 한 번 실행된다. 따라서 가드와 `docs-pdf-en`, `docs-pdf-ko`(각각 역시 가드에 의존)에 의존하는 `docs-pdf`도 가드를 한 번만 평가한다. + +### 2.2 호환성 + +Rust 코드, CI 타깃, GitHub용 `docs/*.md` 문서는 전혀 건드리지 않았다. 이슈의 수용 기준 4가 유지된다. `docs/` 아래에서 변경된 파일은 인덱스 하나뿐이다. + +`webpage-build` 역시 `mkdocs.yml`과 `mkdocs.ko.yml`을 사용하므로 같은 의존성을 공유한다. #1111이 열거한 범위 밖이므로 조용히 바꾸지 않고 그대로 두었다. + +--- + +## 3. 기술적 선택과 그 이유 + +### 3.1 무조건 거부가 아니라 존재 여부 검사 + +| 옵션 | 장점 | 단점 | +|---|---|---| +| 각 타깃에 무조건 `exit 1` | 여기서는 가장 읽기 쉬움 | 소스를 가진 트리에서는 틀림. 다음 동기화가 그 트리의 빌드를 깨거나 이 변경을 되돌림 | +| 13개 타깃과 설정을 삭제 | 죽은 표면을 완전히 제거 | 설정은 매뉴얼 소유 트리의 것이라 다음 동기화에 되돌아옴. 로컬 삭제는 churn을 보장 | +| **선택: 공유 `docs-guard` 존재 검사** | 두 트리에서 동시에 올바름. 실패 대신 설명. 소스가 있는 곳에서는 자동으로 통과 | 하드코딩된 거부보다 Makefile이 조금 늘어남 | + +결정적 성질은 같은 Makefile이 양쪽에서 옳다는 것이다. "소스가 없다"고 말하는 가드는 발동하는 곳에서는 참인 진술이고 발동하지 않는 곳에서는 침묵하므로, 동기화 과정에서 되돌릴 것이 없다. + +### 3.2 13개 복사본 대신 공유 전제 조건 + +같은 검사를 13번 복사하면 서로 어긋나고, 아홉 줄짜리 메시지가 diff에 13번 들어간다. `.PHONY: docs-guard` 하나와 각 타깃 줄에 한 단어씩 추가하는 방식은 메시지를 한곳에 유지하면서 의존 관계를 타깃 줄에서 바로 보이게 한다. + +### 3.3 네 개의 mkdocs 설정은 그대로 둠 + +이슈의 옵션 (b)는 설정 제거 또는 no-op 문서화를 검토했다. 둘 다 옳지 않다. 설정은 매뉴얼을 소유한 트리의 자산이고 이 저장소는 그 트리와 동기화되므로, `nav:` 블록을 로컬에서 포크하면 저쪽에서 틀리고 이쪽에서는 되돌려진다. 설명은 `docs/README.md`에 둔다. 유지 비용이 없고 동기화와 충돌하지 않는다. + +### 3.4 "Expected future layout examples" 정합화 + +`docs/README.md`는 `docs/en/...`과 `docs/ko/...`를 "Expected future layout examples" 아래에 나열하고 있었고, 애초에 옵션 (a)가 그럴듯해 보인 이유가 이것이다. 두 항목은 이 저장소가 향하는 레이아웃이 아니라 이미 다른 곳에 존재하는 트리를 가리키므로 새 절로 옮겼다. 남은 두 항목(`docs/github/...`, `docs/git/...`)은 실제로 아직 미래이므로 그대로 둔다. + +--- + +## 4. 변경 요약 + +### 통계 + +| 항목 | 값 | +|---|---| +| 변경된 파일 수 | 2 | +| 추가된 라인 | +63 | +| 삭제된 라인 | -15 | +| 가드가 걸린 타깃 수 | 13 | + +### 영역별 변경 + +| 영역 | 파일 | 주요 내용 | +|---|---|---| +| 빌드 시스템 | `Makefile` | `docs-guard` 존재 검사 추가, 13개 `docs-*` 타깃이 의존, 각 `##` help 문자열에 단서 접미사 추가 | +| 문서 | `docs/README.md` | 분리 구조를 설명하는 "The MkDocs manual" 절 신설, `docs/en/...`과 `docs/ko/...`를 "Expected future layout examples"에서 이동, 서두 2번 항목 정합화 | + +### 관련 커밋 + +| Hash | Type | Message | +|---|---|---| +| `54a3b294` | chore | chore(docs): guard the docs-* targets and document the manual split | + +--- + +## 5. 검증 및 후속 조치 + +### 통과 + +- 13개 타깃 개별 실행: `docs-install`, `docs-serve`, `docs-serve-en`, `docs-serve-ko`, `docs-build`, `docs-build-ko`, `docs-build-all`, `docs-build-strict`, `docs-pdf-setup`, `docs-pdf-en`, `docs-pdf-ko`, `docs-pdf`, `docs-clean`. 각각 가드에서 설명 메시지와 함께 exit 1 하며 빌드 명령에 도달하지 않는다. +- 긍정 경로: `docs/en` 디렉터리가 있는 상태에서 `make docs-guard`가 exit 0. +- `make help`가 13개 전부를 단서와 함께 네 개 섹션에 표시하고, `docs-guard`는 help에 나타나지 않는다. +- `python3 scripts/ci/check_cross_repo_refs.py` 통과. + +### 후속 후보 + +- `webpage-build`가 같은 두 mkdocs 설정을 사용하므로 동일한 미충족 의존성을 갖는다. `docs-*` 타깃이 아니어서 #1111 범위 밖이었고, 같은 방식으로 가드를 거는 것은 작고 독립적인 후속 작업이 된다. +- `(manual sources not in this checkout)` help 접미사는 이 저장소에 한정된 진술이다. 가드와 달리 다른 곳에서 자동으로 참이 되지 않는다. Makefile을 소스가 있는 트리로 동기화하는 사람은 이 접미사를 로컬 전용으로 취급해야 한다.