Skip to content

apple: add TipKit workflow guidance#119

Merged
gaelic-ghost merged 1 commit into
mainfrom
apple/tipkit-workflow
Jul 12, 2026
Merged

apple: add TipKit workflow guidance#119
gaelic-ghost merged 1 commit into
mainfrom
apple/tipkit-workflow

Conversation

@gaelic-ghost

@gaelic-ghost gaelic-ghost commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a docs-first TipKit workflow for SwiftUI, UIKit, and AppKit
  • cover inline tips, tooltip popovers, eligibility, lifecycle, testing, and troubleshooting
  • align Apple Dev Skills metadata, inventory, roadmap, and validation contracts

Verification

  • uv run --directory plugins/apple-dev-skills pytest (201 passed)
  • bash plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh
  • uv run scripts/validate_socket_metadata.py
  • isolated forward test against a toolbar popover and event-rule scenario

Summary by CodeRabbit

  • New Features

    • Added a TipKit workflow covering setup, presentations, eligibility, lifecycle management, testing, troubleshooting, and platform-specific patterns across SwiftUI, UIKit, and AppKit.
    • Added guidance for TipKit customization, configuration, and persistent settings.
    • Added the TipKit workflow to the available Apple development skills and documentation inventory.
  • Tests

    • Added focused validation covering TipKit guidance, metadata, inventory, and documentation consistency.

@gaelic-ghost gaelic-ghost added the enhancement New feature or request label Jul 12, 2026
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new tipkit-workflow skill covering TipKit implementation, presentation, eligibility, testing, customization, and troubleshooting across SwiftUI, UIKit, and AppKit. Repository metadata, validation scripts, customization tooling, documentation, and focused tests are updated.

Changes

TipKit workflow

