Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
356290e
API module skill
motorro Sep 8, 2026
41a6c08
Adds implementation module
motorro Sep 14, 2026
382cacb
Skills building script
motorro Sep 15, 2026
561e8b9
States and testing
motorro Sep 15, 2026
795b149
Interstate data testing
motorro Sep 15, 2026
7ac7a4f
Library updates 2026-09
motorro Sep 17, 2026
ca7a1e9
Creating UI
motorro Sep 19, 2026
d2be340
DI and API implementation
motorro Sep 20, 2026
5ab5224
Checks skills example
motorro Sep 20, 2026
ff6aca8
Boilerplate skill fixes
motorro Sep 20, 2026
9df6f2a
Boilerplate skill fixes (take 2)
motorro Sep 20, 2026
78819ac
Parent factory implementation reference
motorro Sep 22, 2026
90517b5
Content state stub
motorro Sep 23, 2026
839a35d
Friends stub
motorro Sep 23, 2026
6e77f61
Boilerplate skill example
motorro Sep 23, 2026
fed643e
Module conflict fix
motorro Sep 23, 2026
0776b8f
Building skill fixed
motorro Sep 23, 2026
0a7417f
Convention plugins
motorro Sep 25, 2026
602a32f
Convention publishing
motorro Sep 28, 2026
bdec092
Skills repackaged to use with npx
motorro Sep 30, 2026
4510e46
Add state skill
motorro Oct 2, 2026
0693ee0
Demo skill
motorro Oct 2, 2026
0abc25b
Another flow inside the demo
motorro Oct 2, 2026
f496089
Another flow inside the demo (a-b variants)
motorro Oct 2, 2026
ebe235f
Build flavors for A-B variants
motorro Oct 3, 2026
032d45f
Strict result types in common flow composition
motorro Oct 5, 2026
b31b714
Journeys skill
motorro Oct 6, 2026
bfd8daa
Library updates 2026-10
motorro Oct 6, 2026
940aaae
Removes the obsolete check task
motorro Oct 6, 2026
069f676
More memory
motorro Oct 6, 2026
9894188
Toolchain update
motorro Oct 6, 2026
ac4f4e9
AI TLDR
motorro Oct 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
20 changes: 20 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
# Rebuilds the packaged skills (skills/) from their sources (skills-src/) and stages
# the result, so any changes are included in the commit being made.
set -e

repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"

if [ ! -f "skills-src/build_skills.sh" ]; then
echo "Warning: skills-src/build_skills.sh not found, skipping skills rebuild."
exit 0
fi

echo "Rebuilding skills/ from skills-src/..."
bash skills-src/build_skills.sh

echo "Adding changes..."
git add skills

exit 0
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Check with gradle
run: ./gradlew runUnitTests :examples:lce:assembleDebug :examples:welcome:welcome:assembleDebug :examples:multi:navbar:assembleDebug :examples:multi:parallel:assembleDebug :examples:lifecycle:assembleDebug :examples:di:app:assembleDebug :examples:book:app:assembleDebug :examples:book:book:demo:assembleDebug checkLegacyAbi --no-daemon --no-configuration-cache
run: ./gradlew runUnitTests :examples:lce:assembleDebug :examples:welcome:app:assembleDebug :examples:multi:navbar:assembleDebug :examples:multi:parallel:assembleDebug :examples:lifecycle:assembleDebug :examples:di:app:assembleDebug :examples:book:app:assembleDebug :examples:book:book:demo:assembleDebug :examples:book:app:assembleDebug :examples:skills:auth:demo:assembleHappyPathDebug :examples:skills:auth:demo:assembleConnectionErrorsDebug :examples:skills:app:assembleDebug checkLegacyAbi --no-daemon --no-configuration-cache
- name: Upload problems report
uses: actions/upload-artifact@v4
if: failure()
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
/.idea
.DS_Store
/build
/Claude outputs
/artifacts
/.kotlin
build
/captures
Expand Down
44 changes: 44 additions & 0 deletions .run/Check All.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Check All" type="GradleRunConfiguration" factoryName="Gradle" activateToolWindowBeforeRun="false">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runUnitTests" />
<option value=":examples:lce:assembleDebug" />
<option value=":examples:welcome:app:assembleDebug" />
<option value=":examples:multi:navbar:assembleDebug" />
<option value=":examples:multi:parallel:assembleDebug" />
<option value=":examples:lifecycle:assembleDebug" />
<option value=":examples:di:app:assembleDebug" />
<option value=":examples:book:app:assembleDebug" />
<option value=":examples:book:book:demo:assembleDebug" />
<option value=":examples:book:app:assembleDebug" />
<option value=":examples:skills:auth:demo:assembleHappyPathDebug" />
<option value=":examples:skills:auth:demo:assembleConnectionErrorsDebug" />
<option value=":examples:skills:app:assembleDebug" />
<option value="checkLegacyAbi" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<EXTENSION ID="com.android.tools.idea.testartifacts.testsuite.GradleRunConfigurationExtension">
<com.android.tools.idea.testartifacts.testsuite.SHOW_TEST_RESULT_IN_ANDROID_TEST_SUITE_VIEW>false</com.android.tools.idea.testartifacts.testsuite.SHOW_TEST_RESULT_IN_ANDROID_TEST_SUITE_VIEW>
<android.execution.deploysToLocalDevice>false</android.execution.deploysToLocalDevice>
</EXTENSION>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<method v="2" />
</configuration>
</component>
37 changes: 37 additions & 0 deletions .run/Journeys.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Journeys" type="TestSuiteRunConfigurationType" factoryName="TestSuiteRunConfigurationFactory">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/examples/skills/auth/journey" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="testJourneys" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<ExternalSystemDebugDisabled>false</ExternalSystemDebugDisabled>
<EXTENSION ID="com.android.studio.ml.journeys.gradle.runconfiguration.GeminiEnabledTestSuiteRunConfigurationExtension">
<com.android.studio.ml.journeys.gradle.runconfiguration.FORWARD_GEMINI_ACCESS_TOKEN_KEY>true</com.android.studio.ml.journeys.gradle.runconfiguration.FORWARD_GEMINI_ACCESS_TOKEN_KEY>
</EXTENSION>
<EXTENSION ID="com.android.tools.idea.testartifacts.testsuite.GradleRunConfigurationExtension">
<com.android.tools.idea.testartifacts.testsuite.SHOW_TEST_RESULT_IN_ANDROID_TEST_SUITE_VIEW>true</com.android.tools.idea.testartifacts.testsuite.SHOW_TEST_RESULT_IN_ANDROID_TEST_SUITE_VIEW>
<android.execution.deploysToLocalDevice>true</android.execution.deploysToLocalDevice>
</EXTENSION>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>true</RunAsTest>
<GradleProfilingDisabled>false</GradleProfilingDisabled>
<GradleCoverageDisabled>false</GradleCoverageDisabled>
<testEngineIds>
<testEngineId id="journeys-test-engine" />
</testEngineIds>
<method v="2" />
</configuration>
</component>
63 changes: 63 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# AGENTS.md

