بنقرة واحدة
add-screen
Add a new screen to an existing feature module with Store, UI, factories, and tests
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add a new screen to an existing feature module with Store, UI, factories, and tests
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Add missing test cases, targeting a specific file or all changed files on the branch
Thorough pre-merge audit — dependency graph, correctness, conventions, security, test coverage, and improvement suggestions
Quick review of the current diff for bugs, logic errors, convention violations, and test gaps
Scaffold a new feature module with the appropriate layers and MESA conventions
Scaffold a new Strata interactor with interface, implementation, fake, and test
Bump library version in VERSION file and prepare release notes
| name | add-screen |
| description | Add a new screen to an existing feature module with Store, UI, factories, and tests |
| disable-model-invocation | true |
| argument-hint | <feature-name> <ScreenName> |
Add a new screen to an existing feature module. This scaffolds the Screen, State, Event, Store, UI, and Factory within the feature's directory.
Input: $ARGUMENTS
Extract the feature name and screen name from the input.
Verify the feature directory exists at <AppTarget>/<FeatureName>/. If the feature doesn't exist, suggest running /add-feature first.
Read the existing screen files in the feature module to match:
Also read existing screens from other features if the current feature has no prior screens.
Ask the user:
TrapezioScreen struct)TrapezioNavigator injection?TrapezioInterop injection?Place at: <AppTarget>/<FeatureName>/<ScreenName>Screen.swift
import Trapezio
struct <ScreenName>Screen: TrapezioScreen {
// navigation arguments as properties (must be Hashable & Codable)
}
struct <ScreenName>State: TrapezioState {
// display properties — value types only, must be Equatable
}
enum <ScreenName>Event: TrapezioEvent {
// user intents
}
Place at: <AppTarget>/<FeatureName>/<ScreenName>Store.swift
import Foundation
import Trapezio
import TrapezioNavigation
import Strata
@MainActor
final class <ScreenName>Store: TrapezioStore<<ScreenName>Screen, <ScreenName>State, <ScreenName>Event> {
private let navigator: (any TrapezioNavigator)?
// injected dependencies
init(
screen: <ScreenName>Screen,
navigator: (any TrapezioNavigator)?
// additional dependencies
) {
self.navigator = navigator
super.init(screen: screen, initialState: <ScreenName>State(/* initial values */))
setupBindings()
}
private func setupBindings() {
// strataCollect streams here
}
override func handle(event: <ScreenName>Event) {
switch event {
// handle events
}
}
}
Place at: <AppTarget>/<FeatureName>/<ScreenName>Ui.swift
import SwiftUI
import Trapezio
struct <ScreenName>UI: TrapezioUI {
func map(state: <ScreenName>State, onEvent: @escaping @MainActor (<ScreenName>Event) -> Void) -> some View {
// stateless composable — no @State, @StateObject, or side effects
}
}
Place at: <AppTarget>/<FeatureName>/<ScreenName>Factory.swift
import SwiftUI
import Trapezio
import TrapezioNavigation
struct <ScreenName>Factory {
@ViewBuilder @MainActor
static func make(screen: <ScreenName>Screen, navigator: (any TrapezioNavigator)?, interop: (any TrapezioInterop)?) -> some View {
// assemble dependencies
TrapezioContainer(
makeStore: <ScreenName>Store(
screen: screen,
navigator: navigator
// pass dependencies
),
ui: <ScreenName>UI()
)
}
}
Add the screen to the ContentView builder closure:
case let <name> as <ScreenName>Screen:
<ScreenName>Factory.make(screen: <name>, navigator: navigator, interop: interop)
Automatically generate test files following the conventions from the /add-tests skill:
For Counter app (XCTest):
import XCTest
import Trapezio
import TrapezioNavigation
@testable import <AppTarget>
@MainActor
final class <ScreenName>StoreTests: XCTestCase {
var store: <ScreenName>Store!
override func setUp() {
super.setUp()
let screen = <ScreenName>Screen(/* params */)
store = <ScreenName>Store(
screen: screen,
/* inject fakes */
navigator: nil
)
}
func test_initialState_isCorrect() {
// assert initial state
}
}
For MESA library (Swift Testing) — use TrapezioTest utilities when testing navigation:
import Foundation
import Testing
import TrapezioTest
@testable import <Target>
@Suite("<ScreenName>Store")
struct <ScreenName>StoreTests {
@Test("initial state is correct")
@MainActor func initialState() {
let store = <ScreenName>Store(
screen: <ScreenName>Screen(/* params */),
navigator: nil
)
#expect(store.state == <ScreenName>State(/* expected */))
}
// Use FakeTrapezioNavigator to assert navigation:
// let nav = FakeTrapezioNavigator()
// store.handle(event: .someNavEvent)
// #expect(nav.navigatedScreens.count == 1)
}
All generated files MUST include the Apache 2.0 license header:
/*
* Copyright 2026 Jason Jamieson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Run cd MESA && swift build to verify compilation.
Report:
Then ask:
/add-interactor <feature-name> <InteractorName>