Layer / File(s) Summary
Workflow guidance and platform patterns
plugins/apple-dev-skills/skills/tipkit-workflow/SKILL.md, plugins/apple-dev-skills/skills/tipkit-workflow/references/*.md, plugins/apple-dev-skills/skills/tipkit-workflow/references/snippets/*
Adds TipKit workflow instructions covering setup, presentation, eligibility, lifecycle, deterministic testing, troubleshooting, platform APIs, and Xcode project conventions.
Customization configuration tooling
plugins/apple-dev-skills/skills/tipkit-workflow/references/customization*, plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py
Defines the customization contract and template, and adds CLI commands for inspecting, applying, validating, persisting, and resetting configuration.
Repository registration and metadata
plugins/apple-dev-skills/.codex-plugin/plugin.json, plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh, plugins/apple-dev-skills/README.md, plugins/apple-dev-skills/ROADMAP.md, plugins/apple-dev-skills/skills/tipkit-workflow/agents/openai.yaml, plugins/apple-dev-skills/docs/maintainers/*
Registers the new skill in plugin metadata, inventories, validation counts, roadmap, agent metadata, and customization-surface documentation.
Workflow and inventory tests
plugins/apple-dev-skills/tests/*
Adds TipKit documentation and metadata assertions and updates active-skill and customization-count expectations.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant TipKitWorkflow
  participant CustomizationCLI
  participant RepositoryTests
  Developer->>TipKitWorkflow: Request TipKit implementation or troubleshooting guidance
  TipKitWorkflow->>CustomizationCLI: Inspect or apply documented customization
  CustomizationCLI-->>TipKitWorkflow: Return effective configuration
  TipKitWorkflow-->>Developer: Provide platform-specific workflow and testing guidance
  RepositoryTests->>TipKitWorkflow: Validate documentation and metadata
Loading

Possibly related PRs

  • gaelic-ghost/socket#51: Updates the same active-skill validator and plugin inventory registration paths for another workflow skill.

Suggested labels: documentation

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding TipKit workflow guidance to the Apple skills docs and metadata.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch apple/tipkit-workflow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gaelic-ghost gaelic-ghost merged commit 7e002bd into main Jul 12, 2026
2 checks passed
@gaelic-ghost gaelic-ghost deleted the apple/tipkit-workflow branch July 12, 2026 04:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
plugins/apple-dev-skills/tests/test_tipkit_workflow.py (1)

18-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use subTest in loop-based assertions for faster failure diagnosis.

The loops at lines 18–19 and 27–28 concatenate two files and check multiple terms, but without subTest, a failure reports only the first missing term without identifying which one. Wrapping each iteration in subTest preserves the one-assert-per-failure clarity used in the other test files in this repo.

♻️ Proposed refactor for lines 18–19
-        for term in ("Tips.configure", "TipView", "popoverTip", "TipUIView", "TipUIPopoverViewController", "TipNSView", "TipNSPopover"):
-            self.assertIn(term, skill + presentation)
+        for term in ("Tips.configure", "TipView", "popoverTip", "TipUIView", "TipUIPopoverViewController", "TipNSView", "TipNSPopover"):
+            with self.subTest(term=term):
+                self.assertIn(term, skill + presentation)

Also applies to: 27-28

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/apple-dev-skills/tests/test_tipkit_workflow.py` around lines 18 - 19,
Update the loop-based assertions in the affected tests to wrap each term check
in a self.subTest context, including both loops around the assertions over skill
+ presentation. Preserve the existing terms and assertIn behavior while ensuring
failures identify the specific term that is missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugins/apple-dev-skills/README.md`:
- Line 153: Reconcile the skill inventory centered on the README’s
tipkit-workflow entry so the documented list matches the canonical 33-skill
count required by validate_repo_docs.sh and test_tipkit_workflow.py. Prefer
removing or correcting the extra inventory entries to restore exactly 33, unless
intentionally updating every registration and validation contract consistently.

In
`@plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py`:
- Around line 113-121: Update dump_yaml to serialize an empty config["settings"]
mapping as “settings: {}” rather than emitting a bare “settings:” line. Preserve
the existing indented key serialization for non-empty settings so
validate_config() can reload both cases as mappings.
- Around line 38-45: Update encode_scalar to serialize supported scalar types
without converting them to quoted strings, especially preserving float values
through apply and reload. Retain the existing boolean, integer, None, and string
handling, and align the additional scalar cases with the types accepted by
validate_config().
- Around line 173-175: Update the configuration write flow around durable_path()
to write dump_yaml(updated) to a temporary file in target.parent, then
atomically replace target using os.replace(). Preserve UTF-8 encoding and ensure
the temporary file is cleaned up if replacement fails.
- Around line 71-73: Update the top-level and applicable nested key validation
around ALLOWED_TOP_LEVEL to detect non-string mapping keys before sorting
unknown keys or passing keys to regex validation. Route these cases through fail
with the CLI’s normal validation error, while preserving existing handling for
valid string keys.

In `@plugins/apple-dev-skills/skills/tipkit-workflow/SKILL.md`:
- Line 3: Update the TipKit skill description to remove the term “onboarding”
and any onboarding-oriented guidance, while preserving its contextual
feature-discovery scope and all existing TipKit symbols and workflows.

---

Nitpick comments:
In `@plugins/apple-dev-skills/tests/test_tipkit_workflow.py`:
- Around line 18-19: Update the loop-based assertions in the affected tests to
wrap each term check in a self.subTest context, including both loops around the
assertions over skill + presentation. Preserve the existing terms and assertIn
behavior while ensuring failures identify the specific term that is missing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2670db12-ac79-4510-8d82-ca18bf740ea5

📥 Commits

Reviewing files that changed from the base of the PR and between 4b8bb30 and 4da3a94.

📒 Files selected for processing (17)
  • plugins/apple-dev-skills/.codex-plugin/plugin.json
  • plugins/apple-dev-skills/.github/scripts/validate_repo_docs.sh
  • plugins/apple-dev-skills/README.md
  • plugins/apple-dev-skills/ROADMAP.md
  • plugins/apple-dev-skills/docs/maintainers/customization-consolidation-review.md
  • plugins/apple-dev-skills/skills/tipkit-workflow/SKILL.md
  • plugins/apple-dev-skills/skills/tipkit-workflow/agents/openai.yaml
  • plugins/apple-dev-skills/skills/tipkit-workflow/references/customization-flow.md
  • plugins/apple-dev-skills/skills/tipkit-workflow/references/customization.template.yaml
  • plugins/apple-dev-skills/skills/tipkit-workflow/references/eligibility-lifecycle-and-testing.md
  • plugins/apple-dev-skills/skills/tipkit-workflow/references/presentation-and-platform-patterns.md
  • plugins/apple-dev-skills/skills/tipkit-workflow/references/snippets/apple-xcode-project-core.md
  • plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py
  • plugins/apple-dev-skills/tests/test_apple_developer_provisioning_workflow.py
  • plugins/apple-dev-skills/tests/test_customization_consolidation_review.py
  • plugins/apple-dev-skills/tests/test_devicecheck_app_attest_workflow.py
  • plugins/apple-dev-skills/tests/test_tipkit_workflow.py

- `sf-symbols-workflow`
- `structure-swift-sources`
- `swiftdata-workflow`
- `tipkit-workflow`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Reconcile the Active Skills inventory count.

After adding tipkit-workflow, this README lists 35 skill entries (Lines 131–165), but .github/scripts/validate_repo_docs.sh and tests/test_tipkit_workflow.py require exactly 33. Align the README with the canonical 33-skill inventory, or update all registration and validation contracts consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/apple-dev-skills/README.md` at line 153, Reconcile the skill
inventory centered on the README’s tipkit-workflow entry so the documented list
matches the canonical 33-skill count required by validate_repo_docs.sh and
test_tipkit_workflow.py. Prefer removing or correcting the extra inventory
entries to restore exactly 33, unless intentionally updating every registration
and validation contract consistently.

Comment on lines +38 to +45
def encode_scalar(value) -> str:
if isinstance(value, bool):
return "true" if value else "false"
if isinstance(value, int):
return str(value)
if value is None:
return quote_string("")
return quote_string(str(value))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve scalar types during serialization.

validate_config() accepts floats and other scalar values, but encode_scalar() converts anything other than bool and int to a quoted string. A float setting therefore changes type after apply and reload.

Also applies to: 119-120

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py`
around lines 38 - 45, Update encode_scalar to serialize supported scalar types
without converting them to quoted strings, especially preserving float values
through apply and reload. Retain the existing boolean, integer, None, and string
handling, and align the additional scalar cases with the types accepted by
validate_config().

Comment on lines +71 to +73
unknown = set(config.keys()) - ALLOWED_TOP_LEVEL
if unknown:
fail(f"Unknown top-level keys: {', '.join(sorted(unknown))}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Reject non-string mapping keys before sorting or regex validation.

YAML permits non-string keys. Such input can reach sorted(unknown) or re.fullmatch(..., key) and raise an uncaught TypeError instead of producing the CLI’s normal validation error.

Also applies to: 89-91

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py`
around lines 71 - 73, Update the top-level and applicable nested key validation
around ALLOWED_TOP_LEVEL to detect non-string mapping keys before sorting
unknown keys or passing keys to regex validation. Route these cases through fail
with the CLI’s normal validation error, while preserving existing handling for
valid string keys.

Comment on lines +113 to +121
def dump_yaml(config: dict) -> str:
lines = [
f"schemaVersion: {int(config['schemaVersion'])}",
f"isCustomized: {'true' if config['isCustomized'] else 'false'}",
"settings:",
]
for key in sorted(config["settings"].keys()):
lines.append(f" {key}: {encode_scalar(config['settings'][key])}")
return "\n".join(lines) + "\n"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Serialize an empty settings mapping as {}.

When config["settings"] is empty, this function emits:

settings:

That parses as null, not a mapping, so the default effective output and an empty apply result cannot be loaded again by validate_config().

Proposed fix
 def dump_yaml(config: dict) -> str:
+    if not config["settings"]:
+        return (
+            f"schemaVersion: {int(config['schemaVersion'])}\n"
+            f"isCustomized: {'true' if config['isCustomized'] else 'false'}\n"
+            "settings: {}\n"
+        )
     lines = [
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py`
around lines 113 - 121, Update dump_yaml to serialize an empty
config["settings"] mapping as “settings: {}” rather than emitting a bare
“settings:” line. Preserve the existing indented key serialization for non-empty
settings so validate_config() can reload both cases as mappings.

Comment on lines +173 to +175
target = durable_path()
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(dump_yaml(updated), encoding="utf-8")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Write durable configuration atomically.

A process interruption during write_text() can leave a truncated or invalid customization file, causing subsequent effective and apply commands to fail. Write a temporary file in the same directory and replace the target with os.replace().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@plugins/apple-dev-skills/skills/tipkit-workflow/scripts/customization_config.py`
around lines 173 - 175, Update the configuration write flow around
durable_path() to write dump_yaml(updated) to a temporary file in target.parent,
then atomically replace target using os.replace(). Preserve UTF-8 encoding and
ensure the temporary file is cleaned up if replacement fails.

@@ -0,0 +1,75 @@
---
name: tipkit-workflow
description: Add, configure, present, style, test, and troubleshoot Apple TipKit tips in SwiftUI, UIKit, and AppKit using current Apple documentation. Use for Tip protocol definitions, Tips.configure, TipView inline tips, popoverTip tooltip popovers, TipUIView, TipUIPopoverViewController, TipNSView, TipNSPopover, rules, parameters, events and donations, actions, invalidation, display frequency, persistent datastores, testing overrides, and tips that do not appear or reappear correctly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="plugins/apple-dev-skills/skills/tipkit-workflow/SKILL.md"
wc -l "$file"
cat -n "$file" | sed -n '1,40p'

Repository: gaelic-ghost/socket

Length of output: 3781


🌐 Web query:

TipKit Apple documentation feature discovery onboarding guide cautions app flow

💡 Result:

Apple's TipKit framework is designed to provide contextual, non-intrusive feature discovery and onboarding [1][2]. Rather than traditional, front-loaded onboarding screens that users often ignore, TipKit allows developers to surface tips only when they are contextually relevant to a user's current activity [3][4]. Key guidelines and best practices for integrating TipKit into your app flow include: Focus on Contextual Relevance - Avoid showing tips immediately upon app launch [3]. Instead, trigger tips when a user is in the vicinity of a feature or has shown interest in it [3]. - Use eligibility rules (parameter-based or event-based) to ensure tips reach only the most relevant audience [5][6]. For example, only show a tip if a user has launched the app a minimum number of times or has not yet utilized a specific feature [3]. - Never describe the UI itself. Instead, focus on the user's outcome, such as the benefit they will gain from using the feature [3]. Maintain User Experience (UX) Quality - Use frequency control (e.g.,.daily or.hourly) to prevent tip fatigue [4]. Setting frequency to.immediate is suitable for development but generally discouraged for production [4]. - Always invalidate tips after a user has successfully engaged with the feature being taught [4][6]. Failing to do so can result in redundant, frustrating displays [4]. - Be mindful of tip order. Use.ordered to show tips in a specific sequence, or.firstAvailable to display the most relevant tip when multiple are eligible [4]. Implementation and Testing - Configure the Tips system at app launch using Tips.configure [7][6]. - During development, leverage TipKit's testing functions, such as Tips.showTipsForTesting(_:), to bypass eligibility rules and verify UI presentation [7]. - Ensure your copy is concise and follows Apple's Human Interface Guidelines for "Offering Help," using sentence case and clear, actionable language [8]. By treating tips as data (structs with titles, messages, and rules) and allowing the framework to manage their presentation state, you can create a more educational and less intrusive app experience [4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="plugins/apple-dev-skills/skills/tipkit-workflow/SKILL.md"
printf 'FILE: %s\n' "$file"
nl -ba "$file" | sed -n '1,30p'

Repository: gaelic-ghost/socket

Length of output: 260


🌐 Web query:

site:developer.apple.com TipKit feature discovery onboarding app flow

💡 Result:

TipKit is the recommended framework by Apple for implementing feature discovery and contextual onboarding within iOS and other platform apps [1][2]. Instead of relying solely on traditional, front-loaded onboarding flows, Apple’s Human Interface Guidelines suggest providing a collection of context-specific tips to teach users about features as they encounter them [3][2]. Key components for implementing feature discovery with TipKit include: Contextual Integration: Tips are designed to be displayed at the "perfect moment" when a user is likely to need or appreciate the information, rather than interrupting the user immediately upon launch [4]. Tip Groups: You can use TipGroup to sequence tips, ensuring features are discovered in an ideal, structured order [4]. This helps manage the educational flow and prevents overwhelming the user. Eligibility and Rules: TipKit manages display states and history automatically, but you retain control through eligibility rules. You can use these rules to ensure tips only appear to relevant users (e.g., users who have not used a specific feature yet) [4]. Display Frequency: To maintain a positive user experience, you can set a global display frequency (e.g., daily or weekly) using Tips.configure(_:) to ensure users are not bombarded with too many tips in a short timeframe [4][5]. Customization: TipKit supports custom tip identifiers, which allow for reusable tips (e.g., creating unique tips for dynamic content like new items in a list), and offers configurable presentation styles (TipViewStyle) to ensure the UI matches your app’s design [4][6]. CloudKit Syncing: You can sync the TipKit datastore via CloudKit to share tip display states across a user's devices, preventing the same tip from appearing on multiple devices once it has been dismissed or viewed on one [4]. For further guidance, Apple provides detailed resources in their documentation and session videos, specifically WWDC23 "Make features discoverable with TipKit" and WWDC24 "Customize feature discovery with TipKit" [4][7].

Citations:


Remove “onboarding” from the TipKit guidance. TipKit is for contextual feature discovery; phrasing it as onboarding can steer authors toward using it as a full onboarding flow instead of a dedicated onboarding experience.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/apple-dev-skills/skills/tipkit-workflow/SKILL.md` at line 3, Update
the TipKit skill description to remove the term “onboarding” and any
onboarding-oriented guidance, while preserving its contextual feature-discovery
scope and all existing TipKit symbols and workflows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant