/stack-set: Stack Configuration Workflow
Goal
Analyze project files to detect the tech stack, resolve the target domain skill, then generate language-specific references in that skill's stack/ directory.
Vendor note: This workflow executes inline (no subagent spawning). All vendors use their native file reading tools for manifest detection and file writing tools for stack generation.
Step 1: Detect
Scan the project root for package manifests. Evaluate both tables independently — do not stop at the first match.
Backend manifests → domain backend
| File | Detection |
|:---|:---|
| pyproject.toml, requirements.txt, Pipfile | Python |
| package.json, tsconfig.json | Node.js/TypeScript |
| Cargo.toml | Rust |
| pom.xml, build.gradle, build.gradle.kts | Java/Kotlin |
| go.mod | Go |
| mix.exs | Elixir |
| Gemfile | Ruby |
| *.csproj, *.sln | C#/.NET |
Read manifest contents to detect framework:
- Python: FastAPI? Django? Flask?
- Node.js: NestJS? Express? Hono?
- Rust: Axum? Actix-web? Rocket?
- Java: Spring Boot? Quarkus?
Mobile manifests → domain mobile
| File | Detection |
|:---|:---|
| Package.swift, *.xcodeproj, *.xcworkspace, Podfile | Swift / iOS native |
| pubspec.yaml | Flutter |
| package.json with a react-native dependency | React Native |
For Swift / iOS native, additionally inspect the project to detect the UI framework:
- Look for
import SwiftUIin source files or aSwiftUIframework dependency inPackage.swift. - Default to SwiftUI when ambiguous.
Resolve target_skill
After scanning both tables, record every domain that has at least one detected manifest file:
| Detected domain | target_skill |
|:---|:---|
| backend only | oma-backend |
| mobile only | oma-mobile |
| both (monorepo) | carry both into Step 2 — do NOT first-match |
Multi-domain rule (amendment B): If manifests from both backend and mobile tables are found, collect both domains as the detected set and proceed to Step 2. Do not silently discard either.
Step 2: Confirm
Single-domain: backend
Present detection results and ask for confirmation:
Detected backend stack:
Language: {language}
Framework: {framework}
ORM: {orm}
Validation: {validation}
Migration: {migration}
Test: {test framework}
Correct? (Y/n) or modify:
Single-domain: mobile (Swift)
Present detection results and ask for confirmation:
Detected mobile stack:
Language: {language} (e.g. Swift)
UI: {ui} (e.g. SwiftUI)
API generator: {api_generator} (e.g. swift-openapi-generator)
API spec: {api_spec} (e.g. Core/Networking/openapi.yaml)
Structure: {structure} (e.g. App/Core/Features/Shared)
Test: {test} (e.g. XCTest)
Correct? (Y/n) or modify:
For Flutter or React Native mobile detection, present an equivalent confirmation block using the relevant fields (framework, sdk version, test framework, etc.).
Multi-domain: present choice first
When more than one domain was detected in Step 1, before showing any per-domain confirm block, ask:
Multiple domains detected in this repo:
[backend] {backend_language} / {backend_framework}
[mobile] {mobile_language} / {mobile_ui}
Generate stack references for: [both / backend / mobile]
After the user selects, show the per-domain confirmation block(s) for the chosen domain(s) and confirm each before generating.
Step 3: Generate
Write generated files into .agents/skills/{target_skill}/stack/.
- Backend →
.agents/skills/oma-backend/stack/ - Mobile →
.agents/skills/oma-mobile/stack/ - Multi-domain → run the appropriate generation sub-path for each selected domain in turn.
Backend path
stack.yaml
language: {language}
framework: {framework}
orm: {orm}
validation: {validation}
migration: {migration}
test: {test_framework}
source: detected
detected_from:
- {manifest_file}
verify: # consumed by `oma verify backend` (see _shared/core/stack-verify.schema.json)
detect: {manifest_file} # e.g. package.json, pyproject.toml
syntax:
cmd: "{syntax_check_cmd}" # e.g. bunx tsc --noEmit
tests:
cmd: "{test_cmd}" # e.g. bun test
skip_if_missing: "{optional_binary}"
tech-stack.md
Generate tech stack reference with these MANDATORY sections:
- Framework version and core API
- ORM/DB library and usage
- Validation library
- Migration tool
- Test framework
- Linter/formatter
snippets.md
Generate copy-paste code patterns. MANDATORY patterns (all 8 required):
- [ ] Route/Handler + Auth example
- [ ] Validation Schema example
- [ ] ORM Model/Entity example
- [ ] DI (Dependency Injection) example
- [ ] Repository pattern example
- [ ] Paginated Query example
- [ ] Migration example
- [ ] Test example
api-template.*
Generate CRUD endpoint boilerplate in the detected language.
Mobile path — Swift / iOS native
Adapt, not copy (amendment E): Seed from .agents/skills/oma-mobile/variants/swift-ios/ as the baseline, then adapt every value to match the detected project. Specifically:
- Replace placeholder
Features/module names with the actual feature module names found in the project (e.g.,Features/Auth,Features/Home). - Set
api_specto the actual path where the OpenAPI document lives in this project (defaultCore/Networking/openapi.yamlonly when no other location is found). - Set the minimum iOS deployment target to the value detected from
Package.swiftor.xcodeproj; default17.0when not specified. - Populate the DI wiring in the App entry snippet with the real
Clientand service types from the project, not generic placeholders.
Do not blind-copy the variant files; the generated stack/ must be project-specific.
stack.yaml — mandatory fields
language: swift
framework: swiftui # or uikit — adapt to detected value
ui: swiftui # adapt to detected value
api_generator: swift-openapi-generator
api_spec: {actual_path_to_openapi_yaml}
structure: App/Core/Features/Shared
test: XCTest
source: detected
detected_from:
- {manifest_file} # e.g. Package.swift
verify: # consumed by `oma verify mobile` (see _shared/core/stack-verify.schema.json)
detect: Package.swift
syntax:
cmd: "swift build"
skip_if_missing: "swift"
tests:
cmd: "swift test"
skip_if_missing: "swift"
tech-stack.md
Generate a Swift-specific tech stack reference with these MANDATORY sections:
- SwiftUI + Observation framework (
@Observable, iOS 17+) swift-openapi-generator+swift-openapi-runtime+swift-openapi-urlsession— SwiftPM build plugin wiringApp/Core/Features/Sharedmodule layout (App = entry/composition root, Core = networking/generated client/DI, Features = screen + view-model verticals, Shared = reusable UI/utils)- API spec provenance: where
{api_spec}comes from, how it is kept in sync with the backend producer - Test framework (XCTest / Swift Testing)
- Linter/formatter (SwiftLint if present)
snippets.md — mandatory Swift snippet set (all required)
- [ ]
Package.swiftwith theOpenAPIGeneratorbuild plugin declared andopenapi.yamlspec discovery configured - [ ]
openapi-generator-config.yaml— generator configuration (namespace, accessibility, etc.) - [ ]
@Observableview model (Observation framework, async data loading, error state) - [ ] SwiftUI feature view consuming the view model
- [ ]
Core/Networkingservice wrapping the generatedClient(URLSession transport, bearer auth middleware) - [ ] Generated-client call pattern (
Operations.listItems,Operations.createItem, etc.) - [ ] App entry point + DI composition root (wiring
Client→ service → view model) - [ ] XCTest example for the service or view model
api-template.swift
Generate a CRUD service built on the generated Client (using Operations.* call patterns from swift-openapi-generator). This is the Swift analogue of the backend api-template.*. The template must:
- Import and instantiate the generated
Client(not a hand-rolledURLSessionrequest builder). - Implement list, get-by-id, create, update, and delete operations using
Operations.*types. - Handle transport errors and map them to domain error types.
- Use
async/awaitthroughout.
Step 4: Verify
Confirm generated files meet requirements.
Backend checks
- [ ]
stack.yamlhaslanguage,framework,orm,validationfields - [ ]
stack.yamlhas averify:block with runnablesyntax.cmdandtests.cmd(otherwiseoma verify backendcannot dispatch) - [ ]
snippets.mdcontains all 8 mandatory patterns - [ ]
tech-stack.mdcontains all 6 mandatory sections - [ ]
api-templatefile uses the correct language extension - [ ] Code follows existing project conventions
Mobile (Swift) checks
- [ ]
stack.yamlhaslanguage,api_generator,api_spec, andstructurefields populated with project-specific values (not variant defaults) - [ ]
stack.yamlhas averify:block with runnablesyntax.cmdandtests.cmd(otherwiseoma verify mobilecannot dispatch) - [ ]
snippets.mdincludes the generator configuration snippet (openapi-generator-config.yaml) and at least one snippet that uses the generatedClientviaOperations.* - [ ]
api-template.swiftuses the generated client — not hand-rolledURLSessionrequest construction - [ ]
tech-stack.mddocuments whereapi_specoriginates and how it syncs from the backend producer - [ ] Module names in snippets reflect real
Features/modules detected in the project, not generic placeholders
Constraints
- Do NOT modify
.agents/skills/{target_skill}/SKILL.md(abstract interface is protected) - Do NOT modify
resources/common files under any skill - Only create or modify files in the resolved skill's
stack/directory - If
stack/already exists for the resolved domain skill, ask before overwriting target_skillis always the resolved domain skill (oma-backendoroma-mobile); never hardcode a single skill name in generation logic