Skip to content

fix(harness): #59 と #61 のレビュー指摘の残りを直す (formatVersion の報告、ハーネスのメニュー、Entry lane の denial ほか) - #64

Merged
GeneralD merged 11 commits into
mainfrom
fix/mvp-b-review-followups
Oct 28, 2026
Merged

GeneralD merged 11 commits into
mainfrom
fix/mvp-b-review-followups

Conversation

@GeneralD

@GeneralD GeneralD commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

agent type scope closes

概要

issue #63 の対応。#59 (#45) と #61 (#50) がマージされた後に残っていたレビュー指摘 11 件を、main (0.21.0) で今も成り立つかを 1 件ずつ確かめてから直した。11 件すべてが main でも成り立っていたので、見送った項目は無い (#62 が再構成した HostEffectRegistrationsTests と HarnessLiveWiringTests も、下の各項目で現物を読んで判断した)。1 項目 1 commit。

アプリの挙動が変わるのは formatVersion が整数でない manifest のメッセージだけ。それ以外は docs / テスト / コメント / ハーネスの構造 / make check のスクリプト。version.txt には触れていない。

変更点

#59 由来

  • .lens 段落の裏付けの無い記述を削った (1c8d797): 「Examples/Ripple.lens は live の Metal で一度コンパイルした」を消し、固定されている事実だけにした。ExamplePackagesTests が形式を固定し、コンパイルは 実物結線・loopback 統合・Lane 1 実機確認・docs と grep の閉じ #52 の Lane 1 で確かめる
  • fileNoSuchFile の記述を正した (5f8580f): fake (InMemoryFileSystemGateway) も live gateway (FileSystemGatewayImplTests) も出すのは fileReadNoSuchFile。fileNoSuchFile は防御的に受け入れ、scripted な failRead のテスト (missingIsToldByCode) だけが通す。同じ言い過ぎをしていた isMissing のコメントも同じ commit で直した
  • 実ディスクを読むテストを規則の例外として明記した (81c181c): ExamplePackagesTests はリポジトリの Examples/ を実ディスクから読む。Physical Abstraction Table の File system 行と .claude/rules/testing.md に、「real FS は Gateway smoke だけ」の唯一の読み取り専用の例外として書いた (他にディスクを読むテストは AppDirectoriesProviderImplTests と Gateway smoke だけで、どちらも Gateway の smoke)
  • formatVersion が整数でない manifest を名指しで報告する (2ce0da9): 1.5 や 99999999999999999999 は、valid な JSON なのに「not valid JSON」と報告されていた (JSONDecoder は Int で読めない数を coding path 無しの dataCorrupted で返すため)。probe が Int、だめなら Double で読み、小数は "formatVersion" is not an integer、Int を超える整数は "formatVersion" is out of range になる。EffectManifestDecodingTests に 1.5 / 1.5 + 他のキーの形が違う / 99999999999999999999 / -99999999999999999999 / formatVersion: null / "name": null の 6 行を足した (旧 decoder に対して前 4 行が赤、後ろ 2 行は valueNotFound の arm に行が無かったための追加)。到達しなくなった dataCorrupted の「<key> is not valid」の arm を消した
  • HostEffectRegistrationsTests が実際に in-memory のフォルダを使ったことを assert した (70078e4): MVP-B の終端: 実物の結線・loopback 統合・Lane 1 の計測表・docs と grep の閉じ (#52) #62 の再構成後も、defaultGraphChoosesTheBundledEffect は InMemoryFileSystemGateway をその場で作って捨てていて、「ユーザーのフォルダに触れない」はコメントだけだった。fake を Fakes に束ねて残し、フォルダが 1 回だけ作られ、列挙され、error log が空であることを読み戻す。fileSystemGateway の override だけを外すと赤になる
  • Examples/Ripple.lens の記述を挙動に合わせた (bb14860): band は floor していないので、揺れは帯ごとに揃うのではなく、48 行ごとに新しいランダムな振れを持つ滑らかな波。effect.metal の冒頭と 2 か所のコメント、manifest.json の description、README の例 (manifest と同じ文)、Lane 1 の表の「swaying bands」を直した。kernel のコードは変えていない
  • ExamplePackagesTests の期待する並び順を DataSource と同じ規則にした (4dd51d8): フォルダ名 (.lens つき) を sort していたのを、.lens を除いた id を sort するようにした。Ripple.lens と Ripple-b.lens では名前だと Ripple-b が先 (- が . より小さい)、id だと Ripple が先で、DataSource は後者。scratch の Examples/Ripple-b.lens を置いて旧版が赤・新版が緑を確かめてから消した

#61 由来

  • ハーネスのメニューを testable な型に移した (5621e7a): HarnessAppDelegate から Effects メニューの組み立て (#available(macOS 14.4, *) の分岐を含む) と router の start / stop を HarnessMenu に移した。HarnessMenuTests (7 tests) が Quit、Effects 項目、NSHostingMenu が無い OS ではメニューが app メニューだけになること、既定のメニューが NSHostingMenu<EffectMenu> であること、メニューを読んでも何も start されないこと、start() / stop() が Router を通って Interactor に届くことを固定する。delegate に残るのは実行中の application を要る呼び出し (window、activate、NSApplication へのメニューのセット) だけ。codecov の ignore には何も足していない
  • NSMenuItem.subtitle の制限を D8 に書いた (d5d4c7a): SDK の NSMenuItem.h (macOS 26.4 と 26.5 の SDK で同じ文) は、subtitle が API_AVAILABLE(macos(14.4)) で、macOS 14 では attributed title の項目に出ず macOS 15 以降で出ると書いている。対応の下限は 14.0 なので、ホストの MenuBarExtra の行の 2 行目が出ない場合がある。SwiftUI がこの行に attributed title を付けるかは header に書かれておらず、macOS 14 では動かしていないので、書いたのは「may」まで。Lane 1 の記録欄と EffectMenu のコメントも合わせた
  • Entry lane に \.effectInteractor を禁じた (90fd8ed): scripts/check-dependency-keypaths.sh に DENIALS (<module glob> <key> <reason>) を足し、App と DevHarness が \.effectInteractor を解決すると、理由つきで落とす。.claude/rules/architecture-boundaries.md (Per-key denials)、docs/ARCHITECTURE.md の D8 / D9、AGENTS.md、module checklist に書いた
  • AppRouterTests の既定の factory のテストに「start の前は静か」を足した (060b408): start() の前に fake の interactor が start も stop も受けていないこと、Presenter の行が空であることを assert する。既定の factory が Presenter を start してしまう変更は、以前は緑 (後の start() は start 済みの Presenter では何もしない) で、今は赤

設計判断

  • Entry lane の禁止は check-live-owner.sh 方式ではなく check-dependency-keypaths.sh の per-key denial にした: Entry lane の kind (Interactor) は cameraInteractor / harnessInteractor を許すので、kind の規則では「この Interactor だけは不可」と言えず、lane の表を直接直す必要がある。check-live-owner.sh 流の grep は、コメントや文字列も拾ってしまう (実際、この PR のテストのコメントが \.effectInteractor と書いただけで落ちた) し、lane の表と別の場所に規則を置くことになる。AST 検索は @Dependency / Dependency(...) / Dependency<T>(...) のどの綴りでも同じに見る。Alternative not taken: grep 方式
  • denial の「古さ」は静的に検査する: 効いている denial は resolution に一致しないので、既存の EXCEPTIONS のような「使われなかったら落とす」ができない。代わりに、key がもう port でない / glob に合う module が無い / lane の kind が元からその key を許さない (denial が不要) のどれかで落とす。3 つとも一時コピーに行を足して落ちることを確かめた
  • HarnessMenu は Router を init の引数に取り、既定は live(): テストは AppRouter(makeMenuBarPresenter:) を withDependencies { $0.effectInteractor = fake } の中で作る。\.effectInteractor の key path は HarnessLiveWiringTests 以外に書かず (check-live-owner.sh が通る)、static let の live 値を解決するのも従来どおり HarnessLiveWiringTests だけ。そのテストは delegate と同じ HarnessMenu.live() を呼ぶので、delegate の組み立てが同じ呼び出しで live の経路を通る
  • ホストするメニューの builder を注入できるようにした: CI の runner は macOS 14.4 以上なので #available の else 側は実行できない。builder を差し替えて「NSHostingMenu を作れない OS」のメニューを同じ return nil の経路で確かめる。既定の builder が NSHostingMenu<EffectMenu> を返すことは別のテストで見る
  • formatVersion は Int を先に読み、だめなら Double: Double だけで読むと 2^53 を超える整数が丸まって報告が 1 ずれる。1.0 / 1e0 は従来どおり 1 として読まれる。1e400 のように Double でも持てない数は、引き続き「not valid JSON」(decoder がそれ以上のことを言わない)

テスト

最終 head 90fd8ed で、ローカルの gate を順に全部緑 (make format の差分なし → make lint → make check → make build → make build-dev-harness → make test → make test-gpu):

format: PASS (exit 0)
lint: PASS (exit 0)
check: PASS (exit 0)
build: PASS (exit 0)
build-dev-harness: PASS (exit 0)
test: PASS (exit 0)      Test run with 958 tests in 130 suites passed after 4.055 seconds with 10 known issues.
test-gpu: PASS (exit 0)  Test run with 27 tests in 6 suites passed after 1.257 seconds.
  • 感度の確認 (すべて元に戻した):
    • HarnessMenu の Effects 項目を足す行を外すと HarnessMenuTests の 2 本が赤。start() を空にすると HarnessMenuTests の start / stop の 2 本と HarnessLiveWiringTests の 1 本が赤 (メニューが Router を起こさないので、catalog が走らない)。stop() を空にしても stop のテストが赤
    • 旧 decoder に新しい行を当てると 4 行が赤 (1.5 が 2 行、巨大整数が 2 行)
    • HostEffectRegistrationsTests から fileSystemGateway の override だけを外すと、createdDirectories / isDirectory / listings / error log の 4 つの assert が赤
    • AppRouter の既定の factory に presenter.start() を足すと AppRouterTests の既定の factory のテストが赤 (他の 9 本は緑のまま: 注入した factory しか見ていなかった)
    • scratch の resolution を Sources/App (@Dependency(\.effectInteractor)) と Sources/DevHarness (Dependency<any EffectInteractor>(\.effectInteractor)) に置くと check-dependency-keypaths が exit 1 で落ち、cameraInteractor は通る。消すと緑に戻る
    • scratch の Examples/Ripple-b.lens を置くと、旧 ExamplePackagesTests が赤、新版が緑。消した
  • 待ちは settle / tickUntil / Collector.waitForCount のみ。固定の Task.sleep も壁時計も使っていない

docs 更新

  • docs/ARCHITECTURE.md: .lens 段落 (Ripple のコンパイル、no-such-file の 2 つの code、formatVersion の報告)、File system 行 (読み取り専用の例外)、effect catalog の段落 (HostEffectRegistrationsTests の assert)、Entry 行と Coverage (HarnessMenu)、Menu bar の段落 (D8: 起動役、テスト、2 行目の制限、Entry lane の denial)、Interactor と Presenter の段落 (D9)、Dev harness の段落
  • .claude/rules/architecture-boundaries.md (Per-key denials)、module-checklist.md、testing.md (読み取り専用の例外)、dev-verification.md (Ripple の文言、2 行目の記録欄)
  • AGENTS.md: key-path の規則と Presenter の起動役、ハーネスのメニュー
  • README.md: formatVersion の説明、Ripple の description
  • Package.swift: DevHarness のコメント、DevHarnessTests の依存に Presenters と Views
  • コメント: AppRouter、EffectMenu、EffectPackageDataSourceImpl.isMissing、HarnessAppDelegate、main.swift

入れていないもの

Closes #63

Summary by CodeRabbit

  • New Features
    • The development harness now includes an Effects submenu on supported macOS versions, with menu behavior coordinated with the app session.
  • Bug Fixes
    • Effect package validation now distinguishes unsupported integer format versions from invalid numeric values and provides clearer messages for malformed manifests.
  • Documentation
    • Updated the Ripple effect description to reflect its smooth, drifting wave.
    • Clarified when effect subtitles appear on macOS 14 and later.

…of the app delegate

HarnessAppDelegate was untested by design, so the Effects menu assembly (with its #available branch) and the Router's start and stop were the 13 lines codecov/patch flagged on #61. HarnessMenu holds them: it owns the AppRouter, builds the main menu (Quit, then an Effects item hosting EffectMenu in an NSHostingMenu where the system has one) and forwards start() and stop() to the Router. The hosted-menu builder is injectable, so DevHarnessTests also cover a system without NSHostingMenu. HarnessMenuTests run it over a Router whose Presenter talks to a FakeEffectInteractor, built through an override, so only HarnessLiveWiringTests resolves the stateful catalog values live; that test now builds HarnessMenu.live(), the call the delegate makes.

The delegate keeps the calls that need a running application: the window, the activation and setting the menu on NSApplication.
…ive Metal

Nothing in the repository backs it: ExamplePackagesTests pins the package's shape through the DataSource, and whether the kernel compiles is checked on a device in the Lane 1 run of #52. State only that.
…and which is only accepted

The architecture paragraph and the isMissing comment said fileNoSuchFile was a shape the in-memory and live gateways produce. Both raise fileReadNoSuchFile (InMemoryFileSystemGatewayTests, FileSystemGatewayImplTests); fileNoSuchFile is accepted defensively and only the scripted failRead test passes it.
…the real file system

The File system row of the Physical Abstraction Table and testing.md said the real file system appears only in Gateway smoke suites. ExamplePackagesTests reads the repository's Examples/ from disk; say so, as the single read-only exception.
… name

A manifest that is valid JSON but whose formatVersion is 1.5 or 99999999999999999999 was reported as 'not valid JSON': the decoder refuses a number it cannot read as an Int with no coding path. The probe now reads formatVersion as an Int and, failing that, as a Double, so the key is known: a fraction is 'not an integer', a whole number beyond Int is 'out of range'. Rows added for both, a negative one, a null formatVersion and a null name (the valueNotFound arm had no row). The dataCorrupted arm that named a key ('... is not valid') was reachable only through that Int-range failure and is gone.
…older in memory

defaultGraphChoosesTheBundledEffect created its InMemoryFileSystemGateway inline and never read it back, so 'no test touches the user's folder' was a comment. The fakes are now kept per test (Fakes.live), and the test asserts the folder was made once and listed through the in-memory file system and that no error was logged. Dropping only the fileSystemGateway override turns it red.
…s that sway together

band is float(gid.y) / bandHeight and is not floored, so every row has its own position on the noise lattice: the sway is a smooth wave with a new random swing every 48 rows, not rows that move together. The kernel is unchanged; its comments, the manifest description, the README's copy of it and the Lane 1 table's wording follow what it does.
…sorts them

ExamplePackagesTests sorted the folder names including .lens, while EffectPackageDataSourceImpl sorts the ids without it. The two differ as soon as one name is a prefix of another followed by a character below '.': with Ripple.lens and Ripple-b.lens the names put Ripple-b first and the ids put Ripple first. With a scratch Ripple-b.lens copied into Examples/ the old expectation was red and the new one green; the scratch copy is removed.
…the Router starts

The quiet-before-start check existed only for an injected factory. The default factory is what the host and the harness run, so the test over it now reads the fake Interactor's starts, stops and the Presenter's rows before start(). A default factory that started its Presenter was green before (the later start() is a no-op on a started Presenter) and is red now.
…sing on macOS 14

NSMenuItem.subtitle is API_AVAILABLE(macos(14.4)), and the header (the same text in the macOS 26.4 and 26.5 SDKs) says that on macOS 14 an item with an attributed title does not show it, while macOS 15 and later do. The package's floor is 14.0, so the host's MenuBarExtra rows may lack the author or the reason line there. Written as a known limit of the Menu bar decision (D8) with the alternative not taken, and aligned in the Lane 1 note and EffectMenu's comment. The header does not say whether SwiftUI sets an attributed title, so the claim is 'may'.
The Router alone starts the Presenter that owns the effects menu's Interactor, but the Entry lane may resolve Interactors, so nothing stopped App or DevHarness from resolving effectInteractor and starting the catalog a second time. check-dependency-keypaths.sh gets a DENIALS table beside EXCEPTIONS: <module glob> <key> <reason>, checked before the lane's kinds. A working denial is never matched by a resolution, so staleness is static: an entry fails when its key is no longer a declared port, no module matches its glob, or the lane's kinds already forbid the key. A scratch resolution in App (attribute form) and in DevHarness (Dependency<T>(...) initializer form) fails with the reason and exit 1, a clean tree passes, and each of the three staleness cases fails on a temporary copy. Documented in architecture-boundaries.md (Per-key denials), the Menu bar and Interactor/Presenter decisions, AGENTS.md and the module checklist.
@GeneralD GeneralD self-assigned this Oct 27, 2026
Copilot AI lite review requested due to automatic review settings October 27, 2026 18:40
@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cdd2a614-1d70-4dd9-8ac4-7d9c88547481
Commits

Reviewing files that changed from the base of the PR and between 4b7c243 and 90fd8ed.

Files selected for processing: 24
  • .claude/rules/architecture-boundaries.md
  • .claude/rules/dev-verification.md
  • .claude/rules/module-checklist.md
  • .claude/rules/testing.md
  • AGENTS.md
  • Examples/Ripple.lens/effect.metal
  • Examples/Ripple.lens/manifest.json
  • Package.swift
  • README.md
  • Sources/AppRouter/AppRouter.swift
  • Sources/DevHarness/HarnessAppDelegate.swift
  • Sources/DevHarness/HarnessMenu.swift
  • Sources/DevHarness/main.swift
  • Sources/EffectPackageDataSource/EffectManifestDecoding.swift
  • Sources/EffectPackageDataSource/EffectPackageDataSourceImpl.swift
  • Sources/Views/EffectMenu.swift
  • Tests/AppRouterTests/AppRouterTests.swift
  • Tests/DevHarnessTests/HarnessLiveWiringTests.swift
  • Tests/DevHarnessTests/HarnessMenuTests.swift
  • Tests/EffectPackageDataSourceTests/EffectManifestDecodingTests.swift
  • Tests/EffectPackageDataSourceTests/ExamplePackagesTests.swift
  • Tests/HostDependencyInjectionTests/HostEffectRegistrationsTests.swift
  • docs/ARCHITECTURE.md
  • scripts/check-dependency-keypaths.sh

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The PR adds HarnessMenu as the owner of the harness menu and AppRouter lifecycle, enforces per-key dependency denials, and refines manifest version validation. It also updates package and dependency-graph tests, Ripple descriptions, and related architecture and testing guidance.

Changes: Harness menu lifecycle

Layer / File(s) Summary
Entry dependency boundary
scripts/check-dependency-keypaths.sh, .claude/rules/architecture-boundaries.md, .claude/rules/module-checklist.md, AGENTS.md, Sources/AppRouter/AppRouter.swift, docs/ARCHITECTURE.md, .claude/rules/dev-verification.md, Sources/Views/EffectMenu.swift, Package.swift, Sources/DevHarness/main.swift
The key-path checker denies effectInteractor access from App and DevHarness before lane and exception checks. It rejects stale denials. Architecture and module guidance documents the restriction and the Router’s Presenter lifecycle.
HarnessMenu lifecycle and wiring
Sources/DevHarness/HarnessMenu.swift, Sources/DevHarness/HarnessAppDelegate.swift
HarnessMenu builds the main menu and optional Effects submenu, and forwards start and stop calls to AppRouter. HarnessAppDelegate installs and starts the menu beside the session, then stops the menu before stopping the session.
Menu and Router tests
Tests/AppRouterTests/AppRouterTests.swift, Tests/DevHarnessTests/*, Package.swift
Tests cover menu construction, optional and hosted Effects menus, Router lifecycle, quiet Presenter state before startup, and live harness wiring through HarnessMenu.

Package validation and test fixtures

Layer / File(s) Summary
Manifest version classification
Sources/EffectPackageDataSource/EffectManifestDecoding.swift, Tests/EffectPackageDataSourceTests/EffectManifestDecodingTests.swift, README.md, Sources/EffectPackageDataSource/EffectPackageDataSourceImpl.swift, docs/ARCHITECTURE.md
The decoder distinguishes non-integer or out-of-range numeric formatVersion values from unsupported integer versions. Tests cover fractional and out-of-range values, as well as null fields. The README and architecture documentation describe the validation rules.
Example package listing and filesystem fixture
Tests/EffectPackageDataSourceTests/ExamplePackagesTests.swift, .claude/rules/testing.md, docs/ARCHITECTURE.md
The example-package test sorts IDs without the .lens suffix and copies repository examples into an in-memory filesystem. Testing and architecture guidance document this read-only filesystem access.
Default effects graph assertions
Tests/HostDependencyInjectionTests/HostEffectRegistrationsTests.swift
The tests use a Fakes value to retain in-memory gateways and recording logs. The default-graph test checks effects-directory operations and confirms that the error log is empty.

Ripple description

Layer / File(s) Summary
Ripple wave description
Examples/Ripple.lens/effect.metal, Examples/Ripple.lens/manifest.json, .claude/rules/dev-verification.md, README.md
Comments and descriptions now characterize Ripple as a smooth sideways wave that varies by row and drifts with time. No executable shader code changed.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant HarnessAppDelegate
  participant HarnessSession
  participant HarnessMenu
  participant AppRouter
  participant MenuBarPresenter
  HarnessAppDelegate->>HarnessSession: start
  HarnessAppDelegate->>HarnessMenu: start
  HarnessMenu->>AppRouter: start
  AppRouter->>MenuBarPresenter: start
  HarnessAppDelegate->>HarnessMenu: stop
  HarnessMenu->>AppRouter: stop
  AppRouter->>MenuBarPresenter: stop
  HarnessAppDelegate->>HarnessSession: stop
Loading

Possibly related issues

  • GeneralD/mirage issue 52: The PR updates live-wiring tests and related documentation, but it does not perform the remaining Lane 1 device verification.
  • GeneralD/mirage issue 42: The PR changes manifest validation and the construction and tests of the Effects menu, which overlap with the issue’s package-loading and menu objectives.
Merge Risk: Minimal · up to 90fd8

No material new merge risk was identified.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surv… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title is written in Japanese and names a real, specific part of the changeset: fixing remaining review findings from #59 and #61. It lists the areas touched: formatVersion reporting, harness menu,…
Linked Issues check Passed Issue #63 is the only direct link. Its coding requirements, grouped by objective:

1. [#59] Docs (ARCHITECTURE.md .lens paragraph, fileNoSuchFile description, File system row, testing.md exception): t…
Out of Scope Changes check Passed Each changed area traces to an issue #63 objective or supports one:

- Sources/EffectPackageDataSource/EffectManifestDecoding.swift and EffectPackageDataSourceImpl.swift (isMissing doc): #59 formatVer…
Full details: Title check

Explanation

The title is written in Japanese and names a real, specific part of the changeset: fixing remaining review findings from #59 and #61. It lists the areas touched: formatVersion reporting, harness menu, and the Entry lane denial. The raw summary confirms each of these changes. The title covers several areas rather than one main change, and it is long at 90 characters, but it is not vague or off-topic.

Full details: Linked Issues check

Explanation

Issue #63 is the only direct link. Its coding requirements, grouped by objective:

  1. [#59] Docs (ARCHITECTURE.md .lens paragraph, fileNoSuchFile description, File system row, testing.md exception): the PR description and the AI change summaries cover each item. The docs were assessed from these summaries, not from full text.
  2. [#59] formatVersion (EffectManifestDecoding.swift at head 90fd8ed): verified. FormatVersion tries Int, then Double. A non-integer number yields "formatVersion" is not an integer; an out-of-range integer yields "formatVersion" is out of range. The dead dataCorrupted key-path arm is removed. Null formatVersion and name fall through to valueNotFound with a key path. The 6 test rows are listed in the PR and the summary of EffectManifestDecodingTests.
  3. [#59] HostEffectRegistrationsTests: the Fakes scope records folder creation, listing, and an empty error log. Per the summary, the override removal turns 4 assertions red.
  4. [#59] Ripple comments, manifest description, and README: updated per the summary. Kernel code unchanged.
  5. [#59] ExamplePackagesTests (verified at head): packageIDs() strips .lens and sorts the ids, matching the requirement.
  6. [#61] Harness menu extraction: verified. HarnessAppDelegate uses HarnessMenu.live(), sets mainMenu, and calls menu.start()/stop() around the session. HarnessMenu.swift and HarnessMenuTests.swift are present, with injectable menu builder for the nil path.
  7. [#61] NSMenuItem.subtitle limit in D8, dev-verification.md, and EffectMenu comment: updated per the summary.
  8. [#61] Entry-lane .effectInteractor denial via check-dependency-keypaths.sh DENIALS for App and DevHarness: per the summary and the PR description; the script change is in the change set.
  9. [#61] AppRouterTests: pre-start quiet assertions added per the summary.

Unverified: the acceptance criterion that codecov/patch is green is a CI result outside the repository. The PR reports local gate results (make format, lint, check, build, build-dev-harness, test, test-gpu, all PASS). The PR also states that codecov ignore rules are unchanged. No coding requirement is left unmet on the evidence available.

Full details: Out of Scope Changes check

Explanation

Each changed area traces to an issue #63 objective or supports one:

  • Sources/EffectPackageDataSource/EffectManifestDecoding.swift and EffectPackageDataSourceImpl.swift (isMissing doc): #59 formatVersion and fileNoSuchFile items.
  • Sources/DevHarness/HarnessMenu.swift (new), HarnessAppDelegate.swift, main.swift comment: #61 codecov item (menu and Router start/stop moved to a testable type). The injectable menu builder is needed to test the nil (pre-macOS 14.4) path, which CI cannot run.
  • Tests/DevHarnessTests (HarnessMenuTests, HarnessLiveWiringTests), Package.swift (DevHarnessTests gains Presenters and Views): test support for the #61 items.
  • Tests/AppRouterTests: #61 pre-start quiet assertion.
  • Tests/EffectPackageDataSourceTests (EffectManifestDecodingTests, ExamplePackagesTests): #59 items.
  • Tests/HostDependencyInjectionTests/HostEffectRegistrationsTests.swift: #59 in-memory folder item.
  • Examples/Ripple.lens (effect.metal comments, manifest.json description) and README Ripple example: #59 Ripple item. Kernel logic is unchanged per the summary.
  • scripts/check-dependency-keypaths.sh: #61 per-key denial. The added stale-denial checks (undeclared key, no matching module, kind already disallows key) support the denial rule. They do not add unrelated behavior.
  • .claude/rules/*, AGENTS.md, docs/ARCHITECTURE.md, Package.swift comments, EffectMenu.swift and AppRouter.swift comments: documentation the issue requires (D8, Entry lane, testing exception, Ripple text).

Not in the change set: the repeated unreadable-package error log and version.txt, both excluded by the issue. No change lacks a connection to an objective.

Full details: Docstring Coverage

Explanation

Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 26 functions across 15 files. (9 skipped: 9 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@codecov

codecov Bot commented Oct 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.69767% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
Sources/DevHarness/HarnessAppDelegate.swift 0.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@GeneralD
GeneralD merged commit 9153a42 into main Oct 28, 2026
8 checks passed
@GeneralD
GeneralD deleted the fix/mvp-b-review-followups branch October 28, 2026 14:42
@GeneralD

Copy link
Copy Markdown
Owner Author

agent follow-up

マージ後のレビューの指摘と 0.21.1 への bump は #67 で扱います。

GeneralD added a commit that referenced this pull request Oct 29, 2026
fix: #64 のマージ後レビューの指摘を直し、0.21.1 に bump する (formatVersion の README・テスト行、HarnessMenu.live() の owner guard ほか)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants