بنقرة واحدة
add-screen
Add a new screen to an existing feature module with StateHolder, UI, factories, and tests
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add a new screen to an existing feature module with StateHolder, UI, factories, and tests
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
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
Add missing test cases, targeting a specific file or all changed files on the branch
Bump library versions in gradle.properties and prepare release notes
Diagnose and fix an error from a build failure, stack trace, or error message
| name | add-screen |
| description | Add a new screen to an existing feature module with StateHolder, 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, StateHolder, UI, and factory wiring within the feature's existing presentation/ layer, plus the Screen definition in api/.
Input: $ARGUMENTS
Extract the feature name and screen name from the input.
Verify the feature module exists at features/<feature-name>/ and has a presentation/ layer. If the feature doesn't exist, suggest running /add-feature first. If the feature exists but has no presentation/ layer, inform the user that this feature is headless and a presentation layer would need to be added first.
Read the existing screen files in the feature module to match:
build.gradle.kts is configuredAlso read existing screens from other features if the current feature has no prior screens.
Ask the user:
@Assisted params on the StateHolder)TrapezeNavigationResult implementation)api/Place at: features/<feature-name>/api/src/main/java/<package>/api/<ScreenName>Screen.kt
@Parcelize
data class <ScreenName>Screen(
// navigation arguments as properties
) : TrapezeScreen
If the screen returns a result, also create the result type:
@Parcelize
data class <ScreenName>Result(
// result properties
) : TrapezeNavigationResult
presentation/Place at: features/<feature-name>/presentation/src/main/java/<package>/presentation/<ScreenName>State.kt
data class <ScreenName>State(
// display properties
val eventSink: (<ScreenName>Event) -> Unit
) : TrapezeState
presentation/Place at: features/<feature-name>/presentation/src/main/java/<package>/presentation/<ScreenName>Event.kt
sealed interface <ScreenName>Event : TrapezeEvent {
// user interactions
}
presentation/Place at: features/<feature-name>/presentation/src/main/java/<package>/presentation/<ScreenName>StateHolder.kt
class <ScreenName>StateHolder @AssistedInject constructor(
// @Assisted params — navigation args extracted from screen by factory
@Assisted private val navigator: TrapezeNavigator,
// injected dependencies
) : TrapezeStateHolder<<ScreenName>Screen, <ScreenName>State, <ScreenName>Event>() {
@Composable
override fun produceState(): <ScreenName>State {
val wrappedSink = wrapEventSink { event ->
when (event) {
// handle events
}
}
return <ScreenName>State(
eventSink = wrappedSink
)
}
@AssistedFactory
fun interface Factory {
fun create(/* nav args, */ navigator: TrapezeNavigator): <ScreenName>StateHolder
}
}
presentation/Place at: features/<feature-name>/presentation/src/main/java/<package>/presentation/<ScreenName>Ui.kt
@Composable
fun <ScreenName>Ui(
state: <ScreenName>State,
modifier: Modifier = Modifier
) {
// stateless composable
}
presentation/Place at: features/<feature-name>/presentation/src/main/java/<package>/presentation/<ScreenName>Factories.kt
@ContributesIntoSet(AppScope::class)
class <ScreenName>StateHolderFactory @Inject constructor(
private val factory: <ScreenName>StateHolder.Factory
) : Trapeze.StateHolderFactory {
override fun create(screen: TrapezeScreen, navigator: TrapezeNavigator?): TrapezeStateHolder<*, *, *>? {
return if (screen is <ScreenName>Screen && navigator != null) {
factory.create(/* extract screen args, */ navigator)
} else null
}
}
@ContributesIntoSet(AppScope::class)
class <ScreenName>UiFactory @Inject constructor() : Trapeze.UiFactory {
override fun create(screen: TrapezeScreen): TrapezeUi<*>? {
return if (screen is <ScreenName>Screen) ::<ScreenName>Ui else null
}
}
Automatically generate test files following the conventions from the /add-tests skill:
src/test/)<ScreenName>StateHolderTest.kt — BehaviorSpec + Turbine via TrapezeStateHolder.test {}:
src/androidTest/)Three files following the robot pattern:
<ScreenName>UiTest.kt — JUnit4 test class using robotrobot/<ScreenName>UiRobot.kt — UI interactions and assertionstestdata/<ScreenName>UiTestData.kt — State factory methodsAll 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 ./gradlew :features:<feature-name>:presentation:compileDebugKotlin to verify compilation.
Report:
Then ask:
/add-interactor <feature-name> <InteractorName>