## Project Overview
**CommonStateMachine** is a lightweight, non-opinionated Kotlin Multiplatform (KMP) library that implements a finite-state machine pattern for MVI (Model-View-Intent) architectures.

### Key Architecture Concepts
- **`CommonStateMachine`**: Acts as a bridge between the active logical state and the UI. `FlowStateMachine` exports state updates as a Kotlin `StateFlow`.
- **`CommonMachineState`**: Encapsulates state-bound business logic, processes user gestures (`G`), emits UI states (`U`), and handles transitions to other states. Supports state-scoped coroutines via `CoroutineState`.
- **StateMachine Class diagram**: Take a look at the framework [class diagram](doc/StateMachine.puml).
- **State Separation & DI Abstractions**:
- **Use-cases**: Business logic isolated from view logic.
- **View-state Renderer**: Decouples UI rendering logic from logical state transitions.
- **Context & State Factories**: Common `Context` delegates dependencies to states; dedicated factories (`StateFactory`) create states using inter-state dynamic data.
- **Multi-Module Support (`ProxyMachineState`)**:
- Wraps nested feature flows within a parent state machine.
- Bridges heterogeneous gesture and UI state systems through mapping adapters (`mapGesture`, `mapUiState`).
- Standardized via `commonflow` modules (`commonflow-data`, `commonflow-compose`, `commonflow-viewmodel`).
- Take a look at the [proxy lifecycle diagram](doc/ProxyLifecycle.puml).
- **Parallel Machine Composition (`MultiMachineState`)**:
- Runs multiple state machines concurrently or selectively in parallel using `ProxyMachineContainer`.
- Manages active/dormant machine lifecycles via `MachineLifecycle`.

---

## Build and Verification
If you need to test if everything in the project compiles and unit tests pass:

1. Take the GitHub action: `.github/workflows/check.yml`.
2. Find and execute the Gradle command from the step: `Check with gradle`.

---

## Examples
Example projects demonstrating various architectures, state machine features, and usage patterns are located in the `examples` folder:
- **`examples/lce`**: Basic Load-Content-Error pattern.
- **`examples/welcome`**: Multi-module on-boarding flow.
- **`examples/multi`**: Parallel state machines (`parallel`), bottom navbar navigation (`navbar`), and mixed gesture/UI state composition (`mixed`).
- **`examples/lifecycle`**: View lifecycle tracking and operation pausing on lifecycle changes.
- **`examples/di`**: Dynamic child flow binding with Hilt.
- **`examples/skills`**: Multi-module example demonstrating custom skills implementation.

---

## Skills
There are two folders managing skills:
- **`skills-src`**: Source files used to develop and maintain skills. **Always edit skill files in `skills-src`**, never directly in `skills/`.
- **Shared resources**: Reusable files and templates are stored in `.shared/` subfolders.
- **Asset symlinks**: Code examples in `assets/` subfolders are symlinked from `examples/skills/` so they remain compilable and testable.
- **`skills`**: Contains complete, self-contained generated skills for distribution (e.g. `npx skills`). Do not edit files here directly—they are automatically generated from `skills-src/` via [the build script](skills-src/build_skills.sh) (executed automatically by [.githooks/pre-commit](.githooks/pre-commit) upon commit).

---

## Coding conventions
- Use KDoc for documenting classes, interfaces, and public functions.
- Follow standard Kotlin coding conventions and style guidelines.
- Add copyright headers at the top of Kotlin source files.
- When checking for boolean `false`, use the `.not()` extension function instead of `!` for clarity (e.g., `if (condition.not()) { ... }`).
- Use Yoda style for equality comparisons (e.g., `if ("a" == b) { ... }`).

## Disk operations
- When moving or renaming files, use `git mv` instead of deleting the old file and creating a new file at the new path, so file history and changes remain tracked.
- When deleting files, use `git rm` so the removal is properly tracked by Git.

Loading