Create well-defined issues (bugs, features, tasks) using Socratic questioning to eliminate ambiguity...
Hard rules:
/define/define unless the user explicitly asks for analysis-only validation/define.mobius/issues/...) after user approvalIf the user asks for both definition and implementation in one request:
/refine or /execute as the next command# mobius.config.yaml
backend: linear # or 'jira' or 'local'
The backend determines the output format for issue specifications.
# mobius.config.yaml
backend: local
If the backend is local, the entire CLI-based creation flow is bypassed. The Socratic questioning workflow remains identical — only the final output step changes.
The counter file tracks the next available ID. Use an atomic read-increment-write pattern:
{"nextTaskNumber": 1, "lastUpdated": "..."} if missing)nextTaskNumber valueLOC-{N} zero-padded to 3 digits (e.g., LOC-001, LOC-012)# Read current counter (or initialize if missing)
COUNTER_FILE=".mobius/issues/counter.json"
if [ ! -f "$COUNTER_FILE" ]; then
mkdir -p .mobius/issues
echo '{"nextTaskNumber": 1, "lastUpdated": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' > "$COUNTER_FILE"
fi
# Read the current value
NEXT_NUM=$(cat "$COUNTER_FILE" | jq '.nextTaskNumber')
After reading, immediately increment and write back:
# Increment and write back atomically
echo "{\"nextTaskNumber\": $((NEXT_NUM + 1)), \"lastUpdated\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" > "$COUNTER_FILE"
Format the identifier:
LOC_ID=$(printf "LOC-%03d" $NEXT_NUM)
Edge case — counter.json missing or corrupted: Scan existing LOC-* directories under .mobius/issues/ to find the highest number, then set nextTaskNumber to max + 1.
The JSON schema follows the ParentIssueContext type from src/types/context.ts:
{
"id": "LOC-001",
"identifier": "LOC-001",
"title": "Issue title from Socratic questioning",
"description": "## Summary\n\nFull markdown description with acceptance criteria...",
"gitBranchName": "feature/loc-001",
"status": "Backlog",
"labels": ["Feature"],
"url": ""
}
Field mapping for local mode:
| Field | Value |
|---|---|
id |
Same as identifier (e.g., LOC-001) |
identifier |
Generated LOC-{N} ID |
title |
Issue title from investigation |
description |
Full markdown description with acceptance criteria |
gitBranchName |
feature/{loc-id} lowercase (e.g., feature/loc-001) |
status |
"Backlog" (initial state) |
labels |
Array of label strings (e.g., ["Bug"], ["Feature"]) |
url |
Empty string "" (no backend URL) |
Directory creation and file write:
# Create the issue directory
mkdir -p ".mobius/issues/${LOC_ID}/tasks"
mkdir -p ".mobius/issues/${LOC_ID}/execution"
Then use the Write tool to create parent.json with the full issue spec.
Also create the context.json wrapper file:
{
"parent": { ... },
"subTasks": [],
"metadata": {
"fetchedAt": "2026-01-30T12:00:00Z",
"updatedAt": "2026-01-30T12:00:00Z",
"backend": "local"
}
}
Ensure .mobius/.gitignore exists: If .mobius/.gitignore does not exist, create it with:
# Mobius local state - gitignored by default
*
!.gitignore
After Socratic questioning is complete, present the issue for approval (same as CLI flow):
"Here is the issue I'll create:
Title: [title] ID: [LOC-{N}] (local) Type/Labels: [Bug/Feature/Improvement] Priority: [Urgent/High/Normal/Low] Description: [full description with acceptance criteria]
Ready to create this local issue?"
Use AskUserQuestion:
After writing the files:
"Local issue created successfully!
{LOC-ID}: {Issue Title}
Location: .mobius/issues/{LOC-ID}/parent.json
Would you like to:
/refine {LOC-ID})What stays the same:
# mobius.config.yaml
backend: jira
jira:
base_url: https://yourcompany.atlassian.net
project_key: PROJ
Jira Concepts:
Before presenting options to the user, read team, project, and label defaults from the config file.
For Linear backend — read from config:
linear:
team: Engineering
project: My Project
default_labels: [Bug, Feature, Improvement]
For Jira backend — read from config:
jira:
base_url: https://yourcompany.atlassian.net
project_key: PROJ
default_labels: [bug, story, task]
Workflow:
CLI availability check (run once at start):
# For Linear backend
command -v linearis >/dev/null 2>&1 || echo "linearis not found. Install via: npm install -g linearis"
# For Jira backend
command -v acli >/dev/null 2>&1 || echo "acli not found. See: https://developer.atlassian.com/cloud/acli/"
For searching related issues (when user mentions related work):
# Linear: search for related issues
linearis issues search "search terms"
# Jira: search for related issues
acli jira workitem search --jql "summary ~ 'search terms' AND project = PROJ"
This approach avoids runtime metadata fetching and uses config defaults instead.
If user provides no context (just invoked the skill), use AskUserQuestion:
Question: "What kind of issue do you need to create?"
Options:
Then proceed directly with issue questioning. Do not perform implementation actions.
The goal is to create issues with no ambiguity for execution and verification.
Interactive questioning flow:
Anti-Ambiguity Checklist (verify before creating):
AskUserQuestion patterns:
For scope clarification:
Question: "Which parts of the system does this affect?"
Options:
1. **Frontend only** - UI components, styling, client-side logic
2. **Backend only** - API, database, server-side logic
3. **Full stack** - Both frontend and backend changes
4. **Infrastructure** - CI/CD, deployment, configuration
For edge case handling:
Question: "What should happen when the operation fails?"
Options:
1. **Show error message** - Display user-friendly error and allow retry
2. **Silent fallback** - Use default behavior without notification
3. **Block operation** - Prevent action until issue resolved
4. **Log and continue** - Record error but proceed with degraded functionality
For verification method:
Question: "How should we verify this criterion is met?"
Options:
1. **Automated test** - Unit/integration test that can run in CI
2. **Manual testing** - Step-by-step verification by human
3. **Observable behavior** - Visible in logs, metrics, or UI
4. **Code review** - Verified by inspecting the implementation
Continue questioning until all aspects are crystal clear.
## Summary
[1-2 sentence overview of the issue]
## Current Behavior (bugs only)
[What happens now that shouldn't]
## Expected Behavior
[What should happen instead]
## Reproduction Steps (bugs only)
1. Step one
2. Step two
3. Observe issue
## Acceptance Criteria
- [ ] Criterion 1 with verifiable outcome
- **Verification**: `test command` | manual step | observable
- [ ] Criterion 2 with test method
- **Verification**: `test command` | manual step | observable
- [ ] Criterion 3 with manual verification step
- **Verification**: `test command` | manual step | observable
## Additional Context
[Screenshots, logs, related issues]
GOOD (outcomes):
BAD (implementation):
Each criterion should be:
Do NOT create checkpoints for:
[Specific question that needs answering - one decision per checkpoint]
Option A - [Name]
Option B - [Name]
Option C - [Name] (optional)
[If the agent has a recommendation, state it with reasoning. Otherwise: "No strong recommendation - depends on team preference."]
If no decision is made within [timeframe, e.g., "24 hours" or "before next sprint"], proceed with: [Option X] Reason: [Why this is a safe default]
This decision blocks: [List of dependent sub-tasks or issues]
</checkpoint_template>
<checkpoint_example>
**Scenario**: Implementing dark mode feature requires deciding how to persist theme preference.
```markdown
## Summary
Choose the approach for persisting user theme preference.
## Type: checkpoint:decision
## Decision Required
How should we persist the user's theme preference across sessions?
## Options
1. **localStorage only**
- Pros: Simple implementation, no server changes, immediate read
- Cons: Not available during SSR, can flash wrong theme on load
- Example: `localStorage.setItem('theme', 'dark')`
2. **Cookie only**
- Pros: Available during SSR, no theme flash
- Cons: Sent with every request, 4KB limit, requires cookie parsing
- Example: `document.cookie = 'theme=dark; max-age=31536000'`
3. **Cookie + localStorage hybrid**
- Pros: SSR-friendly AND fast client reads, best UX
- Cons: More complex, must keep in sync
- Example: Cookie for SSR, localStorage for client preference changes
## Recommendation
**Option 3 (hybrid)** if SSR is used, otherwise **Option 1 (localStorage)**.
Our app uses Next.js with SSR, so the hybrid approach prevents theme flash.
## Default Behavior
If no decision is made within 24 hours, proceed with: **Option 1 (localStorage)**
Reason: Simplest implementation; theme flash is acceptable for initial release.
## Blocks
This decision blocks: MOB-125 (Create ThemeProvider), MOB-126 (Add useTheme hook)
If the checkpoint is critical and has no safe default, escalate to the issue creator.
The agent executing dependent tasks should read the checkpoint's decision before implementing.
Gathering workflow:
team, project, and default_labels from config linear: sectiondefault_labels via AskUserQuestionFor Jira:
project_key and default_labels from config jira: sectiondefault_labels via AskUserQuestionFor related issues: Ask the user if they know of related issues, or use CLI to search:
# Linear: search for related issues
linearis issues search "search terms"
# Jira: search for related issues
acli jira workitem search --jql "summary ~ 'search terms' AND project = PROJ"
Linear relationships (included in output):
blocks: Issues this one blocksblockedBy: Issues blocking this onerelatedTo: Related issuesduplicateOf: If this duplicates another issueJira links (included in output):
Question: "What priority should this have?"
Options:
"Here is the issue I'll create:
Title: [title] Team/Project: [team or project name] Type/Labels: [Bug/Feature/Improvement or issue type] Priority: [Urgent/High/Normal/Low] State/Status: [initial state] Description: [full description with acceptance criteria]
Relationships: [if any] Parent: [if applicable]
Ready to create this issue?"
Use AskUserQuestion:
For Linear — use linearis issues create:
linearis issues create "{issue title}" \
--team "{team from config}" \
--description "{full description with acceptance criteria}" \
--priority {1-4} \
--state "{initial state}" \
--labels "{label1},{label2}"
For Jira — use acli jira workitem create:
acli jira workitem create \
--project "{project_key from config}" \
--type "{Bug|Story|Task}" \
--summary "{issue title}" \
--description "{full description with acceptance criteria}" \
--priority "{High|Medium|Low}"
After creation, parse the JSON output to extract the issue ID and URL.
If CLI is not installed, report a clear error:
npm install -g linearis""Issue created successfully!
{Issue ID}: {Issue Title} URL: {issue URL from CLI output}
Would you like to:
Response flow with AskUserQuestion:
After gathering all details, present for approval:
"Here is the issue I'll create:
Title: Schedule deactivation throws 500 error Team: Engineering Type: Bug Priority: Urgent (1) State: Todo
Description:
Users receive HTTP 500 error when deactivating schedules. ...
Ready to create this issue?"
After approval, create via CLI:
linearis issues create "Schedule deactivation throws 500 error" \
--team "Engineering" \
--description "## Summary
Users receive HTTP 500 error when deactivating schedules.
## Current Behavior
Clicking 'Deactivate' shows error toast and schedule remains active.
## Expected Behavior
Schedule deactivates successfully with confirmation message.
## Reproduction Steps
1. Navigate to Schedule Settings
2. Click 'Deactivate Schedule'
3. Observe 500 error in toast
## Acceptance Criteria
- [ ] User can deactivate schedule without error
- **Verification**: Manual test - click Deactivate, observe success toast
- [ ] Schedule status updates to 'inactive'
- **Verification**: \`npm test -- --grep 'schedule deactivation'\`
- [ ] Team members see schedule status change
- **Verification**: Manual test - check team view after deactivation
- [ ] Error logs capture root cause for monitoring
- **Verification**: Observable - check logs after fix deployment" \
--priority 1 \
--state "Todo" \
--labels "Bug"
Report result to user:
"Issue created successfully!
MOB-200: Schedule deactivation throws 500 error URL: https://linear.app/mobius/issue/MOB-200
Would you like to break this down into sub-tasks (/refine)?"
Response flow with thorough AskUserQuestion:
After gathering all details and approval, create via CLI:
linearis issues create "Add dark mode theme support" \
--team "Engineering" \
--description "## Summary
Add dark mode support with system preference detection and manual toggle.
## Expected Behavior
- App detects system dark mode preference on launch
- User can manually toggle between light/dark/system
- All screens render correctly in both modes
## Scope
**In scope**: All core screens, settings, navigation
**Out of scope**: Admin dashboard (separate issue)
## Acceptance Criteria
- [ ] Theme follows system preference by default
- **Verification**: \`npm test -- --grep 'theme system preference'\`
- [ ] Settings screen has theme toggle (Light/Dark/System)
- **Verification**: Manual test - navigate to Settings, verify toggle exists
- [ ] All text maintains 4.5:1 contrast ratio in both modes
- **Verification**: \`npm run test:a11y\` or Lighthouse accessibility audit
- [ ] Theme preference persists across app restarts
- **Verification**: Manual test - set theme, restart app, verify theme persists
- [ ] No flash of wrong theme on app launch
- **Verification**: Observable - launch app in dark mode, no white flash
## Edge Cases
- If localStorage is unavailable, default to system preference
- If system preference API unavailable, default to light mode" \
--priority 3 \
--state "Backlog" \
--labels "Feature"
Report result to user:
"Issue created successfully!
MOB-201: Add dark mode theme support URL: https://linear.app/mobius/issue/MOB-201
This is a larger feature. Would you like to break it down into sub-tasks (/refine MOB-201)?"
This skill creates issues directly via CLI — no structured YAML output needed.
For Linear — use linearis issues create:
# Write description to a temp file for multi-line content
DESCRIPTION=$(cat <<'DESC'
## Summary
{description content}
## Acceptance Criteria
- [ ] Criterion 1
- **Verification**: test command or manual step
DESC
)
linearis issues create "{issue title}" \
--team "{team from config}" \
--description "$DESCRIPTION" \
--priority {1-4} \
--state "{initial state}" \
--labels "{label1},{label2}"
For Jira — use acli jira workitem create:
DESCRIPTION=$(cat <<'DESC'
## Summary
{description content}
## Acceptance Criteria
- [ ] Criterion 1
- **Verification**: test command or manual step
DESC
)
acli jira workitem create \
--project "{project_key from config}" \
--type "{Bug|Story|Task}" \
--summary "{issue title}" \
--description "$DESCRIPTION" \
--priority "{High|Medium|Low}"
After successful creation:
If CLI command fails:
npm install -g linearisRelationship handling:
blocks: Issues that cannot start until this one completesblockedBy: Issues that must complete before this one can startrelatedTo: Related issues for referenceduplicateOf: Mark as duplicate of existing issueBackend-specific field mappings:
| Field | Linear (CLI) | Jira (acli) |
|---|---|---|
team / project |
--team flag |
--project flag |
priority |
--priority {1-4} |
--priority {High/Medium/Low} |
state / status |
--state flag |
N/A (uses workflow default) |
labels / type |
--labels flag (comma-separated) |
--type flag |
Don't skip acceptance criteria:
Don't assume priority:
Don't ignore relationships:
Don't create compound issues:
Don't write untestable acceptance criteria:
Verification: Lighthouse performance score > 90Verification: Visual regression testDon't start coding from define:
src/* right after issue creation/refine or /execute/define (except local backend issue artifacts)