[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C4F6E7T4NN593M9WKKDPDQ":3,"skill-same:01M6C4F6E7T4NN593M9WKKDPDQ":65},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":37,"linkOnly":38,"markdownContent":39,"markdownBody":40,"frontMatter":41,"refName":42,"commitSha":43,"skillDirectory":44,"forksCount":45,"repositoryHtmlUrl":46,"repositoryHomepageUrl":6,"ownerHtmlUrl":47,"ownerBlogUrl":48,"ownerDescription":49,"updatedAt":50,"install":51,"resources":64},"01M6C4F6E7T4NN593M9WKKDPDQ","xcode-dev-loop",null,"WHEN building, testing, or visually verifying an Xcode project from the command line — xcodebuild runs, Swift Testing result reading, simulator install\u002Flaunch, and screenshots; NOT for authoring Swift source or tests; returns the canonical build\u002Ftest\u002Finspect loop.","mintuz\u002Fskills","mintuz","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F447031?v=4","01M6BVWJYSVR4XQC9AQCEMWQRG","Adam Bulmer","01M6C4DCXKNYZB281YB3PZDJJG",35,"MIT","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fapp\u002Fskills\u002Fxcode-dev-loop\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36],"dev","loop","xcode dev loop","testing","screenshots","swift","test","launch","command line","returns","command","install","swift testing","2026-11-10 10:12:30",false,"---\nname: xcode-dev-loop\ndescription: >\n  WHEN building, testing, or visually verifying an Xcode project from the command line —\n  xcodebuild runs, Swift Testing result reading, simulator install\u002Flaunch, and screenshots;\n  NOT for authoring Swift source or tests; returns the canonical build\u002Ftest\u002Finspect loop.\n---\n\n# Xcode Dev Loop\n\nDiscover, build in the background, read results, launch on a simulator, capture screens.\nThis loop runs and inspects; it does not author Swift source or tests. Route\nSwift Testing authoring to `swift-testing`, XCTest UI automation to `xcuitest`,\nand existing non-UI XCTest unit\u002Fintegration or `measure` tests to the project's\nestablished XCTest conventions with `tdd`. A dedicated reusable non-UI XCTest\nauthoring guide remains a gap. Preserve the suite's framework rather than forcing\na migration. Return here to execute and interpret the real result.\n\n## 1. Discover Before You Guess\n\n- Find the container first: list the checkout for a `.xcworkspace` or `.xcodeproj`.\n- List the schemes of a workspace with `xcodebuild -list -workspace \u003Cname>.xcworkspace`.\n- List the targets, build configurations, and schemes of a project with\n  `xcodebuild -list -project \u003Cname>.xcodeproj` (use this form when you need a target name).\n- Build and test with the container flag you listed with, and always name the scheme:\n  `xcodebuild test -workspace \u003Cname>.xcworkspace -scheme \u003CScheme>`. The `test` action fails\n  without a scheme.\n- List simulator UDIDs with `xcrun simctl list devices available -j`; resolve the UDID\n  once, then reuse it.\n- Read installed simulator command options with `xcrun simctl help \u003Csubcommand>`.\n- Never address a simulator by name: duplicate names (\"iPhone 17 Pro Max\") cause\n  \"No booted simulator named …\" failures. Only the listing output separates same-named\n  devices, so give the listing command beside the UDID whenever you replace a name.\n- When a scheme needs a runtime the default Xcode lacks (e.g. a watchOS beta), export\n  `DEVELOPER_DIR=\u002FApplications\u002FXcode-\u003Cversion>.app\u002FContents\u002FDeveloper` for the whole\n  session, so every `xcodebuild` and `xcrun` call selects the same Xcode.\n\n## 2. Build and Test in the Background\n\n- Never let `xcodebuild` hold the foreground: a clean build or test run routinely exceeds\n  the 600 s command timeout, and a command killed at the timeout leaves no verdict.\n- Start the run in the background, redirect its output to a log file in the scratchpad, and\n  keep a handle whose exit status you can read later. Prefer the harness's background\n  facility (`Bash` with `run_in_background: true`) and the task handle it returns.\n- With only a plain shell, make the run record its own exit status; a later shell cannot\n  `wait` for another shell's child. Give every attempt its own log and status path; a stale\n  status file ends the wait at once and reports the wrong result:\n\n  ```bash\n  ( xcodebuild ... > \"$LOG\" 2>&1; echo $? > \"$LOG.status\" ) &   # start it\n  until [ -f \"$LOG.status\" ]; do sleep 5; done                  # wait, in a later call\n  ```\n\n- Use `CODE_SIGNING_ALLOWED=NO` for simulator builds.\n- Pin the destination as `platform=iOS Simulator,id=\u003Cudid>`.\n- When one target or test matters, scope the run with `-only-testing:\u003CTestTarget>[\u002F\u003CSuite>\u002F\u003Ctest>]`; preserve the log.\n- Never wait with a chained foreground `sleep`; the harness blocks it.\n- Wait on the kept handle with the harness's blocking wait (`Monitor`, or the task-output\n  wait), or for the `.status` file with the loop above. Read the exit status first, then the\n  log's terminal marker. Do not wait by grep alone: it keeps polling when `xcodebuild` exits\n  before writing a marker.\n\n## 3. Read Results Correctly (Swift Testing Is Not XCTest)\n\n- Swift Testing does NOT emit XCTest's `Test Case ... passed` lines.\n- `Executed 0 tests, with 0 failures` is the empty XCTest summary; it proves nothing.\n- Always pass `-resultBundlePath` with a new path per attempt; `xcodebuild` fails when the\n  path already exists.\n- Read the verdict from that fresh bundle with\n  `xcrun xcresulttool get test-results summary --path \u003Cbundle>`. A pass needs the expected\n  non-zero test count there, no failure or crash there, `** TEST SUCCEEDED **`, and a zero\n  exit status (`principle-prove-it-works`).\n- The log's `✔ Test run with N tests in M suites passed`, with N greater than zero,\n  corroborates that count; a pattern that also matches zero proves nothing. A filtered or\n  `-quiet` log can omit the line, so never treat its absence alone as the verdict.\n- Take the expected test count from the target's tests or test plan, never from the run you\n  are judging.\n- Match the expected case IDs against `xcresulttool get test-results tests --path\n  \u003Cbundle>`; totals alone do not prove each selected case ran. Inspect `test-details`\n  and `metrics` when a case fails or measures performance, preserving the actual\n  measurements and failure reason. Pin the toolchain, configuration, device and\n  workload for comparisons. State the non-UI XCTest authoring-guide gap explicitly\n  when using project conventions as the fallback.\n- A run that executed zero tests is not a pass, whatever its exit status\n  (`principle-gaps-are-not-passes`). Suspect the selection before the code: confirm\n  `-only-testing` still names the current suite and test after any rename, and that the\n  target belongs to the test plan.\n- Grep once with the full set of terminal markers: `\\*\\* BUILD SUCCEEDED \\*\\*`,\n  `\\*\\* BUILD FAILED \\*\\*`, `\\*\\* TEST SUCCEEDED \\*\\*`, `\\*\\* TEST FAILED \\*\\*`,\n  `Testing failed:`, and `^error:`. Judge the marker together with the exit status.\n- To confirm which suites ran, match both spellings: XCTest prints `Test Suite '.*' started`,\n  and Swift Testing prints a `Suite .* started` record. Match them case-sensitively as printed.\n- On failure, read the bundle summary for the structured crash reason, such as\n  `Test crashed with signal abrt`; it may appear only there. The log may repeat it as an\n  underlying error, but the bundle is the reliable source. Do not re-run blind.\n- Treat `The test runner hung before establishing connection` and diagnostic-collection\n  timeouts as a suspected environmental fault, not a proven diagnosis. Shut down the\n  pinned simulator (`xcrun simctl shutdown \u003Cudid>`) only if this run created and still\n  owns it, then retry once within the run's time bounds with a new result-bundle path.\n  Pinning a pre-existing device does not confer ownership: preserve it and report\n  blocked when recovery needs its shutdown. Never use `xcrun simctl shutdown all`.\n- Pass `TEST_RUNNER_\u003CNAME>=\u003Cvalue>` on the `xcodebuild test` command; Xcode strips the\n  prefix and gives the variable to the test runner process. A UI test target's app under test\n  does not receive it; set `XCUIApplication.launchEnvironment` for that case.\n- `test-without-building` runs the product and `.xctestrun` file an earlier build produced,\n  so it can report a success that excludes your latest source change. Rebuild with\n  `xcodebuild test` before you trust a pass, and whenever that product is the suspect.\n- A test-bundle load error names the missing library, not the cause. When a load failure\n  survives the rebuild, inspect the framework's embedding and runpath settings as candidates.\n\n## 4. Install, Launch, and Drive\n\n- Install the build you just made before launching. Never launch whatever is already on the\n  device: it can come from another branch (`principle-prove-it-works`).\n  Record revision plus relevant uncommitted-source identity and bind it to the\n  actual built, installed and launched product; a matching HEAD alone is insufficient.\n- `simctl install` needs a booted device. Boot the pinned device with\n  `xcrun simctl bootstatus \u003Cudid> -b`, which boots it if shut down and waits for the boot to\n  finish. Do not call `xcrun simctl boot` first: it fails on a running device.\n- Know the product path before you install: pass `-derivedDataPath \u003Cdir>` to the build, or\n  read `BUILT_PRODUCTS_DIR` and `FULL_PRODUCT_NAME` from `xcodebuild -showBuildSettings`.\n  On that call repeat every flag the build used, including `-derivedDataPath`, the scheme,\n  and the destination; different flags report another build's product path.\n- Read the bundle id from that build, not from memory:\n  `\u002Fusr\u002Flibexec\u002FPlistBuddy -c 'Print :CFBundleIdentifier' \u003Capp-path>\u002FInfo.plist`.\n- Prefer the simulator MCP: call its install action with the new `.app` path, then its\n  launch action with the bundle id. Pass the pinned UDID to both; their device argument is\n  optional and defaults elsewhere.\n- A running MCP server does not inherit a `DEVELOPER_DIR` exported in a shell. When the run\n  needs a beta Xcode, use the `xcrun` commands with that `DEVELOPER_DIR` instead.\n- When the MCP launch fails with `Failed to spawn xcrun (via disclaimer)`, fall back to\n  `xcrun simctl install \u003Cudid> \u003Capp-path>`, then `xcrun simctl launch \u003Cudid> \u003Cbundle-id>`.\n- A deep link (`xcrun simctl openurl \u003Cudid> \u003Cscheme>:\u002F\u002F\u003Cpath>`) or existing\n  DEBUG\u002Fseed mechanism may establish a screen or fixture precondition. It must\n  not replace the public interaction that the claimed journey is meant to prove.\n  Use accessible UI automation for that boundary, not blind coordinate taps.\n  For capture-only screen setup, prefer an existing deep link or DEBUG scenario\n  over UI navigation; its purpose here is to reach the state, not prove creation\n  or another public-action boundary.\n- Read the accessibility hierarchy before you tap; coordinates are the last resort.\n\n## 5. Screenshots\n\n- Pick ONE capture mechanism per run: `xcrun simctl io \u003Cudid> screenshot \u003Cpath>.png` when\n  the file must persist for comparison, the MCP screenshot action to look now. Never use\n  both for the same frame.\n- Number the files (`round2\u002F01-hub-gate.png`) so rounds diff cleanly against a baseline.\n- A freshly erased simulator posts a system banner soon after boot. Wait for the boot with\n  `xcrun simctl bootstatus \u003Cudid> -b`, then read the accessibility hierarchy and confirm no\n  system alert covers the view. Capture only after that check passes; a fixed short delay is\n  not evidence (`principle-observe-dont-infer`).\n\n## Isolation, cleanup and evidence\n\nUse independently owned simulator\u002Fapp\u002Ffixture state when a run mutates data.\nDo not erase or reset a user's shared simulator or store. Record ownership before\nlaunch; only a created device may be shut down\u002Fdeleted as this run's teardown.\nOn success, error or cancellation, release only resources still owned by the run,\nnever kill by process name or trust a reused PID. Preserve logs, result bundles\nand captures outside cleanup targets and confirm they survive teardown. A blocked\ndevice\u002Fentitlement\u002Fsystem boundary is not proved through another simulator path.\n\nUse synthetic data and disposable accounts. Inspect and redact shareable log,\nresult-bundle and capture derivatives; keep necessary originals access-controlled\nunder the project's retention policy. Never publish credentials, customer data\nor whole unreviewed bundles.\n\nIn a capture plan, name the pinned UDID and derive the bundle identifier from\nthe intended build; pass both to the launch command. Report missing state proof,\nfailed cleanup and unavailable evidence explicitly rather than implying success.\n\n## 6. Cadence\n\n- Compile after the domain layer and again after the first view, not once at the end\n  (`principle-sequence-verifiable-units`).\n- Run the test suite once, early, before you declare a change done.\n\n## Related Skills\n\n- **`app:debug`** — structured feedback loop for simulator failures, user-reported or observed\n- **`core:visual-feedback`** — interactive appearance diagnosis and before\u002Fafter\n  review; this loop supplies the execution, captures and identity\u002Fstate evidence.\n- **`app:swift-testing`** — Swift Testing authoring; **`app:xcuitest`** —\n  XCTest UI authoring. Keep non-UI XCTest tests in their existing framework.\n- **`app:swiftui-architecture`** — SwiftUI patterns for the code under test\n","# Xcode Dev Loop\n\nDiscover, build in the background, read results, launch on a simulator, capture screens.\nThis loop runs and inspects; it does not author Swift source or tests. Route\nSwift Testing authoring to `swift-testing`, XCTest UI automation to `xcuitest`,\nand existing non-UI XCTest unit\u002Fintegration or `measure` tests to the project's\nestablished XCTest conventions with `tdd`. A dedicated reusable non-UI XCTest\nauthoring guide remains a gap. Preserve the suite's framework rather than forcing\na migration. Return here to execute and interpret the real result.\n\n## 1. Discover Before You Guess\n\n- Find the container first: list the checkout for a `.xcworkspace` or `.xcodeproj`.\n- List the schemes of a workspace with `xcodebuild -list -workspace \u003Cname>.xcworkspace`.\n- List the targets, build configurations, and schemes of a project with\n  `xcodebuild -list -project \u003Cname>.xcodeproj` (use this form when you need a target name).\n- Build and test with the container flag you listed with, and always name the scheme:\n  `xcodebuild test -workspace \u003Cname>.xcworkspace -scheme \u003CScheme>`. The `test` action fails\n  without a scheme.\n- List simulator UDIDs with `xcrun simctl list devices available -j`; resolve the UDID\n  once, then reuse it.\n- Read installed simulator command options with `xcrun simctl help \u003Csubcommand>`.\n- Never address a simulator by name: duplicate names (\"iPhone 17 Pro Max\") cause\n  \"No booted simulator named …\" failures. Only the listing output separates same-named\n  devices, so give the listing command beside the UDID whenever you replace a name.\n- When a scheme needs a runtime the default Xcode lacks (e.g. a watchOS beta), export\n  `DEVELOPER_DIR=\u002FApplications\u002FXcode-\u003Cversion>.app\u002FContents\u002FDeveloper` for the whole\n  session, so every `xcodebuild` and `xcrun` call selects the same Xcode.\n\n## 2. Build and Test in the Background\n\n- Never let `xcodebuild` hold the foreground: a clean build or test run routinely exceeds\n  the 600 s command timeout, and a command killed at the timeout leaves no verdict.\n- Start the run in the background, redirect its output to a log file in the scratchpad, and\n  keep a handle whose exit status you can read later. Prefer the harness's background\n  facility (`Bash` with `run_in_background: true`) and the task handle it returns.\n- With only a plain shell, make the run record its own exit status; a later shell cannot\n  `wait` for another shell's child. Give every attempt its own log and status path; a stale\n  status file ends the wait at once and reports the wrong result:\n\n  ```bash\n  ( xcodebuild ... > \"$LOG\" 2>&1; echo $? > \"$LOG.status\" ) &   # start it\n  until [ -f \"$LOG.status\" ]; do sleep 5; done                  # wait, in a later call\n  ```\n\n- Use `CODE_SIGNING_ALLOWED=NO` for simulator builds.\n- Pin the destination as `platform=iOS Simulator,id=\u003Cudid>`.\n- When one target or test matters, scope the run with `-only-testing:\u003CTestTarget>[\u002F\u003CSuite>\u002F\u003Ctest>]`; preserve the log.\n- Never wait with a chained foreground `sleep`; the harness blocks it.\n- Wait on the kept handle with the harness's blocking wait (`Monitor`, or the task-output\n  wait), or for the `.status` file with the loop above. Read the exit status first, then the\n  log's terminal marker. Do not wait by grep alone: it keeps polling when `xcodebuild` exits\n  before writing a marker.\n\n## 3. Read Results Correctly (Swift Testing Is Not XCTest)\n\n- Swift Testing does NOT emit XCTest's `Test Case ... passed` lines.\n- `Executed 0 tests, with 0 failures` is the empty XCTest summary; it proves nothing.\n- Always pass `-resultBundlePath` with a new path per attempt; `xcodebuild` fails when the\n  path already exists.\n- Read the verdict from that fresh bundle with\n  `xcrun xcresulttool get test-results summary --path \u003Cbundle>`. A pass needs the expected\n  non-zero test count there, no failure or crash there, `** TEST SUCCEEDED **`, and a zero\n  exit status (`principle-prove-it-works`).\n- The log's `✔ Test run with N tests in M suites passed`, with N greater than zero,\n  corroborates that count; a pattern that also matches zero proves nothing. A filtered or\n  `-quiet` log can omit the line, so never treat its absence alone as the verdict.\n- Take the expected test count from the target's tests or test plan, never from the run you\n  are judging.\n- Match the expected case IDs against `xcresulttool get test-results tests --path\n  \u003Cbundle>`; totals alone do not prove each selected case ran. Inspect `test-details`\n  and `metrics` when a case fails or measures performance, preserving the actual\n  measurements and failure reason. Pin the toolchain, configuration, device and\n  workload for comparisons. State the non-UI XCTest authoring-guide gap explicitly\n  when using project conventions as the fallback.\n- A run that executed zero tests is not a pass, whatever its exit status\n  (`principle-gaps-are-not-passes`). Suspect the selection before the code: confirm\n  `-only-testing` still names the current suite and test after any rename, and that the\n  target belongs to the test plan.\n- Grep once with the full set of terminal markers: `\\*\\* BUILD SUCCEEDED \\*\\*`,\n  `\\*\\* BUILD FAILED \\*\\*`, `\\*\\* TEST SUCCEEDED \\*\\*`, `\\*\\* TEST FAILED \\*\\*`,\n  `Testing failed:`, and `^error:`. Judge the marker together with the exit status.\n- To confirm which suites ran, match both spellings: XCTest prints `Test Suite '.*' started`,\n  and Swift Testing prints a `Suite .* started` record. Match them case-sensitively as printed.\n- On failure, read the bundle summary for the structured crash reason, such as\n  `Test crashed with signal abrt`; it may appear only there. The log may repeat it as an\n  underlying error, but the bundle is the reliable source. Do not re-run blind.\n- Treat `The test runner hung before establishing connection` and diagnostic-collection\n  timeouts as a suspected environmental fault, not a proven diagnosis. Shut down the\n  pinned simulator (`xcrun simctl shutdown \u003Cudid>`) only if this run created and still\n  owns it, then retry once within the run's time bounds with a new result-bundle path.\n  Pinning a pre-existing device does not confer ownership: preserve it and report\n  blocked when recovery needs its shutdown. Never use `xcrun simctl shutdown all`.\n- Pass `TEST_RUNNER_\u003CNAME>=\u003Cvalue>` on the `xcodebuild test` command; Xcode strips the\n  prefix and gives the variable to the test runner process. A UI test target's app under test\n  does not receive it; set `XCUIApplication.launchEnvironment` for that case.\n- `test-without-building` runs the product and `.xctestrun` file an earlier build produced,\n  so it can report a success that excludes your latest source change. Rebuild with\n  `xcodebuild test` before you trust a pass, and whenever that product is the suspect.\n- A test-bundle load error names the missing library, not the cause. When a load failure\n  survives the rebuild, inspect the framework's embedding and runpath settings as candidates.\n\n## 4. Install, Launch, and Drive\n\n- Install the build you just made before launching. Never launch whatever is already on the\n  device: it can come from another branch (`principle-prove-it-works`).\n  Record revision plus relevant uncommitted-source identity and bind it to the\n  actual built, installed and launched product; a matching HEAD alone is insufficient.\n- `simctl install` needs a booted device. Boot the pinned device with\n  `xcrun simctl bootstatus \u003Cudid> -b`, which boots it if shut down and waits for the boot to\n  finish. Do not call `xcrun simctl boot` first: it fails on a running device.\n- Know the product path before you install: pass `-derivedDataPath \u003Cdir>` to the build, or\n  read `BUILT_PRODUCTS_DIR` and `FULL_PRODUCT_NAME` from `xcodebuild -showBuildSettings`.\n  On that call repeat every flag the build used, including `-derivedDataPath`, the scheme,\n  and the destination; different flags report another build's product path.\n- Read the bundle id from that build, not from memory:\n  `\u002Fusr\u002Flibexec\u002FPlistBuddy -c 'Print :CFBundleIdentifier' \u003Capp-path>\u002FInfo.plist`.\n- Prefer the simulator MCP: call its install action with the new `.app` path, then its\n  launch action with the bundle id. Pass the pinned UDID to both; their device argument is\n  optional and defaults elsewhere.\n- A running MCP server does not inherit a `DEVELOPER_DIR` exported in a shell. When the run\n  needs a beta Xcode, use the `xcrun` commands with that `DEVELOPER_DIR` instead.\n- When the MCP launch fails with `Failed to spawn xcrun (via disclaimer)`, fall back to\n  `xcrun simctl install \u003Cudid> \u003Capp-path>`, then `xcrun simctl launch \u003Cudid> \u003Cbundle-id>`.\n- A deep link (`xcrun simctl openurl \u003Cudid> \u003Cscheme>:\u002F\u002F\u003Cpath>`) or existing\n  DEBUG\u002Fseed mechanism may establish a screen or fixture precondition. It must\n  not replace the public interaction that the claimed journey is meant to prove.\n  Use accessible UI automation for that boundary, not blind coordinate taps.\n  For capture-only screen setup, prefer an existing deep link or DEBUG scenario\n  over UI navigation; its purpose here is to reach the state, not prove creation\n  or another public-action boundary.\n- Read the accessibility hierarchy before you tap; coordinates are the last resort.\n\n## 5. Screenshots\n\n- Pick ONE capture mechanism per run: `xcrun simctl io \u003Cudid> screenshot \u003Cpath>.png` when\n  the file must persist for comparison, the MCP screenshot action to look now. Never use\n  both for the same frame.\n- Number the files (`round2\u002F01-hub-gate.png`) so rounds diff cleanly against a baseline.\n- A freshly erased simulator posts a system banner soon after boot. Wait for the boot with\n  `xcrun simctl bootstatus \u003Cudid> -b`, then read the accessibility hierarchy and confirm no\n  system alert covers the view. Capture only after that check passes; a fixed short delay is\n  not evidence (`principle-observe-dont-infer`).\n\n## Isolation, cleanup and evidence\n\nUse independently owned simulator\u002Fapp\u002Ffixture state when a run mutates data.\nDo not erase or reset a user's shared simulator or store. Record ownership before\nlaunch; only a created device may be shut down\u002Fdeleted as this run's teardown.\nOn success, error or cancellation, release only resources still owned by the run,\nnever kill by process name or trust a reused PID. Preserve logs, result bundles\nand captures outside cleanup targets and confirm they survive teardown. A blocked\ndevice\u002Fentitlement\u002Fsystem boundary is not proved through another simulator path.\n\nUse synthetic data and disposable accounts. Inspect and redact shareable log,\nresult-bundle and capture derivatives; keep necessary originals access-controlled\nunder the project's retention policy. Never publish credentials, customer data\nor whole unreviewed bundles.\n\nIn a capture plan, name the pinned UDID and derive the bundle identifier from\nthe intended build; pass both to the launch command. Report missing state proof,\nfailed cleanup and unavailable evidence explicitly rather than implying success.\n\n## 6. Cadence\n\n- Compile after the domain layer and again after the first view, not once at the end\n  (`principle-sequence-verifiable-units`).\n- Run the test suite once, early, before you declare a change done.\n\n## Related Skills\n\n- **`app:debug`** — structured feedback loop for simulator failures, user-reported or observed\n- **`core:visual-feedback`** — interactive appearance diagnosis and before\u002Fafter\n  review; this loop supplies the execution, captures and identity\u002Fstate evidence.\n- **`app:swift-testing`** — Swift Testing authoring; **`app:xcuitest`** —\n  XCTest UI authoring. Keep non-UI XCTest tests in their existing framework.\n- **`app:swiftui-architecture`** — SwiftUI patterns for the code under test\n",{"name":5,"description":7},"main","4e0a12b5048eac78a3ace4feee657873cdd530ef","src\u002Fapp\u002Fskills\u002Fxcode-dev-loop",7,"https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills","https:\u002F\u002Fgithub.com\u002Fmintuz","http:\u002F\u002Fwww.mintuz.com","Working at @monzo, Previously worked at Moonpig, @booking and @bbc","2026-11-13 19:21:11",{"source":8,"skillName":5,"commands":52,"prompt":62,"zipAvailable":63},[53,56,59],{"tool":54,"command":55},"npx","npx skills add mintuz\u002Fskills --skill xcode-dev-loop",{"tool":57,"command":58},"bunx","bunx skills add mintuz\u002Fskills --skill xcode-dev-loop",{"tool":60,"command":61},"pnpm","pnpm dlx skills add mintuz\u002Fskills --skill xcode-dev-loop","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fapp\u002Fskills\u002Fxcode-dev-loop\u002FSKILL.md",true,[],[66,84,107,120,140,157],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":76,"publishedAt":37},"01M6C4PDGB6ZZWBS35N3DF7PZZ","xstate","WHEN React state changes in response to an external answer — async submit, in-flight or loading flags, retries, cancellation, polling, optimistic updates, stale responses — or to an interaction with an interruptible middle, such as a drag or a gesture; or WHEN building, reviewing, testing, or visualising XState 5 actors and @xstate\u002Freact integrations; NOT for a value one event sets completely, such as a text draft, a focus flag, or a plain open and closed toggle; models typed lifecycles and renders legal Mermaid stateDiagram-v2 charts.","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fweb\u002Fskills\u002Fxstate\u002FSKILL.md",[72,73],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":74,"categoryName":75,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[68,77,78,79,80,81,82,27,83],"react","text","state","integrations","Charts","mermaid","open",{"skillNo":85,"name":86,"nameZh":6,"description":87,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":98,"publishedAt":37},"01M6C4PB6VVC2X19B63B7YNH0T","web-design","WHEN refining UI layout, typography, color, or polish; NOT code implementation; provides concise principles for intentional, legible design.","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fweb\u002Fskills\u002Fweb-design\u002FSKILL.md",[90,95],{"categoryNo":91,"categoryName":92,"taxonomyType":93,"taxonomyTypeDesc":94},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",{"categoryNo":96,"categoryName":97,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",[99,100,101,102,103,104,105,106],"web","design","web design","code implementation","polish","ui","typography","code",{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":114,"publishedAt":37},"01M6C4P8D92GJDA49V7X1CZXEV","tailwind","USE WHEN writing, fixing or reviewing styling in a project that uses Tailwind CSS, even a one-class change or a request that does not name Tailwind: colours, focus rings, spacing, class names chosen by a prop, map or CVA variants, theme tokens and dark mode in the Tailwind stylesheet or tailwind.config, setup or upgrades (if unsure whether the project uses Tailwind, check package.json or the main stylesheet first); NOT WHEN writing plain CSS or Sass in a project without Tailwind; produces class names Tailwind can find, syntax for the installed major version, visible focus indicators, and no unrequested dependency or invented brand value.","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fweb\u002Fskills\u002Ftailwind\u002FSKILL.md",[113],{"categoryNo":96,"categoryName":97,"taxonomyType":21,"taxonomyTypeDesc":22},[115,116,117,118,100,119],"Tailwind","libraries","component","css","design systems",{"skillNo":121,"name":122,"nameZh":6,"description":123,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":124,"categories":125,"keywords":129,"publishedAt":37},"01M6C4P5VWQ69Q32DA0634GDJY","refactoring","WHEN you need a plan to refactor, restructure, or clean up working code and the test result is known, either green or a recorded failing set; NOT for new feature delivery or any behavior change; reversible-baseline safety with prioritized improvements.","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fweb\u002Fskills\u002Frefactoring\u002FSKILL.md",[126],{"categoryNo":127,"categoryName":128,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000007","代码审查",[122,130,131,132,133,134,135,136,137,138,106,139,30],"Safety","baseline","refactor","behavior","change","plan","new feature","SET","up","feature delivery",{"skillNo":141,"name":77,"nameZh":6,"description":142,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":143,"categories":144,"keywords":147,"publishedAt":37},"01M6C4P345APEFEX00J8T7QMXQ","USE WHEN changing the logic, data, props, state, Effects or rendered text of a React component, hook or page, even a one-line change; NOT WHEN the request is styling only (class names, Tailwind, CSS, dark mode, spacing, shadows) or tests only, or when it models submit, in-flight, loading, retry or failure states, even for a named React form (xstate covers that, including its React wiring); applies React 19 composition, state, Effect, structure, API and performance rules with only the project's installed libraries.","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fweb\u002Fskills\u002Freact\u002FSKILL.md",[145,146],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":74,"categoryName":75,"taxonomyType":21,"taxonomyTypeDesc":22},[77,106,118,115,148,27,149,150,151,152,153,79,30,154,155,156],"performance","hooks","components","architecture","api","react components","state management","styling","management",{"skillNo":158,"name":159,"nameZh":6,"description":160,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":161,"categories":162,"keywords":165,"publishedAt":37},"01M6C4P0DK385QBG3B3S86TQV2","react-testing","USE WHEN writing, fixing or reviewing a React Testing Library test for a component, hook or context provider, even one small test, or when asked for an end-to-end journey inside a Vitest or React Testing Library suite; NOT WHEN changing the component itself (react), testing XState actors or @xstate\u002Freact (xstate), or writing a Playwright or Cypress test; covers renderHook, providers, async results, forms and false-pass anti-patterns, and declines end-to-end journeys with the testable slices.","https:\u002F\u002Fgithub.com\u002Fmintuz\u002Fskills\u002Fblob\u002Fmain\u002Fsrc\u002Fweb\u002Fskills\u002Freact-testing\u002FSKILL.md",[163,164],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":74,"categoryName":75,"taxonomyType":21,"taxonomyTypeDesc":22},[166,27,77,167,149,168,169,170,150,171,172,153],"react testing","anti-patterns","e2e","library","testing library","Providers","context"]