Arturo Quest System¶
Overview¶
The Quest System is Arturo's core work-tracking feature, measuring outcome-scoped work in pomodoros (25-minute focused sessions) and cycles (4 pomodoros). Quests are tiered by effort: errand (1-2p), venture (1 cycle), quest (2-4c), expedition (5-10c), and saga (10+c).
Lifecycle¶
Quests progress through: proposed -> charted -> active -> completed (or abandoned). Each quest can have multiple role assignments with independent effort estimates.
When a quest is created without an explicit issue_url, Arturo automatically opens a corresponding GitLab issue in the astrolabe knowledge repo (the-smithy1/agents/astrolabe). The issue is labelled quest::<title-slug> and tier::<tier>, along with any domain tags.
Contributor Linkage¶
Quest roles can optionally be linked to a contributor identity via contributor_id and contributor_source (currently 'spyder'). These fields are stored on the quest_roles table and are set when assigning a role:
quest_service.add_quest_role(
quest_id=42,
role_name="implementer",
scope="backend API",
estimated_pomodoros=8,
contributor_id=117,
contributor_source="spyder",
)
If a role is re-assigned (upsert on quest_id, role_name), existing contributor values are preserved unless explicitly overwritten (COALESCE logic).
Shimmer Credits¶
On quest completion, contributors linked to roles automatically receive shimmer credits based on the quest tier:
| Tier | Credits |
|---|---|
| errand | 5 |
| venture | 15 |
| quest | 40 |
| expedition | 100 |
| saga | 250 |
Credits are created as pending entries in the shimmer_credit_log table and delivered asynchronously by the scheduler via retry_pending_shimmer_credits(). This avoids blocking the completion path with synchronous HTTP calls. Credit statuses are: pending, sent, or failed.
Prerequisites: A role must have a non-null contributor_id to receive credits. Roles without a linked contributor are skipped.
Auto-Completion¶
When ARTURO_QUEST_AUTO_COMPLETE=true, the QuestCompletionService monitors merged MRs. If all MRs linked to a quest have been merged, the quest is automatically marked complete. Completion now also triggers shimmer credit issuance for any contributor-linked roles (see Shimmer Credits).
Key Code Paths¶
| File | Purpose |
|---|---|
src/services/quest_service.py |
Quest CRUD, velocity calculation, GitLab issue creation (target project: the-smithy1/agents/astrolabe), shimmer credit issuance |
src/services/quest_completion_service.py |
Auto-complete on MR merge |
src/services/feedback_service.py |
Mobile feedback pipeline: screenshot analysis via Claude vision and GitLab issue creation |
src/handlers/quest_command_handler.py |
/arturo quest Slack commands |
src/api/router.py |
REST API endpoints for quest operations, feedback, and CI/automation notifications |
src/core/schema.sql |
Schema including quest_roles contributor columns and shimmer_credit_log table |
src/core/migrations/006_quest_contributor_linkage.sql |
Migration adding contributor linkage and shimmer credit log |
agents_shared/notify.py (agents-shared) |
Shared notify substrate: NotifyHandler and attach_notify_routes used by the /notify endpoint |
Slack Commands¶
/arturo quest create <title> --tier <tier> --effort <Np>-- Create a quest/arturo quest list [status]-- List quests/arturo quest view <id>-- View quest details/arturo quest update <id> --status <s>-- Update quest/arturo quest log <id> <Np> [notes]-- Log time/arturo quest velocity [weeks]-- Velocity report
API Endpoints¶
GET /api/v1/quest/list-- List quests. Supports optional query parameters:status-- Filter by quest statusdomain-- Filter by domaininclude_roles-- Set totrue,1, oryesto include role details, contributor info, and role counts (roles_total,roles_filled,roles_open) in the responseGET /api/v1/quest/{id}-- Quest details (roles now includecontributor_idandcontributor_source)POST /api/v1/quest/create-- Create questPATCH /api/v1/quest/{id}-- Update questGET /api/v1/velocity-- Quest velocity reportPOST /api/v1/feedback/analyze-- Analyze a mobile screenshot and logs using Claude vision. Returns a draft description, suggested category (bug,suggestion, orquestion), and confidence score. Requiresfeedback_serviceto be configured; returns503otherwise.POST /api/v1/feedback/submit-- Submit confirmed feedback as a GitLab issue. Requires adescriptionfield in the JSON body. The issue is created in the GitLab project mapped to theclient_name(e.g.,Smithy-Reader,Smithy-iOS). Returns503iffeedback_serviceis not configured.POST /api/v1/notify-- Post a Slack message through Arturo's bot voice. Intended for CI/automation pipelines to post build, deploy, and release outcomes. Wired through the sharedagents_shared.notifysubstrate (agents-shared#37). Accepts a JSON body with:text(required) -- Non-empty message stringchannel(optional) -- Slack channel override; omit or set tonullto use the default channellevel(optional) -- One ofinfo,success,error, orwarning. Prepends an emoji (ℹ️,✅,❌,⚠️) totextwhen supplied. Callers may also pass fully formattedtextand omitlevel.
Default channel: Configured via the ARTURO_CI_NOTIFY_CHANNEL environment variable (k8s configmap). Falls back to #build-alerts when the variable is absent or blank.
Prerequisites: The route is only registered when a slack_client is injected into ApiRouter (always true in production; omitted in unit tests that don't need it). Requires Bearer auth like all other /api/v1 routes.
Responses: 200 {ok: true, data: {ts, channel}} on success; 400 for missing or empty text; 401 for missing/wrong Bearer token; 502 for Slack post failures.
Example: List quests with roles¶
Response entries include:
{
"id": 42,
"title": "Implement shimmer integration",
"tier": "quest",
"status": "active",
"roles": [
{
"role_name": "implementer",
"scope": "backend API",
"status": "assigned",
"contributor_id": 117
}
],
"roles_total": 1,
"roles_filled": 1,
"roles_open": 0
}
Example: Analyze mobile feedback¶
POST /api/v1/feedback/analyze
Content-Type: application/json
{
"screenshot_base64": "<base64-encoded image>",
"logs": "recent client log lines...",
"app_name": "Smithy-Reader",
"device_info": {"os": "iOS 18.1", "model": "iPhone 15"},
"current_room": "The Great Hall"
}
Response:
{
"ok": true,
"data": {
"draft_description": "The screenshot shows a rendering glitch in the room description panel...",
"suggested_category": "bug",
"confidence": 0.85
}
}
Example: Submit feedback as GitLab issue¶
POST /api/v1/feedback/submit
Content-Type: application/json
{
"category": "bug",
"description": "Rendering glitch in room description panel",
"client_name": "Smithy-Reader",
"app_name": "Smithy-Reader",
"device_info": {"os": "iOS 18.1", "model": "iPhone 15"},
"current_room": "The Great Hall"
}
Response:
{
"ok": true,
"data": {
"status": "created",
"issue_url": "https://gitlab.com/the-smithy1/mobile/reader/-/issues/42",
"issue_number": 42
}
}
Supported clients for feedback routing:
client_name |
GitLab project |
|---|---|
Smithy-Reader |
the-smithy1/mobile/reader |
Smithy-iOS |
the-smithy1/ios |
Smithy-Looper |
the-smithy1/mobile/looper |
Smithy-Companion |
the-smithy1/mobile/companion |
Unknown clients default to the-smithy1/TheSmithy.
Example: Post a CI notification¶
curl -sf -X POST "$ARTURO_API_BASE_URL/api/v1/notify" \
-H "Authorization: Bearer $ARTURO_INTERNAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"text": "dev-cd #142 deploy succeeded", "level": "success"}'
Response:
To post to a specific channel instead of the default:
curl -sf -X POST "$ARTURO_API_BASE_URL/api/v1/notify" \
-H "Authorization: Bearer $ARTURO_INTERNAL_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"text": "rollback initiated", "channel": "#incidents", "level": "warning"}'
Feature Repositories¶
arturo→ project_id:the-smithy1/agents/arturo
Code Paths to Explore¶
tests/test_quest_service.pyinarturosrc/api/router.pyinarturosrc/handlers/quest_command_handler.pyinarturosrc/services/quest_completion_service.pyinarturosrc/services/quest_service.pyinarturosrc/services/feedback_service.pyinarturo
Feature Repositories¶
arturo→ project_id:the-smithy1/agents/arturo
Code Paths to Explore¶
tests/test_quest_service.pyinarturosrc/api/router.pyinarturosrc/handlers/quest_command_handler.pyinarturosrc/services/quest_completion_service.pyinarturosrc/services/quest_service.pyinarturo