[#186] Replace preconditionFailure with graceful fallback#194
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates ManifestBuilder.renderComponent to avoid crashing the CLI when encountering .generic or missing fileType values while rendering YAML, replacing a hard preconditionFailure with a debug-only assertion and a fallback YAML key.
Changes:
- Replace
preconditionFailurewithassertionFailurein the.generic/.nonebranch. - Add a fallback YAML key (
hook) so release builds render valid YAML instead of terminating.
Comments suppressed due to low confidence (1)
Sources/mcs/Export/ManifestBuilder.swift:499
case .generic, .none:triggersassertionFailurefor both.genericand a missingfileType(nil). SincefileTypeis optional inExternalCopyPackFileConfig, a manifest loaded from disk with an omittedfileTypewould assert in debug builds even though it should be a normal, recoverable case. Consider splitting the cases so only.genericasserts, and.nonejust falls back to a default key without an assertion.
case .generic, .none:
assertionFailure("Export does not produce .generic file components")
key = "hook"
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d14efbb to
2b73e62
Compare
2b73e62 to
c857662
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
Sources/mcs/Export/ManifestBuilder.swift:505
- There are two separate skip paths for
.generic/.nonecopy-pack files: the early-return guard at the top ofrenderComponentand thecase .generic, .none: returninside thefileTypeswitch. This duplication makes it easy for the handling to drift, and the innerreturnis currently redundant given the guard. Suggest consolidating the behavior into a single place (preferably where you can decide before emitting any YAML for the component) so the output is deterministic and easier to maintain.
switch config.fileType {
case .hook: key = "hook"
case .skill: key = "skill"
case .command: key = "command"
case .generic, .none:
return
}
Sources/mcs/Export/ManifestBuilder.swift:442
- This newly introduced edge-case handling for
.copyPackFilewithfileType == nil/.genericisn’t covered by the existingManifestBuilderTests. Since the change is meant to prevent crashes / define fallback behavior, it would be good to add a regression test that constructs a manifest containing such a component and verifies the renderer’s output (fallback key, verbose rendering, or explicit skip) matches the intended behavior.
// Skip .generic file components — no YAML shorthand key exists for this type
if case .copyPackFile(let config) = comp.installAction,
config.fileType == .generic || config.fileType == nil {
return
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Skip .generic file components — no YAML shorthand key exists for this type | ||
| if case .copyPackFile(let config) = comp.installAction, | ||
| config.fileType == .generic || config.fileType == nil { | ||
| return | ||
| } |
There was a problem hiding this comment.
This change silently skips .copyPackFile components when fileType is .generic or nil, but the PR description/Issue #186 state we should emit an assertionFailure in debug and fall back to rendering valid YAML (e.g., defaulting the shorthand key to hook in release). As written, these components will be dropped from the exported YAML with no signal, which is a behavioral change and may lose data. Consider implementing the described assertionFailure + fallback (or rendering the verbose type + installAction form / emitting an explicit YAML warning comment) instead of an unconditional early return.
- Early guard skips .generic/.none file components before any YAML is emitted - Inner switch retains preconditionFailure as a contract: unreachable after guard
c857662 to
0cc533d
Compare
Context
ManifestBuilder.renderComponentusedpreconditionFailurefor the.generic/.nonecases ofExternalCopyFileType. This crashes the CLI in both debug and release builds. While the export wizard never produces.genericcomponents,renderYAMLaccepts anyExternalPackManifest— so a manifest loaded from disk with an omitted or.genericfileType would crash with no recovery.Closes #186
Changes
preconditionFailurewithassertionFailure(stripped in release builds) plus akey = "hook"fallback.genericreaches the render pathhook:YAML instead of crashingTesting Steps
swift buildsucceedsswift test)