-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Context
Follow-up from #176 (fixed in PR #216 for pack-level supplementaryDoctorChecks).
ExternalPackAdapter.convertComponent() calls ProjectDetector.findProjectRoot() for each component that has inline doctorChecks defined. These checks are baked into ComponentDefinition.supplementaryChecks as concrete [any DoctorCheck] instances at construction time — the projectRoot used during creation is frozen into the check structs.
This means:
- Every access to
pack.componentstriggersfindProjectRoot()for each component withdoctorChecks - Multi-scope doctor runs may use a stale/incorrect
projectRoot(e.g., global scope should usenil, but picks up the project root from CWD) allDoctorChecks(projectRoot:)returnsderived + supplementaryChecks— onlyderivedchecks use the scope-appropriateprojectRoot; the baked-in supplementary checks do not
Why this is harder than #176
ComponentDefinition.supplementaryChecksis aletstored property ([any DoctorCheck])- Two consumers access it:
allDoctorChecks(projectRoot:)(doctor runs) andComponentExecutor(install-time "already installed?" checks) componentsis aTechPackprotocol property used in many contexts beyond doctor — adding aprojectRootparameter would be a larger refactor
Proposal
Change ComponentDefinition.supplementaryChecks from [any DoctorCheck] to @Sendable (URL?) -> [any DoctorCheck] (a factory closure). Call the factory from allDoctorChecks(projectRoot:) so each doctor run gets scope-correct checks. ComponentExecutor would pass nil or the appropriate project root.
Impact
Low — same as #176. Pack count and component count are small in practice and the walk-up is fast. This is a code quality improvement, not a performance fix.
Files involved
Sources/mcs/TechPack/Component.swift— changesupplementaryCheckstypeSources/mcs/ExternalPack/ExternalPackAdapter.swift:157— provide closure instead of eager checksSources/mcs/Doctor/DerivedDoctorChecks.swift:46-49— call factory withprojectRootSources/mcs/Install/ComponentExecutor.swift:338— pass appropriateprojectRoot