/lets-work - Session Workflow Orchestrator
The single skill for this workspace covering project/store resolution, session start-of-day setup, Asana task-context loading, and the dev-to-QA handoff. Net-new relative to add-to-qa-retainer (doesn't reuse its code) but inherits several hard-won constraints from that skill's learnings log - see "Constraints carried over" below.
Determine the phase before doing anything
Each invocation must first work out where the active task/project stands - never assume this is always a "start" or always a "finish" call.
- No active project/task tracked yet in this conversation -> Phase A (Start).
- An active task is already tracked in this conversation and the user names something different this time (a different task/project/keyword) -> treat it as a fresh Phase A run for that new thing. Don't silently drop the old one - mention it's still sitting mid-flight before moving on.
- An active task is already tracked, the dev server was already started, no PR opened yet, and the user re-invokes with no new task named -> ask first: "Are we still working on [task name]?"
- Yes -> pull back in whatever's already known from earlier in this conversation (task, project, branch) and go straight to Phase B - don't re-fetch or re-resolve what's already known.
- No -> drop it as the active task and start fresh from Phase A step 1, as if nothing were tracked.
- A PR is already open and QA subtasks already exist for the active task -> nothing left to automate; tell the user so rather than re-running Phase B's side effects a second time.
- Fresh Phase A run, dev-server command just handed over -> Phase A step 6 itself asks whether development is complete and changes are staged; a "Yes" there flows straight into Phase B within the same invocation, no re-invocation of
/lets-workneeded. A "Not yet" stops the skill there, same as before - the re-invocation branches above are for picking the thread back up on a later/lets-workcall.
Never repeat a step already completed and confirmed earlier in this same conversation (re-fetching the same Asana task, re-resolving an already-known project, re-starting an already-running dev server, etc.) - check what's already known first.
Whenever this skill needs a yes/no (or any small fixed-choice) answer from the user - committing, resuming the active task, Project vs Retainer, dev-server-up, etc. - ask it via AskUserQuestion with clickable options, never a plain text question. It's a faster, lower-friction confirmation for the user than typing a reply, and keeps this behavior consistent across every checkpoint in the skill rather than just the one it was first noticed on.
Shopify project mapping
Use this table to resolve a project name, store handle, or client name to the other two. Not every mapped project has a local folder in this workspace yet - check client-theme/ before assuming one exists.
| Project | Store Handle | Local Folder |
|---|---|---|
| GIR | guestinresidence | GIR |
| CR | crn-dev | CR |
| Capegrey | capegrey | Capegrey |
| Splits59 | splits-59 | Splits59 |
| ReDone | redun-com | ReDone |
| Still Here | still-here-new-york | Still Here |
| Rival Activewear | rivalactivewear | Rival (client-theme/shopify-rival-activewear) |
| Ruti | ruti-staging | Ruti (client-theme/shopify-ruti) |
| Shopko Optical | mmr7xd-8z | Shopko |
| Fielmann Sandbox | fielmann-sandbox | Fielmann |
| Oribe US | oribe-usa | Oribe |
| Oribe CA | oribe-canada | Oribe |
| Oribe US/CA Sandbox | oribesandbox-us | Oribe |
| Oribe UK | oribe-uk | Oribe |
| Oribe SE | oribe-sweden | Oribe |
| Oribe DE | oribe-germany | Oribe |
| Oribe EMEA Sandbox | oribehaircare-germany | Oribe |
| Kao Family of Brands USA | kaomallshop | Kao |
| Kao Beauty Brands Sandbox | kaosandbox | Kao |
| Kao Family of Brands Canada | kao-ccb-ca | Kao |
| MB South Africa | moltonbrown-south-africa | Molton Brown |
| MB Malaysia | moltonbrown-malaysia | Molton Brown |
| MB Netherlands | moltonbrown-netherlands | Molton Brown |
| MB Hungary | moltonbrown-hungary | Molton Brown |
| MB Italy | moltonbrown-italy | Molton Brown |
| MB Cyprus | moltonbrown-cyprus | Molton Brown |
| MB Poland | moltonbrown-poland | Molton Brown |
| MB Spain | moltonbrown-spain | Molton Brown |
| MB Sweden | moltonbrown-sweden | Molton Brown |
| MB Greece | moltonbrown-greece | Molton Brown |
| MB Sandbox | moltonbrown-sandbox | Molton Brown |
| Quickstart | quickstart-cf48f706 | Quickstart |
Only blackandblackcreative, shopify-rival-activewear, and shopify-ruti currently have a local folder under client-theme/. Never invent a project/store/folder that isn't in this table or in client-theme/ - ask if something doesn't match.
Phase A - Start
- Figure out what the user gave you when invoking, and fire the matching Asana fetch(es) in the same turn as confirming connectivity (
get_me) - don't gate the fetch onget_mesucceeding first; connectivity failure is rare and the calls don't depend on each other:- Nothing, or anything short of an exact task name/keyword/URL/GID -> call
get_meandget_my_tasks(completed_since="now")together in one turn - don't ask the user to supply a task name, keyword, or Asana link first. Sort Overdue > Today > Upcoming > No due date, exclude anything clearly completed/cancelled/blocked, and ask the user to pick one from that list. This is the default path and should fire with zero round-trips beyond the pick. - A task name, keyword, Asana URL, or GID was actually given -> call
get_meandsearch_tasks/get_tasktogether in one turn; if multiple plausible matches come back, show a short list and ask which one. - A project/store/client name with no specific task -> just confirm
get_meand skip straight to project resolution below; there may not be an associated Asana task at all (e.g. general theme work).
- Nothing, or anything short of an exact task name/keyword/URL/GID -> call
- If a task was found, load its full context (
get_taskwith description, comments, attachments, custom fields, parent, project/section, due date, assignee). Note any Figma links or acceptance criteria. Retain its gid as "the active task" for the rest of this conversation - every later phase refers back to this same task, not a re-resolved one.- If the project/store is already resolvable at this point without waiting on this fetch - the user explicitly named the project/store, or the task-search result from step 1 already surfaced the project - kick off locating the theme directory (step 4 below) in parallel with this
get_taskcall instead of waiting for it to finish first. Otherwise (project only resolvable from a field on the full task record), sequence as before: finish this fetch, then resolve the project, then locate the theme directory.
- If the project/store is already resolvable at this point without waiting on this fetch - the user explicitly named the project/store, or the task-search result from step 1 already surfaced the project - kick off locating the theme directory (step 4 below) in parallel with this
- Resolve the client project (store handle + local folder) from: what the task/user explicitly named, the project's own field on the Asana task, or the mapping table above. Don't guess - if resolution is ambiguous (task spans projects, name doesn't match the table, no local folder exists yet), ask.
3a. If a task was selected (not just a bare project), move it into active development: set its Status custom field to In Dev. Check live via
get_project(on the task's own project) for the field's gid and the "In Dev" enum option's gid before setting it - don't assume it matches another client's setup. If the task's project has no Status field, or no option that reads "In Dev", say so and skip rather than inventing one. This lookup is independent of locating the theme directory (step 4) - run both in the same turn rather than sequentially. - Locate the theme directory by checking where the session is already sitting -
client-theme/<Local Folder>is just this one workspace's own layout, not a portable convention, so don't scan for it and don't assume it exists:- Check the current working directory directly: does it (or an ancestor) have a
.gitfolder/remote (git rev-parse --show-toplevel), and doesgit statusshow staged changes there? If so, that's the theme directory - use it as-is, no further searching, nocd. - If the cwd isn't a git repo, don't stop to ask and don't go hunting elsewhere in the workspace for it (a broad
Glob/lsscan can be truncated/sorted by mtime and miss the real folder, as happened on the first Quickstart run) - just proceed on the assumption the user is already sitting in the right place. - If the user then tells you the actual path (as happened on that same run), use it directly - don't re-derive it from the mapping table.
- Check the current working directory directly: does it (or an ancestor) have a
- As soon as the store handle is known, hand the user the dev-server command - no running-process check first, no
cd, regardless of whether the theme directory found in step 4 differs from the current directory. Just give:
as its own fenced code block so it's a single click to copy-paste into whatever terminal/field the user runs it in. It genuinely doesn't matter whether a server is already running or not - never check, and never prepend ashopify theme dev --store=<store-handle>cd.- Right after handing over the command, use
AskUserQuestionwith a Yes/No-style option to ask "Is development complete on this task and are the changes staged?" ("Yes - move to QA" / "Not yet") instead of a plain text question - a one-click confirmation is faster for the user than typing a reply. Don't poll for the answer, and don't start a second copy via Claude's own background shell as a substitute for the user's own terminal.
- Right after handing over the command, use
- Branch on that answer:
- Not yet -> tell the user the environment is ready and stop here. Don't proceed into Phase B until they come back and confirm - either by re-invoking
/lets-workor answering this questionYeson a later run. - Yes -> don't stop the skill - continue straight into Phase B in this same invocation, picking up with its step 1 (re-confirm the active task and branch, then handle staged changes).
- Not yet -> tell the user the environment is ready and stop here. Don't proceed into Phase B until they come back and confirm - either by re-invoking
Phase B - Ship for QA
Re-confirm the active task and the current branch (
git branch --show-current,git status).If there are uncommitted changes:
- Ask whether to stage them if they aren't staged yet - never
git addbeyond what's explicitly asked. - Draft the commit message using the
git-commit-messageskill (orshared-tools:git-commit-messagewhere that's what the repo has enabled) againstgit diff --staged, using the active task as the task-context input. - Show the drafted message and ask for explicit yes/no before running
git commit. Re-running/lets-workis not itself authorization to commit - the standing "never commit without being asked" rule applies every time, no exceptions for this being a second invocation.
- Ask whether to stage them if they aren't staged yet - never
Push the branch (
git push -u origin <branch>first time,git pushafter). Never force-push; if one is genuinely needed, stop and ask.Open the PR:
gh pr create --base <integration branch> --head <branch>. Get the correct base branch from the repo's own conventions (its CLAUDE.md / git-workflow docs - e.g. shopify-ruti ships fromstaging, notmain) rather than assumingmain; ask if the repo has no documented convention. If a PR already exists for this branch, reuse its URL instead of erroring.Add the PR link as a comment on the active task via
add_comment- do this directly, don't ask the user to do it first. Post it as a plain comment in the exact formatPR: <link>, nothing else - no mention of the GitHub app card or attaching it themselves. Only post this once per task: before adding it, check the task's existing comments (get_task_storiesor the comments already fetched this session) for a priorPR:comment - if one's already there (e.g. this is a later push/re-run of Phase B for the same task, not a first PR), skip posting again rather than adding a duplicate.Ask: "Is this a Retainer or a Project?" via
AskUserQuestionfirst - this one has to stay its own round trip since it gates which follow-up question(s) even apply. Then branch:- Retainer -> in the same
AskUserQuestioncall, ask both of the following as separate questions (they don't depend on each other's answer, so there's no reason to ask them one after another): "How should the QA preview theme be created?" and "Who should be assigned for FQA and DQA?" (options for the latter as in step 5 below). Offer for the first:- GitHub-connected theme - stays in sync with this branch and maps to the PR for later merge. Creating this connection is an OAuth-consent Admin UI action with no CLI or Admin API equivalent (confirmed against
shopify theme push/list/open --help, and against the Admin GraphQL schema -themeCreate's only input issource: URL!, a ZIP/staged-upload URL, never a git/GitHub reference). The user must create it manually. - Manual theme (Shopify CLI) - a disposable unpublished preview theme Claude pushes directly via
shopify theme push --unpublished. Fully automatable, but it's a one-time snapshot: it will NOT stay in sync with the branch, and will go stale if more commits are pushed after it's created. Say this plainly when offering the option. Retain the QA-assignee answer from this same call for use in step 5 below - don't ask it again later.
- GitHub-connected theme - stays in sync with this branch and maps to the PR for later merge. Creating this connection is an OAuth-consent Admin UI action with no CLI or Admin API equivalent (confirmed against
- Project -> skip the theme-creation question, but still ask "Who should be assigned for FQA and DQA?" here (same options as step 5 below) in this same
AskUserQuestioncall, then runshopify theme list --store=<store-handle> --json, find the store's staging theme, and use itspreview_urldirectly as the QA preview URL - no push, no GitHub-connect walkthrough, no resource-aware URL-building. Go straight to "Both paths converge here" below with that link.
- Retainer -> in the same
If GitHub-connected theme
- Ask the user to log into the resolved Shopify store if authentication is needed.
- Tell the user to: Shopify Admin -> Online Store -> Themes -> "Add theme" -> "Connect from GitHub" -> select this repo and the branch just pushed. Propose a name -
BB - DEV - <dev initials> - <task name>, where<task name>drops the leading bracketed store/project prefix entirely (not just the bracket characters) - e.g.[Quickstart] - PDP TESTbecomes justPDP TEST,[Ruti] - Utility Pagesbecomes justUtility Pages. Let the user confirm or adjust it before they create it. Wait for the user to confirm it's done - don't poll for it.- If the store's theme limit is reached (Shopify Admin blocks adding a new theme), tell the user to go into the store's Admin -> Online Store -> Themes themselves and delete a theme to free up a slot, then re-run
/lets-workto pick this back up. Never delete a theme via the CLI/Admin API on the user's behalf - which theme is safe to remove is their call, not something to infer or automate. Don't offer anAskUserQuestioncheckbox here - just stop the skill at this point and wait for the next invocation.
- If the store's theme limit is reached (Shopify Admin blocks adding a new theme), tell the user to go into the store's Admin -> Online Store -> Themes themselves and delete a theme to free up a slot, then re-run
- Once the user confirms the theme is created and they've opened its preview, ask them directly (plain text - this is arbitrary pasted input, not a small fixed choice, so
AskUserQuestion's clickable-option pattern doesn't fit here) to paste the theme's preview link. Use that pasted link as-is as the QA preview URL - skip the resource-aware URL-building logic in step 4 below entirely for this path; there's no theme ID to build from since Claude never looked one up, and the user-supplied link is already the real thing.
If Manual theme (Shopify CLI)
- Determine the theme name using the same convention:
BB - DEV - <dev initials> - <task name>, where<task name>drops the leading bracketed store/project prefix entirely (not just the bracket characters) - e.g.[Quickstart] - PDP TESTbecomes justPDP TEST. - Run
shopify theme push --unpublished --theme="<name>" --path="<resolved theme directory>" --store=<store> --jsonfrom Claude's own shell. Always pass an explicit--pathpointing at the resolved theme directory from Phase A step 4 - never rely on an earliercdstill being in effect. Confirmed the hard way: Bash/PowerShell tool calls in this environment do not persist a working-directory change between invocations (each call resets to the workspace root), so a first attempt without--pathsilently ran from the workspace root, found no real theme structure, and partially uploaded/attempted to delete core files (layout/theme.liquid,config/settings_schema.json,templates/gift_card.liquid) on the newly created theme before erroring. Re-running the same command with the correct--path(targeting the same returned theme ID) fixed it. - Parse
theme.idandtheme.preview_urlfrom the returned JSON. - Remind the user this preview theme is a one-time snapshot, not connected to the branch - if they push more commits later and want the QA preview to reflect them, this command needs to be re-run.
Both paths converge here
- Build the QA preview URL:
- Project path: already have the staging theme's
preview_urlfrom step 6 above - use it as-is, skip everything below. - Retainer / GitHub-connected path: already have the real preview link the user pasted in step 3 above - use it as-is, skip everything below.
- Retainer / Manual-CLI path: build a resource-aware URL from the theme ID just obtained:
- Determine the touched template(s) from the diff (
templates/page.<suffix>.json-> page,templates/product.<suffix>.json-> product,templates/collection.<suffix>.json-> collection). A global/site-wide change with no specific template goes straight to the fallback below. - Existing template, just edited: find a real resource already assigned to it via Admin GraphQL (
pages/products/collectionsqueried bytemplate_suffix). If more than one plausible candidate comes back, ask rather than picking one. - Brand-new template, no resource assigned yet: query for any real resource of that type and force-render the new template with
&view=<suffix>. - Fallback: no applicable template, or the lookup returns nothing usable - use the theme's own
preview_urlfrom the push JSON (bare?preview_theme_id=<id>) and say plainly it's the generic homepage, not page-specific. - Always use the theme ID just obtained this run - never reuse an ID from an earlier session or a different task.
- Determine the touched template(s) from the diff (
- Project path: already have the staging theme's
- Who to assign for FQA and DQA - fixed options (role is determined by which list a name is picked from, not stated separately):
- FQA: Anjum, Majid, Khurram, Ashhal, Fazeela, Sidra
- DQA: Grace, Olena
This was already asked as part of step 6's combined
AskUserQuestioncall above - use that answer here rather than asking again. Once picked, still look up each chosen person's real gid live (search_objects(resource_type="user")orget_users) rather than hardcoding one - never invent a gid even for a name on this fixed list. If the user names someone outside these two lists (typed as free text, e.g. via the question's "Other" option, or stated outright), just look up that person's gid and assign them - no separate yes/no confirmation needed, since naming a specific person is already an explicit, unambiguous instruction.
- Create the QA subtask(s) - only for the role(s) actually covered by names given:
- Parent: the active task's gid.
- Name:
FQA - <active task name>/DQA - <active task name>. - Confirm live (don't assume from another client's setup) that the B&B Team Resource Planning project and its Preview Link and Status custom fields exist and get their real gids/enum options via
get_projectbefore using them - a gid confirmed for one client isn't guaranteed to be right for another. - Create the subtask assigned to the project first (project = B&B Team Resource Planning, due date = today, Preview Link = the URL from step 4, assignee = the looked-up gid) - do not set Status in this same call. Confirmed the hard way: adding a task to this project resets its Status back to "New Request" regardless of what Status was passed in the same create call, so setting it up front gets silently clobbered.
- Then, in a separate follow-up update, set Status = QA on the subtask that now exists in the project.
- Add a comment "Please Proceed with QA [assigne-name]" via
add_comment.
- Update the active task itself: Status -> QA and Preview Link -> the same URL, but only if the active task's own project actually has those fields - check via
get_projectrather than assuming every client project mirrors B&B Team Resource Planning's schema; if it doesn't, say so instead of silently skipping or inventing a field. - Report back: branch, PR link, theme name and preview URL, and a link to each subtask created. Don't mark anything complete yourself - that's QA's call.
Constraints carried over from prior work in this workspace
- Never invent an Asana project/custom-field gid. Fetch it live via
get_project/search_objectsbefore using it, even when a similar one is already documented for another client (learned buildingadd-to-qa-retainerfor shopify-ruti - its gids are Ruti-specific, not assumed portable). - Never invent a project/store/folder mapping not in the table above or in
client-theme/- ask if something doesn't match. - Never commit without an explicit yes/no, even on a Phase B re-run.
- Connecting a Shopify theme to a GitHub branch is manual, Admin-UI-only - confirmed via
shopify theme --help/theme push/list/open --helpAND via the Admin GraphQL schema (themeCreate's only source input issource: URL!, a ZIP/staged-upload URL, never a git/GitHub reference - there is no mutation or argument anywhere for a GitHub link). Always pause for user confirmation; never poll for it. Separately, pushing a disposable unpublished preview theme IS scriptable viashopify theme push --unpublished --theme="<name>" --path="<dir>" --json- this is the "Manual theme (Shopify CLI)" option, a one-time snapshot only, not a substitute for the real GitHub connection. - Attaching a PR to Asana's GitHub app card is manual, UI-only - no MCP tool exists for it (checked the full Asana tool list before assuming otherwise). The PR-link comment itself stays a plain
PR: <link>with no mention of the app card. - QA assignee options are a fixed list (FQA: Anjum, Majid, Khurram, Ashhal, Fazeela, Sidra; DQA: Grace, Olena) - role is implied by which list a name comes from. Still never hardcode a person's gid - look it up live even for a name on this list.
- Never force-push, and always check the repo's actual documented base branch before opening a PR - some client repos ship from
staging, notmain. - QA subtask creation must add the task to B&B Team Resource Planning before setting Status to QA, never in the same call. Adding a task to this project resets its Status back to "New Request" - if Status = QA is set in the same create call as the project assignment, the project add silently overwrites it back to New Request. Always create the subtask in the project first, then a separate follow-up update sets Status = QA.
- Claude has no tool that can drive the visible VS Code integrated terminal panel - confirmed by searching the full available tool set.
Bash/PowerShellcalls (includingrun_in_background) run in Claude's own separate managed shell, not that panel. Startingshopify theme devso it's visible there is always a manual handoff: give the user the command, let them run it, wait for their confirmation - never substitute Claude's own background shell as a silent stand-in for "it's running."
Learnings log
Append dated entries here after each real use - what worked, what didn't, what assumption turned out wrong. Follow add-to-qa-retainer's convention: this is a living document, not a finished spec.
- 2026-08-22 (written, not yet run for real): Built after walking through the full Project-vs-Retainer distinction with the user and checking it against the existing
add-to-qa-retainerskill (shopify-ruti-scoped) and its generalizedshared-toolscounterpart. Deliberately kept net-new rather than wrapping those skills, per explicit choice. Confirmed live (by inspecting the actual Asana MCP tool list) that there is no attachment-creation tool, so PR-to-task linking via the GitHub app card stays a manual handoff. Deliberately deferred auto-detecting an existing GitHub-connected theme via the API for the Project path - going manual for now per explicit instruction, revisit later if a reliable signal turns up. - 2026-08-22 (same day, consolidation): Merged the standalone
start-day,task, andshopify-project-resolutionskills into this one at the user's explicit request, so this is now the single entry point for session start, Asana task-context loading, and project/store/folder resolution - those three skill files were deleted. First real run should confirm: the phase-detection logic in "Determine the phase" actually resumes correctly across a real gap in the conversation, that the merged "what did the user give me" branching in Phase A step 2 correctly distinguishes a bare project name from a task reference, and that checking a client project's own custom fields (step 7) before writing Status/Preview Link doesn't surprise the user by silently skipping a field they expected to be set. - 2026-08-23 (first real run, Ruti - Blogs Test): Ran the full flow end to end against
[Ruti - Blogs Test]on shopify-ruti - confirmed Phase A/B resumed correctly across multiple re-invocations, including one where the user had committed and another where they asked to undo/unstage a commit outside the skill's own flow (handled with a plaingit reset HEAD~1, not--hard). Confirmed live that no MCP tool can create the Asana GitHub app-card attachment shown in the task's Apps panel - fell back to a plain comment with the PR link, as designed.ghwas not installed/authenticated in this environment; installed viawingetand walked the user throughgh auth loginmanually (also confirmed that PATH updates from a fresh install don't propagate to already-open shell tool calls, needing the full binary path as a workaround). Post-run, the user asked for three changes, applied here: (1) the active task now moves to Status "In Dev" as soon as it's selected in Phase A, not left alone until QA; (2) QA subtask naming flipped from<task> - FQA/DQAtoFQA/DQA - <task>; (3) the QA-assignee lookup changed from a fully open live-search with user-stated roles to a fixed two-list menu (FQA: Anjum, Majid, Khurram, Ashhal, Fazeela, Sidra; DQA: Grace, Olena) where the role is implied by the list - gids are still looked up live, never hardcoded, even for names on this fixed list. - 2026-08-23 (same day, resume-confirmation): Also investigated (and abandoned) driving the VS Code integrated terminal programmatically - tried the
vscode-terminal-mcpnpm package/extension (a real, purpose-built MCP server for this), installed it and registered it, but its IPC socket to the VS Code extension host never connected even after a window reload; user decided to uninstall it and keep the manual copy-paste handoff rather than keep debugging it. Separately, the user flagged a real gap: "Determine the phase" assumed a re-invocation always meant resuming the same active task, which breaks if the user context-switches to unrelated dev chat or a different task mid-session. Fixed by adding an explicit resume-confirmation question ("Are we still working on [task]?") whenever/lets-workis re-invoked with no new task named - yes pulls back in existing context and goes to Phase B, no drops the tracked task and restarts from Phase A step 1. Naming a different task/project outright still short-circuits straight to a fresh Phase A run for that one, with a mention that the old one is left mid-flight. Not yet verified in a real long/messy session with actual unrelated chatter in between - worth confirming the question doesn't feel naggy when the answer is obviously "yes." - 2026-08-23 (same day, dev-server confirmation UX): On the
[Ruti] - Utility Pages ( Skill Test )run, after suggesting theshopify theme devcommand Claude asked a plain text question and then just sat there. User pointed out this is backwards: once the command is handed off, they're likely to go start coding rather than reply, and might come back much later with changes already staged and ready to ship. A prose question they have to type a reply to is friction for zero benefit, since the real confirmation that matters is whatever they say the next time they invoke/lets-workanyway. Fixed step 6 to useAskUserQuestionwith a one-click Yes/No option right after the command instead of open-ended text, and made explicit that not answering at all is a fine outcome - the resume-confirmation logic already picks the thread back up correctly on the next invocation. - 2026-08-23 (same day, full Phase B run + 3 fixes): Completed the first real full Phase A->B run for
[Ruti] - Utility Pages ( Skill Test )end to end: committed a trivial test change, pusheddev/abdullah, opened shopify-ruti PR #44 againststaging(confirmed via the repo's own CLAUDE.md, not assumed), created FQA/DQA subtasks, and updated the parent task's Status/Preview Link. Landed a name outside the fixed QA-assignee lists (the user asked to assign both FQA and DQA to themselves as a test) - handled by asking an explicit yes/no first, which the user then flagged as unnecessary friction. Three fixes applied as a result: (1) generalized the dev-server-confirmation learning above into a standing rule - any yes/no or small fixed-choice question anywhere in this skill (committing, resume-confirmation, Project vs Retainer, QA assignee picks, dev-server-up) must useAskUserQuestionwith clickable options, never plain text; (2) dropped the explicit confirmation step for an off-list QA assignee name - naming a specific person is already unambiguous, so just look up their gid and assign, no extra yes/no gate; (3) stopped asking the user to attach the PR to the task themselves before continuing - Claude now posts the PR link as a plainadd_commentdirectly (it still can't create the actual GitHub app-card attachment, no MCP tool exists for that, but the link itself doesn't need to wait on the user to hand-add it). - 2026-08-24 (dev-server handoff simplified): User asked to cut friction/time in Phase A: (1) step 2's "nothing given" path now fetches
get_my_tasksimmediately rather than implying the user should supply a task name/link first; (2) step 6 dropped the running-process check entirely - doesn't matter if a server is already running, never check; (3) step 6 also dropped the conditionalcd <path> &&prefix - always hand over the bareshopify theme dev --store=<store-handle>command in its own fenced code block so it's a one-click copy-paste, regardless of where the theme directory actually is. Step 5 (locating the theme directory) is kept as-is since Phase B's--pathargument fortheme push --unpublishedstill needs it - only the step 6 dev-server suggestion changed. - 2026-08-24 (same day, QA subtask Status ordering): User flagged that creating the QA subtask with project = B&B Team Resource Planning and Status = QA in the same call was resetting Status back to "New Request" - adding a task to this project apparently resets Status regardless of what was passed alongside it. Fixed step 6 to create the subtask assigned to the project first (no Status set in that call), then a separate follow-up update sets Status = QA once the task already exists in the project. Added as a standing constraint since this would silently produce wrong-status QA tasks on every run otherwise.
- 2026-08-24 (same day, Phase A->B same-invocation flow): Replaced the "Server's up / Not yet" question in step 6 with "Is development complete on this task and are the changes staged? (Yes - move to QA / Not yet)". A "Not yet" still stops the skill exactly as before. A "Yes" no longer requires the user to re-invoke
/lets-workseparately - the skill now continues straight into Phase B step 1 within the same invocation. "Determine the phase" updated with a note explaining this Phase A-internal branch is distinct from the existing re-invocation/resume-confirmation logic, which still applies when the user comes back in a later/lets-workcall instead. - 2026-08-24 (same day, Retainer/Project distinction restored): User pointed out the original Project-vs-Retainer question (present in an earlier draft, then dropped during the 2026-08-23 theme-creation rework) should never have been removed - it needed to gate the existing GitHub-connected/Manual-CLI sub-question, not be replaced by it. Restored as the first question in Phase B step 6: Retainer -> unchanged, falls straight into the existing "GitHub-connected theme" vs "Manual theme (Shopify CLI)" sub-question exactly as it already worked. Project -> a new, simpler path: run
shopify theme list --store=<store> --json, find the store's staging theme, and use itspreview_urldirectly as the QA preview link - no push, no GitHub-connect walkthrough, no resource-aware URL-building. Kept intentionally minimal per explicit instruction; not yet verified end-to-end on a real Project-type engagement. - 2026-08-24 (same day, latency pass - Phase A batching + Phase B question collapse): User asked for a time-reduction brainstorm on this skill, then picked four to implement now. Phase A: (1)
get_meno longer gates the Asana fetch - both fire in the same turn regardless of which invocation path (bare/named-task/named-project) is taken; (2) the fullget_taskcontext fetch (old step 3) can now run in parallel with locating the theme directory (old step 5) whenever the project is already resolvable without it (explicit project name, or the project already surfaced from the initial search) - otherwise still sequenced since project resolution can depend on a field from the full task record; (3) setting Status to "In Dev" (old step 4a) and locating the theme directory are unconditionally independent, so they're now batched together regardless. Renumbered Phase A to 1-6 accordingly (old 4a is now 3a; old steps 6/7 are now 5/6) and fixed the cross-references in "Determine the phase" and the Manual-CLI--pathnote. Phase B: collapsed the "How should the QA preview theme be created?" question (Retainer branch only) and the "Who should be assigned for FQA/DQA?" question (previously asked later, after building the preview URL) into one multi-questionAskUserQuestioncall - they don't depend on each other's answer, so asking both up front saves a full round trip on every Retainer run. The Retainer-vs-Project question itself stays its own separate ask since it gates whether the theme-creation question even applies. Not yet verified end-to-end on a real run since this change. - 2026-08-24 (same day, theme-directory location fixed): On the
[Quickstart] - Testrun, step 4's old logic (check cwd looks like a theme root, else checkclient-theme/<Local Folder>, else assume already in the right place) failed silently:Glob("client-theme/*")returned "No files found" because Glob only matches files, not bare directory names, andclient-theme/has no loose files directly inside it - so the realclient-theme/quickstartfolder was never detected even though it existed. A fallback broadGlob("*")scan then got flooded by thousands of recently-touched.git/objects/...files in a different theme's repo (truncated at "100 of 4732 shown," sorted by mtime), so the folder still never surfaced. Claude reported no local folder existed and had to ask the user, who then gave the path directly. User then pointed outclient-theme/<Local Folder>is this workspace's own layout, not something every user of this skill has - the skill should instead just check whatever directory the session is already in for a git repo/remote and staged changes, not scan for or assume a specific folder structure. Rewrote step 4 accordingly: check cwd for.gitdirectly, use it as-is if found: only fall back to "assume already in the right place" if not, with no workspace-wide scanning in between. - 2026-08-23 (same day, theme-creation rework): During the first real Quickstart run (
[Quickstart] - PDP TEST), tried to shortcut the old Retainer path by runningshopify theme push --unpublisheddirectly - it worked (returned a real theme ID/preview URL) but the first attempt was run without an explicit--path, silently executed from the workspace root instead of the theme directory (confirmed Bash/PowerShell tool calls reset cwd between invocations, an earliercddoes not carry over), and partially corrupted the created theme (failed deletes onlayout/theme.liquid,config/settings_schema.json,templates/gift_card.liquid). Fixed by re-running with the correct--pathagainst the same theme ID. The user then pointed outtheme pushonly creates a disconnected snapshot, not a real GitHub-linked theme, and asked whether GraphQL automation could do the real GitHub connection - checked viashopify-adminskill'ssearch_docs.mjsagainst the Admin GraphQL schema and confirmedthemeCreateonly acceptssource: URL!(a ZIP/staged-upload URL), no GitHub/git argument exists anywhere in the schema, so the OAuth-consent Admin UI step is genuinely the only path for a real GitHub connection. Reworked the old Project-vs-Retainer theme-creation split into a clearer two-option choice instead: "GitHub-connected theme" (manual, user creates it and pastes back the real preview link - no resource-aware URL-building needed since the link is already real) vs "Manual theme (Shopify CLI)" (Claude runs the push automatically, then still applies the resource-aware preview-URL logic against the returned theme ID, with an explicit warning that it's a snapshot that goes stale on further pushes). Not yet verified end-to-end for the GitHub-connected path's new paste-the-link step in a real run. Also fixed the naming convention right after:<task name>inBB - DEV - <initials> - <task name>must drop the leading bracketed store/project prefix entirely, not just strip the bracket characters -[Quickstart] - PDP TESTbecomesPDP TEST, notQuickstart - PDP TEST.