@mmerterden/multi-agent-pipeline 20.35.0 → 20.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +6 -5
- package/README.tr.md +6 -5
- package/docs/architecture.md +3 -3
- package/docs/ecosystem.md +5 -5
- package/docs/facts.json +4 -4
- package/install/catalog-history.json +1 -1
- package/manifest.json +210 -136
- package/package.json +5 -1
- package/pipeline/commands/multi-agent/SKILL.md +33 -154
- package/pipeline/commands/multi-agent/analysis/SKILL.md +14 -68
- package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +5 -8
- package/pipeline/commands/multi-agent/autopilot-on/SKILL.md +38 -109
- package/pipeline/commands/multi-agent/channels/SKILL.md +38 -167
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +37 -144
- package/pipeline/commands/multi-agent/design-check/SKILL.md +27 -131
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +22 -48
- package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +37 -180
- package/pipeline/commands/multi-agent/jira/SKILL.md +16 -46
- package/pipeline/commands/multi-agent/office-pair/SKILL.md +66 -0
- package/pipeline/commands/multi-agent/office-status/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/refactor/SKILL.md +23 -184
- package/pipeline/commands/multi-agent/resume/SKILL.md +30 -136
- package/pipeline/commands/multi-agent/review/SKILL.md +24 -199
- package/pipeline/commands/multi-agent/setup/SKILL.md +25 -181
- package/pipeline/commands/multi-agent/stack/SKILL.md +9 -53
- package/pipeline/commands/multi-agent/status/SKILL.md +13 -2
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +27 -226
- package/pipeline/commands/multi-agent/sync/SKILL.md +38 -167
- package/pipeline/commands/multi-agent/test-gen/SKILL.md +2 -4
- package/pipeline/commands/multi-agent/update/SKILL.md +18 -60
- package/pipeline/contract/CHANGELOG.md +9 -0
- package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
- package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
- package/pipeline/contract/fixtures/error-unsigned.json +1 -1
- package/pipeline/contract/fixtures/runs-awaiting-question.json +1 -1
- package/pipeline/contract/fixtures/runs-empty.json +1 -1
- package/pipeline/contract/fixtures/runs-failed.json +1 -1
- package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +1 -1
- package/pipeline/contract/fixtures/runs-pr-opened.json +1 -1
- package/pipeline/contract/fixtures/runs-running.json +1 -1
- package/pipeline/contract/manifest.json +5 -5
- package/pipeline/contract/types/index.d.ts +3 -2
- package/pipeline/lib/qr-code.mjs +26 -0
- package/pipeline/multi-agent-refs/autopilot-on/details.md +148 -0
- package/pipeline/multi-agent-refs/channels/generator.md +14 -0
- package/pipeline/multi-agent-refs/channels/preview.md +13 -0
- package/pipeline/multi-agent-refs/channels/reference.md +46 -0
- package/pipeline/multi-agent-refs/complaint-analysis/phases.md +159 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
- package/pipeline/multi-agent-refs/design-check/export.md +1 -0
- package/pipeline/multi-agent-refs/design-check/init-inventory.md +1 -1
- package/pipeline/multi-agent-refs/design-check/scope-and-ledger.md +64 -0
- package/pipeline/multi-agent-refs/features/analysis-command-notes.md +53 -0
- package/pipeline/multi-agent-refs/garbage-collect/phases.md +60 -0
- package/pipeline/multi-agent-refs/help/en.md +1 -0
- package/pipeline/multi-agent-refs/help/tr.md +1 -0
- package/pipeline/multi-agent-refs/ios-coding-standard/plan.md +71 -0
- package/pipeline/multi-agent-refs/ios-coding-standard/resolve-and-scan.md +135 -0
- package/pipeline/multi-agent-refs/jira/picker-detail.md +71 -0
- package/pipeline/multi-agent-refs/orchestrator/copilot-pipeline.md +88 -0
- package/pipeline/multi-agent-refs/orchestrator/dispatcher.md +96 -1
- package/pipeline/multi-agent-refs/refactor/sweep.md +190 -0
- package/pipeline/multi-agent-refs/resume/details.md +115 -2
- package/pipeline/multi-agent-refs/review/inputs.md +33 -1
- package/pipeline/multi-agent-refs/review/module-guides.md +9 -1
- package/pipeline/multi-agent-refs/review/panel.md +75 -0
- package/pipeline/multi-agent-refs/review/valven.md +5 -1
- package/pipeline/multi-agent-refs/setup/hooks-and-plugins.md +4 -0
- package/pipeline/multi-agent-refs/setup/token-save-flow.md +13 -0
- package/pipeline/multi-agent-refs/stack/background.md +72 -0
- package/pipeline/multi-agent-refs/store-ready/gates.md +139 -0
- package/pipeline/multi-agent-refs/store-ready/report.md +40 -2
- package/pipeline/multi-agent-refs/sync/office.md +10 -0
- package/pipeline/multi-agent-refs/sync/overview.md +61 -0
- package/pipeline/multi-agent-refs/sync/repo.md +91 -0
- package/pipeline/multi-agent-refs/update/details.md +83 -0
- package/pipeline/schemas/runs-index.schema.json +2 -1
- package/pipeline/scripts/contract-server.mjs +1 -1
- package/pipeline/scripts/office-pair.mjs +40 -9
- package/pipeline/scripts/runs-index.mjs +34 -7
- package/pipeline/scripts/status-overview.mjs +401 -0
- package/pipeline/skills/.skill-manifest.json +69 -65
- package/pipeline/skills/.skills-index.json +15 -4
- package/pipeline/skills/shared/README.md +4 -3
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +8 -71
- package/pipeline/skills/shared/core/apple-archive-compliance/references/examples.md +67 -0
- package/pipeline/skills/shared/core/apple-archive-compliance/references/version-history.md +8 -0
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +11 -73
- package/pipeline/skills/shared/core/google-play-compliance/references/examples.md +69 -0
- package/pipeline/skills/shared/core/google-play-compliance/references/notes.md +7 -0
- package/pipeline/skills/shared/core/google-play-compliance/references/version-history.md +5 -0
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +39 -262
- package/pipeline/skills/shared/core/multi-agent-autopilot-on/SKILL.md +35 -73
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +37 -337
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +27 -122
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +8 -340
- package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +37 -180
- package/pipeline/skills/shared/core/multi-agent-office-pair/SKILL.md +19 -0
- package/pipeline/skills/shared/core/multi-agent-office-status/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +23 -184
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +14 -82
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +25 -277
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +13 -2
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +75 -219
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +11 -162
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-code.md +257 -0
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +7 -58
- package/pipeline/skills/shared/external/android-architecture/references/code-examples.md +68 -0
- package/pipeline/skills/shared/external/app-intents/SKILL.md +3 -45
- package/pipeline/skills/shared/external/app-intents/references/code-examples.md +54 -0
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +5 -81
- package/pipeline/skills/shared/external/app-store-optimization/references/engagement-and-localization.md +96 -0
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +6 -112
- package/pipeline/skills/shared/external/app-store-review/references/monetization-and-submission.md +138 -0
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +10 -117
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models-code.md +186 -0
- package/pipeline/skills/shared/external/authentication/SKILL.md +3 -50
- package/pipeline/skills/shared/external/authentication/references/code-examples.md +59 -0
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +3 -84
- package/pipeline/skills/shared/external/callkit-voip/references/code-examples.md +93 -0
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +7 -263
- package/pipeline/skills/shared/external/ci-cd-pipelines/references/pipeline-examples.md +281 -0
- package/pipeline/skills/shared/external/clean-code/SKILL.md +8 -41
- package/pipeline/skills/shared/external/clean-code/references/code-examples.md +56 -0
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +8 -146
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-code.md +214 -0
- package/pipeline/skills/shared/external/compose-components/SKILL.md +6 -80
- package/pipeline/skills/shared/external/compose-components/references/code-examples.md +89 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +5 -64
- package/pipeline/skills/shared/external/compose-navigation/references/code-examples.md +70 -0
- package/pipeline/skills/shared/external/core-data/SKILL.md +9 -157
- package/pipeline/skills/shared/external/core-data/references/core-data-code.md +221 -0
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +3 -89
- package/pipeline/skills/shared/external/core-nfc/references/code-examples.md +98 -0
- package/pipeline/skills/shared/external/coreml/SKILL.md +17 -133
- package/pipeline/skills/shared/external/coreml/references/coreml-code.md +208 -0
- package/pipeline/skills/shared/external/css-modern/SKILL.md +8 -131
- package/pipeline/skills/shared/external/css-modern/references/code-examples.md +142 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +6 -103
- package/pipeline/skills/shared/external/database-patterns/references/orm-examples.md +112 -0
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +7 -48
- package/pipeline/skills/shared/external/html-semantic/references/code-examples.md +54 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +6 -19
- package/pipeline/skills/shared/external/humanizer/references/voice.md +24 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +13 -170
- package/pipeline/skills/shared/external/ios-accessibility/references/assistive-tech-review.md +224 -0
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +2 -24
- package/pipeline/skills/shared/external/ios-localization/references/code-examples.md +30 -0
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +3 -58
- package/pipeline/skills/shared/external/ios-networking/references/code-examples.md +67 -0
- package/pipeline/skills/shared/external/ios-security/SKILL.md +4 -64
- package/pipeline/skills/shared/external/ios-security/references/code-examples.md +74 -0
- package/pipeline/skills/shared/external/live-activities/SKILL.md +4 -90
- package/pipeline/skills/shared/external/live-activities/references/code-examples.md +108 -0
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -23
- package/pipeline/skills/shared/external/localization-reuse-map/references/project-settings.md +22 -0
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +5 -95
- package/pipeline/skills/shared/external/mapkit-location/references/code-examples.md +117 -0
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +7 -106
- package/pipeline/skills/shared/external/nextjs-app-router/references/app-router-examples.md +124 -0
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +2 -31
- package/pipeline/skills/shared/external/permissionkit/references/code-examples.md +37 -0
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +6 -74
- package/pipeline/skills/shared/external/play-store-review/references/signing-and-policies.md +83 -0
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +8 -125
- package/pipeline/skills/shared/external/push-notifications/references/notification-code.md +176 -0
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +7 -158
- package/pipeline/skills/shared/external/python-patterns/references/python-examples.md +176 -0
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +7 -157
- package/pipeline/skills/shared/external/rest-api-design/references/api-examples.md +175 -0
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +11 -230
- package/pipeline/skills/shared/external/swift-architecture/references/pattern-examples.md +295 -0
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +17 -149
- package/pipeline/skills/shared/external/swift-codable/references/codable-recipes.md +207 -0
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +12 -99
- package/pipeline/skills/shared/external/swift-concurrency/references/code-examples.md +100 -0
- package/pipeline/skills/shared/external/swift-concurrency/references/swift-6-2-additions.md +18 -0
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +9 -78
- package/pipeline/skills/shared/external/swift-formatstyle/references/formatstyle-examples.md +113 -0
- package/pipeline/skills/shared/external/swift-language/SKILL.md +3 -56
- package/pipeline/skills/shared/external/swift-language/references/code-examples.md +65 -0
- package/pipeline/skills/shared/external/swift-testing-pro/SKILL.md +1 -0
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +6 -122
- package/pipeline/skills/shared/external/swiftdata/references/code-examples.md +140 -0
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +12 -139
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/interop-code.md +198 -0
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +9 -81
- package/pipeline/skills/shared/external/tailwind-css/references/code-examples.md +91 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +7 -207
- package/pipeline/skills/shared/external/testing-backend/references/testing-examples.md +225 -0
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +8 -89
- package/pipeline/skills/shared/external/typescript-patterns/references/code-examples.md +100 -0
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +2 -20
- package/pipeline/skills/shared/external/vision-framework/references/code-examples.md +26 -0
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +7 -169
- package/pipeline/skills/shared/external/vue-composition/references/vue-examples.md +187 -0
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +7 -174
- package/pipeline/skills/shared/external/web-accessibility/references/a11y-examples.md +192 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +8 -66
- package/pipeline/skills/shared/external/web-performance/references/code-examples.md +77 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +11 -186
- package/pipeline/skills/shared/external/web-testing/references/testing-examples.md +213 -0
- package/pipeline/skills/skills-index.md +2 -1
- /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/format-and-output.md +0 -0
- /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/publish-and-snapshot.md +0 -0
- /package/pipeline/skills/shared/external/localization-reuse-map/{reference → references}/sources-and-recipes.md +0 -0
|
@@ -9,197 +9,100 @@ metadata:
|
|
|
9
9
|
|
|
10
10
|
# Multi-Agent Sync
|
|
11
11
|
|
|
12
|
-
**
|
|
12
|
+
**One command. Full ecosystem sync. No arguments needed.**
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
It syncs all targets in order, updating only the stale ones, and reports. macOS only (ADR-0012); credential access goes through `~/.claude/lib/credential-store.sh` so no call site names the keychain backend.
|
|
15
15
|
|
|
16
|
-
**Input**: $ARGUMENTS (optional
|
|
16
|
+
**Input**: $ARGUMENTS (optional)
|
|
17
|
+
|
|
18
|
+
| Arg | Meaning |
|
|
19
|
+
|---|---|
|
|
20
|
+
| (none) | Full ecosystem sync, every target |
|
|
21
|
+
| `release` | Full sync + version bump + tag + npm publish + website deploy (Release Flow) |
|
|
22
|
+
| `multi-agent-toolkit` | Run Step 3d only: gate, commit and publish the companion MCP server |
|
|
23
|
+
| `"change description"` | Apply the description to every target at once |
|
|
24
|
+
|
|
25
|
+
## Gotchas
|
|
26
|
+
|
|
27
|
+
- The pre-push gate is timing-sensitive: under heavy load a deadline test fails closed. Re-run it on a quiet machine; never push with `--no-verify`.
|
|
28
|
+
- `npm publish` answering 202 means the registry is still processing. Verify with the registry's dist-tags before moving `required`, which is asked for every release.
|
|
29
|
+
- The installed tree is localized (Turkish descriptions, `model: opus` while fable is off). Normalize to English and `model: fable` before copying into the repo.
|
|
30
|
+
- Synced shell runs on BSD userland: BSD grep has no Perl-regex flag, and `sed` has no `\b` or `\|`. A pattern that silently matches nothing reads as "clean".
|
|
17
31
|
|
|
18
32
|
## Targets
|
|
19
33
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
| 3 | multi-agent-pipeline repo | `~/multi-agent-pipeline/pipeline/` | <- from Claude (genericized) |
|
|
26
|
-
| 4 | Website | `{owner}/{website-host}` | <- version + features |
|
|
27
|
-
| 5 | multi-agent-toolkit MCP server | resolved from `prefs.global.devToolkit` or the `mcpServers` registration | own repo: gate, commit, publish |
|
|
34
|
+
Claude Code (source of truth) -> Copilot CLI, Codex CLI (path-rewritten), the
|
|
35
|
+
pipeline repo (genericized), the website (`{owner}/{website-host}`) and the
|
|
36
|
+
multi-agent-toolkit MCP server (its own repo). Paths, directions, the shared
|
|
37
|
+
Claude <-> Copilot sections and the token table: `$HOME/.claude/multi-agent-refs/sync/overview.md`; read it
|
|
38
|
+
before Step 1.5.
|
|
28
39
|
|
|
29
|
-
## Default Behavior (no
|
|
40
|
+
## Default Behavior (no arguments)
|
|
30
41
|
|
|
31
|
-
Run
|
|
42
|
+
Run every step automatically:
|
|
32
43
|
|
|
33
44
|
```
|
|
34
|
-
Step 0: DOCTOR
|
|
35
|
-
Step 1: DETECT
|
|
36
|
-
Step 2: COPILOT Claude Code -> Copilot CLI (instructions +
|
|
37
|
-
Step 2b: CODEX Claude Code -> Codex CLI (
|
|
38
|
-
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub)
|
|
39
|
-
Step
|
|
45
|
+
Step 0: DOCTOR doctor.mjs - exit 2 or 4 stops the sync
|
|
46
|
+
Step 1.5: DETECT Compare timestamps, find stale targets
|
|
47
|
+
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 70 sub-command skills)
|
|
48
|
+
Step 2b: CODEX Claude Code -> Codex CLI (router skill + specs as refs + agent TOML)
|
|
49
|
+
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
|
|
50
|
+
Step 3c: PLUGINS shared/external -> multi-agent-plugins marketplace (rebuild, bump, push)
|
|
51
|
+
Step 3d: DEV-TOOLKIT companion MCP server -> detect movement, run the ship gates, commit + publish
|
|
52
|
+
Step 3e: OFFICE panel page is current, installed copies match it, toolkit version recorded
|
|
40
53
|
Step 4: WEBSITE Version + phase/model counts -> {website-host} (i18n + projects.ts)
|
|
41
54
|
Step 5: Commit Commit + push all changed repos
|
|
42
|
-
Step 6: Report
|
|
55
|
+
Step 6: Report Synced targets, changed files, deploy status, multi-agent-toolkit version
|
|
43
56
|
```
|
|
44
57
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
If nothing is stale -> report "All targets up to date" and stop.
|
|
58
|
+
If nothing is stale → report "All targets up to date" and stop.
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
| Input | Behavior |
|
|
52
|
-
|-------|----------|
|
|
53
|
-
| (no argument) | Full ecosystem sync (default) |
|
|
54
|
-
| `release` | Full sync + version bump + tag + npm publish + website deploy |
|
|
55
|
-
| `multi-agent-toolkit` | Run Step 3d only: gate, commit and publish the companion MCP server |
|
|
56
|
-
| `"change description"` | Apply the description to ALL targets at once |
|
|
60
|
+
Step 0 gate rules and why: `features/doctor.md`.
|
|
57
61
|
|
|
62
|
+
---
|
|
58
63
|
|
|
59
64
|
## Sync rules
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- `copilot-instructions.md`: general development instructions + pipeline summary section
|
|
65
|
-
- `multi-agent-pipeline/pipeline/`: generic open-source version (NO personal data)
|
|
66
|
-
3. **Sync shared sections** (Claude <-> Copilot):
|
|
67
|
-
- Pipeline entries table (base / :autopilot)
|
|
68
|
-
- Project detection (URL-based + cwd-based)
|
|
69
|
-
- Figma pipeline flow
|
|
70
|
-
- Git conventions (author, branch, commit format)
|
|
71
|
-
- Keychain management (registry, naming convention, multi-agent pattern)
|
|
72
|
-
4. **Do not duplicate** - Summary in Copilot, full spec in Claude. Preserve this distinction.
|
|
73
|
-
5. **Report** - Show a short diff summary after the sync
|
|
74
|
-
|
|
75
|
-
## Pipeline Repo Sync Rules (CRITICAL)
|
|
76
|
-
|
|
77
|
-
1. **Source**: `~/.claude/commands/multi-agent/` + `~/.claude/multi-agent-refs/` + `~/.claude/agents/` + `~/.claude/lib/`
|
|
78
|
-
2. **Target**: `~/multi-agent-pipeline/pipeline/`
|
|
79
|
-
3. **Genericization** (must be applied BEFORE writing to the target):
|
|
80
|
-
- Jira project key (`prefs.global.defaultJiraKey`) -> `{JIRA_KEY}`, `PROJ` in examples
|
|
81
|
-
- Personal names/emails -> generic placeholder
|
|
82
|
-
- Branch names -> `develop`
|
|
83
|
-
- Project names -> `my-app`
|
|
84
|
-
- `{JIRA_HOST}`, `{BITBUCKET_HOST}`, `{CONFLUENCE_HOST}`, `{CORP_DOMAIN}` stay as-is
|
|
85
|
-
- **Verify**: scan for personal/corporate data inside pipeline/ with `grep` -> 0 results
|
|
86
|
-
4. **File mapping**:
|
|
87
|
-
```
|
|
88
|
-
~/.claude/commands/multi-agent/ -> pipeline/commands/multi-agent/
|
|
89
|
-
~/.claude/multi-agent-refs/ -> pipeline/multi-agent-refs/ (refs + pickers, non-command)
|
|
90
|
-
~/.claude/commands/sim-test.md -> pipeline/commands/sim-test.md
|
|
91
|
-
~/.claude/agents/*.md -> pipeline/agents/
|
|
92
|
-
```
|
|
93
|
-
5. **Files NOT synced** (local-only, may contain personal data):
|
|
94
|
-
- `~/.claude/multi-agent-preferences.json`
|
|
95
|
-
- `~/.claude/CLAUDE.md`, `~/.claude/rules/`, `~/.claude/knowledge/`
|
|
96
|
-
- `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh` and `build-stack-plugins.mjs` (generic, synced)
|
|
97
|
-
- Step 3c (PLUGINS): rebuild the `{owner}/multi-agent-plugins` marketplace from `shared/external` via `build-stack-plugins.mjs` (bumps changed plugins' patch version), then commit + push the plugins repo. On any change also verify help + README freshness: every plugin registers `./skills/tools/help` in plugin.json, `tools/bump.py --check` shows no DRIFT, `tools/validate.py` clean (CHANGELOG entry per bumped version), and pipeline help/READMEs reflect any command-surface change from Step 3
|
|
98
|
-
- `~/.claude/settings.json`
|
|
99
|
-
- `~/.claude/multi-agent-refs/registries/` - the installer copies gate registries there from `pipeline/skills/shared/external`; the repo already holds the source
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
## Codex Sync (Step 2b)
|
|
103
|
-
|
|
104
|
-
This step does **not** hand-copy files. The Codex tree is a *transform* of the Claude
|
|
105
|
-
tree, not a mirror: the sub-command specs become reference files (Codex silently
|
|
106
|
-
truncates its skills block - see `cross-cli-contract.md` 2.6), every reference to a
|
|
107
|
-
CLI-owned tree is retargeted (`agents/<persona>.md` becomes `.toml`, the dispatcher
|
|
108
|
-
becomes the router skill), the personas under `agents/` are regenerated as TOML with a model +
|
|
109
|
-
reasoning-effort map, and shared state (`logs/`, prefs, `knowledge/`) is deliberately
|
|
110
|
-
left under `~/.claude`.
|
|
111
|
-
|
|
112
|
-
That transform lives in `install/codex.mjs` and is gate-locked by
|
|
113
|
-
`smoke-codex-install.sh`. Describing it again in prose would give the pipeline two
|
|
114
|
-
definitions of the same thing, and the prose one would rot. So the step runs the
|
|
115
|
-
installer:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
cd "$HOME/multi-agent-pipeline" && node install.js --codex
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Verify:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
ls -1 "$HOME/.codex/skills" | grep -c '^multi-agent$' # want 1
|
|
125
|
-
find "$HOME/.codex/multi-agent-refs/commands" -name SKILL.md | wc -l # want the command count
|
|
126
|
-
grep -rhoE '(\$HOME|~)/\.claude/(agents|scripts|lib|schemas|commands|multi-agent-refs|rules)' \
|
|
127
|
-
"$HOME/.codex/skills" "$HOME/.codex/multi-agent-refs" | sort -u # want empty
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
MCP is registered by the installer via `codex mcp add multi-agent-toolkit` (idempotent,
|
|
131
|
-
skipped with a warning when `codex` is absent). Never hand-edit
|
|
132
|
-
`~/.codex/config.toml` - Codex owns it. Run this AFTER the REPO step, since the
|
|
133
|
-
installer reads the repo tree.
|
|
66
|
+
Read every target's current state before changing anything; keep each target's
|
|
67
|
+
own format; summary in Copilot, full spec in Claude, never duplicated; finish
|
|
68
|
+
with a short diff summary.
|
|
134
69
|
|
|
135
70
|
---
|
|
136
71
|
|
|
137
|
-
##
|
|
138
|
-
|
|
139
|
-
The companion MCP server (`multi-agent-toolkit-mcp`) is its own repo with its own registry. Pipeline skills call its tools and several declare a minimum version, so when it moves it has to ship.
|
|
140
|
-
|
|
141
|
-
**Resolution**: identical to `multi-agent-refactor` Step 0c - `prefs.global.devToolkit` first, then the `mcpServers` registration, then skip.
|
|
142
|
-
|
|
143
|
-
**Detect movement**: dirty working tree, unpushed commits, or no `v<version>` tag for the version in `package.json`. Nothing moved -> report "up to date" and continue.
|
|
144
|
-
|
|
145
|
-
**Ship gates** (a failure aborts this step only, with file + line; the rest of the sync continues).
|
|
146
|
-
When the toolkit ships its own gate script (`npm run gates` / `scripts/gates.sh`), run that instead of the list below - the repo owns the definition, this skill owns the requirement. The list is the fallback, and the coverage the script must have:
|
|
72
|
+
## Step procedures (read each file before its step)
|
|
147
73
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
74
|
+
| Step | Procedure |
|
|
75
|
+
|---|---|
|
|
76
|
+
| 2b CODEX (runs after Step 3) | `$HOME/.claude/multi-agent-refs/sync/codex.md` |
|
|
77
|
+
| 3 REPO | `$HOME/.claude/multi-agent-refs/sync/repo.md` |
|
|
78
|
+
| 3c PLUGINS | `$HOME/.claude/multi-agent-refs/sync/stack-plugins.md` |
|
|
79
|
+
| 3d DEV-TOOLKIT (and `multi-agent-toolkit` arg) | `$HOME/.claude/multi-agent-refs/sync/dev-toolkit.md` |
|
|
80
|
+
| 3e OFFICE (also release step 9c) | `$HOME/.claude/multi-agent-refs/sync/office.md` |
|
|
155
81
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
**Ship**: commit with that repo's own convention, tag `v<version>`, push with `--tags`, then publish to the registry from `publishConfig` using a throwaway userconfig - never edit `~/.npmrc`, never a bare `npm publish`. The token depends on the registry AND on the package scope: the registry picks the credential type, the scope picks the account. `npm.pkg.github.com` needs a **Classic** GitHub PAT with `write:packages`; `registry.npmjs.org` needs the `npm` key. Resolving on host alone misroutes on any machine with a work and a personal GitHub identity - prefer a scope-specific mapping (`github_<scope>`) and fall back to the generic `github` key only when there is one identity.
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
NPMRC=$(mktemp); trap 'rm -f "$NPMRC"' EXIT
|
|
162
|
-
REG=$(node -p "require('./package.json').publishConfig?.registry || 'https://registry.npmjs.org'")
|
|
163
|
-
HOST=${REG#https://}; HOST=${HOST%/}
|
|
164
|
-
SCOPE=$(node -p "(require('./package.json').name.match(/^@([^/]+)/)||[])[1] || ''")
|
|
165
|
-
case "$HOST" in
|
|
166
|
-
npm.pkg.github.com*) KEY=github; [ -n "$SCOPE" ] && KEY="github_$SCOPE" ;;
|
|
167
|
-
*) KEY=npm ;;
|
|
168
|
-
esac
|
|
169
|
-
# Fall back to the generic key when no scope-specific mapping exists.
|
|
170
|
-
bash "$HOME/.copilot/lib/credential-store.sh" get "$KEY" >/dev/null 2>&1 || KEY=github
|
|
171
|
-
TOKEN=$(bash "$HOME/.claude/lib/credential-store.sh" get "$KEY")
|
|
172
|
-
[ -n "$TOKEN" ] || echo "ABORT: no '$KEY' token - onboard it via /multi-agent:setup before publishing"
|
|
173
|
-
printf '%s\n' "registry=$REG" "//$HOST/:_authToken=$TOKEN" > "$NPMRC"
|
|
174
|
-
npm publish --userconfig "$NPMRC"
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**Approval**: outside autopilot and outside `release`, ask first: commit + push / commit + push + publish / skip. Never ship unapproved band-E work from `multi-agent-refactor` silently.
|
|
82
|
+
Hard rules for Step 3, whatever `repo.md` adds:
|
|
178
83
|
|
|
84
|
+
- Genericize BEFORE writing to `~/multi-agent-pipeline/pipeline/`; the personal/corporate data scan must return 0 results.
|
|
85
|
+
- Never sync a `local-only: true` SKILL.md, local config, or `~/.claude/office/`. A leaked wrapper, sidecar or localized description aborts the sync.
|
|
86
|
+
- Synced shell follows the BSD / bash 3.2 contract in `repo.md` (`grep -P` banned, keychain I/O only via `credential-store.sh`). A failed smoke gate aborts the push; fix the `~/.claude/` source, re-sync.
|
|
179
87
|
|
|
180
88
|
## Website Sync (Step 4)
|
|
181
89
|
|
|
182
|
-
Propagate version, phase and model counts and feature descriptions to the website.
|
|
183
|
-
|
|
184
90
|
```bash
|
|
185
91
|
gh auth switch --user {owner}
|
|
186
92
|
WEBSITE_DIR="$HOME/{website-host}"
|
|
187
|
-
[ ! -d "$WEBSITE_DIR" ] && gh repo clone {owner}/website "$WEBSITE_DIR"
|
|
93
|
+
[ ! -d "$WEBSITE_DIR" ] && gh repo clone {owner}/{website-host} "$WEBSITE_DIR"
|
|
188
94
|
cd "$WEBSITE_DIR" && git pull origin main
|
|
189
95
|
```
|
|
190
96
|
|
|
191
|
-
|
|
192
|
-
|-------|--------------|
|
|
193
|
-
| `src/lib/i18n.tsx` | Phase count, model count, feature descriptions (EN + TR) |
|
|
194
|
-
| `src/data/projects.ts` | Version number, tagline, description, feature list |
|
|
97
|
+
Files: `src/lib/i18n.tsx` (counts, feature copy EN + TR) and `src/data/projects.ts` (version, features); detail in `overview.md`.
|
|
195
98
|
|
|
196
99
|
```bash
|
|
197
|
-
#
|
|
198
|
-
# keeps the old version. {identity} is the one routed to {owner}, not the run's own.
|
|
100
|
+
# {identity} is the one routed to {owner}, not the run's own.
|
|
199
101
|
# Why, signature, recovery: `$HOME/.claude/multi-agent-refs/website-deploy.md`.
|
|
200
102
|
bash "$HOME/.claude/scripts/website-deploy-commit.sh" "{identity.name}" "{identity.email}" "{VERSION}" "$WEBSITE_DIR"
|
|
201
103
|
```
|
|
202
104
|
|
|
105
|
+
---
|
|
203
106
|
|
|
204
107
|
## Release Flow
|
|
205
108
|
|
|
@@ -207,9 +110,8 @@ When invoked with the `release` argument:
|
|
|
207
110
|
|
|
208
111
|
```
|
|
209
112
|
1. REPO Claude Code -> pipeline repo (genericized)
|
|
210
|
-
2. VERIFY Personal data scan -> 0 results
|
|
211
|
-
3. LINT + TEST ESLint + smoke tests (
|
|
212
|
-
it with sign-skills.sh whenever a SKILL.md moved)
|
|
113
|
+
2. VERIFY Personal data scan -> 0 results; config-hygiene scan (scan-agent-config.sh) -> 0 HIGH
|
|
114
|
+
3. LINT + TEST ESLint + smoke tests (re-sign .skill-manifest.json with sign-skills.sh when a SKILL.md moved)
|
|
213
115
|
4. VERSION package.json version bump (patch/minor/major)
|
|
214
116
|
5. Commit + TAG git commit + git tag v{VERSION}
|
|
215
117
|
6. PUSH git push --tags; publish is local (release.yml off)
|
|
@@ -217,84 +119,38 @@ When invoked with the `release` argument:
|
|
|
217
119
|
8. WEBSITE Version + features -> {website-host} (maintainer identity, build verified Ready)
|
|
218
120
|
9. COPILOT Copilot CLI instructions + skills sync
|
|
219
121
|
9b. CODEX Codex CLI router skill + refs + agent TOML (node install.js --codex)
|
|
122
|
+
9c. OFFICE Step 3e: the installed panel matches the release
|
|
220
123
|
10. Report Summary: version, touched repos, deploy status
|
|
221
124
|
```
|
|
222
125
|
|
|
126
|
+
---
|
|
223
127
|
|
|
224
128
|
## Sub-Command Sync (Claude Code <-> Copilot CLI Skills)
|
|
225
129
|
|
|
226
|
-
|
|
130
|
+
Claude <-> Copilot axis only; Codex takes Step 2b (`cross-cli-contract.md` 2.6).
|
|
227
131
|
|
|
228
|
-
|
|
229
|
-
|-------------|-------------|
|
|
230
|
-
| `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
|
|
132
|
+
`~/.claude/commands/multi-agent/{cmd}/SKILL.md` <-> `~/.copilot/skills/multi-agent-{cmd}/SKILL.md`.
|
|
231
133
|
|
|
232
|
-
**
|
|
134
|
+
**70 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
|
|
233
135
|
|
|
234
136
|
```
|
|
235
|
-
analysis, analysis-jira, analysis-resolve, autopilot, autopilot-off,
|
|
236
|
-
autopilot-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
security-review, serve, setup, stack, status, steer, store-ready, sync, test, test-accessibility,
|
|
244
|
-
test-dark-mode, test-dynamic-type, test-gen, test-screenshots, testflight-validation,
|
|
245
|
-
uninstall, update
|
|
137
|
+
analysis, analysis-jira, analysis-resolve, autopilot, autopilot-off, autopilot-on,
|
|
138
|
+
autopilot-status, bug-bash, build-optimize, channels, complaint-analysis, create-jira,
|
|
139
|
+
design-check, diff-explain, doctor, estimate, feedback, forget, garbage-collect, graph, help,
|
|
140
|
+
ios-coding-standard, issue, jira, kill, language, log,
|
|
141
|
+
manual-test, model, office-off, office-on, office-pair, office-status, postmortem, prune-logs, prune-prompts, purge, refactor, research, resume, review, review-analysis, review-issue, review-jira, route-off, route-on, route-status,
|
|
142
|
+
routines, save, scaffold, scan, scenario-audit, search, security-review, serve, setup, stack, status, steer, store-ready, sync, test,
|
|
143
|
+
test-accessibility, test-dark-mode, test-dynamic-type, test-gen, test-screenshots,
|
|
144
|
+
testflight-validation, uninstall, update
|
|
246
145
|
```
|
|
247
146
|
|
|
248
|
-
**NOT synced**:
|
|
147
|
+
**NOT synced**: `$HOME/.claude/multi-agent-refs/*` - lazy-load references, Claude Code specific
|
|
249
148
|
|
|
250
|
-
|
|
251
|
-
**Copilot -> Claude**: Simplify the frontmatter (`description` + `allowed-tools`), add `$ARGUMENTS`
|
|
149
|
+
Frontmatter conversion between the two forms: `overview.md`, "Sub-command paths".
|
|
252
150
|
|
|
151
|
+
---
|
|
253
152
|
|
|
254
153
|
## Keychain Token Access
|
|
255
154
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
| `gh` CLI (personal) | `{owner}` gh auth (Keychain) |
|
|
259
|
-
| `gh` CLI (work) | `${USER}_{work-gh-alias}` gh auth (Keychain) |
|
|
260
|
-
| npm publish | `NODE_AUTH_TOKEN` - `GITHUB_TOKEN` in CI, Keychain PAT locally |
|
|
261
|
-
| multi-agent-toolkit publish (Step 3d) | scope-resolved key (`github_<scope>`, else `github`, else `npm`) -> throwaway `--userconfig`, registry from that repo's `publishConfig` |
|
|
262
|
-
|
|
263
|
-
```bash
|
|
264
|
-
gh auth switch --user {owner} # for personal repos
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
## Pre-flight the token scope
|
|
269
|
-
|
|
270
|
-
GitHub reports a token's scopes on any authenticated request, so check before
|
|
271
|
-
uploading instead of reading it out of a 403:
|
|
272
|
-
|
|
273
|
-
```bash
|
|
274
|
-
curl -sI -H "Authorization: token $TOKEN" https://api.github.com/user \
|
|
275
|
-
| grep -i '^x-oauth-scopes:' | grep -q 'write:packages'
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
Candidate order for `npm.pkg.github.com`, because storage location and scope are
|
|
279
|
-
not correlated: `github_<scope>` from the mapping, then `gh auth token -u <scope>`
|
|
280
|
-
(gh's own OAuth token often carries `write:packages` when a hand-made PAT does
|
|
281
|
-
not), then the generic `github` key only on a single-identity machine. Take the
|
|
282
|
-
first candidate whose scopes include `write:packages` AND whose login matches the
|
|
283
|
-
package scope. If none qualifies, stop before publishing and report each candidate
|
|
284
|
-
with the login it resolved to and the scope it was missing - that is the
|
|
285
|
-
actionable output, not a 403 body.
|
|
286
|
-
|
|
287
|
-
## Publish 403s: two causes, two fixes
|
|
288
|
-
|
|
289
|
-
Neither message says "wrong token" plainly, and they need opposite responses:
|
|
290
|
-
|
|
291
|
-
- `Unauthorized: As an Enterprise Managed User, you cannot access this content` -
|
|
292
|
-
the resolved token belongs to a corporate EMU account, which cannot publish to a
|
|
293
|
-
personal scope at all. No scope grant fixes this; map the personal account's PAT
|
|
294
|
-
under `github_<scope>`.
|
|
295
|
-
- `The token provided does not match expected scopes` - right account, missing
|
|
296
|
-
permission. Regenerate as a **Classic** PAT with `write:packages`
|
|
297
|
-
(plus `repo` for a private package) and re-onboard through setup.
|
|
298
|
-
|
|
299
|
-
Always report which of the two occurred. "Permission denied" alone sends the user
|
|
300
|
-
to regenerate a token that was never the problem.
|
|
155
|
+
Token sources per operation: `overview.md`. Personal repos run under
|
|
156
|
+
`gh auth switch --user {owner}`; tokens are read only through `credential-store.sh`.
|
|
@@ -58,39 +58,12 @@ The user must grant access. The app may ask up front, or AlarmKit will prompt
|
|
|
58
58
|
the first time something is scheduled. If neither prompt ends in approval, no
|
|
59
59
|
alarm is scheduled and nothing will ring.
|
|
60
60
|
|
|
61
|
-
```swift
|
|
62
|
-
import AlarmKit
|
|
63
|
-
|
|
64
|
-
func ensureAlarmAccess() async -> Bool {
|
|
65
|
-
let center = AlarmManager.shared
|
|
66
|
-
switch center.authorizationState {
|
|
67
|
-
case .authorized:
|
|
68
|
-
return true
|
|
69
|
-
case .denied:
|
|
70
|
-
return false
|
|
71
|
-
case .notDetermined:
|
|
72
|
-
let answer = try? await center.requestAuthorization()
|
|
73
|
-
return answer == .authorized
|
|
74
|
-
@unknown default:
|
|
75
|
-
return false
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
func watchAlarmAccess(onChange: @escaping (Bool) -> Void) async {
|
|
80
|
-
for await state in AlarmManager.shared.authorizationUpdates {
|
|
81
|
-
switch state {
|
|
82
|
-
case .authorized: onChange(true)
|
|
83
|
-
case .denied, .notDetermined: onChange(false)
|
|
84
|
-
@unknown default: onChange(false)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
61
|
`AlarmManager.AuthorizationState` has three cases: `.notDetermined`,
|
|
91
62
|
`.denied` and `.authorized`. `authorizationState` is a synchronous read;
|
|
92
63
|
`authorizationUpdates` is an async sequence of changes.
|
|
93
64
|
|
|
65
|
+
Code for this section: [AlarmKit code](references/alarmkit-code.md).
|
|
66
|
+
|
|
94
67
|
## Alarm or timer?
|
|
95
68
|
|
|
96
69
|
| | `.alarm` | `.timer` |
|
|
@@ -126,38 +99,6 @@ let schoolRun = Alarm.Schedule.relative(.init(time: sixAM, repeats: .weekly(clas
|
|
|
126
99
|
|
|
127
100
|
### Configuring and scheduling
|
|
128
101
|
|
|
129
|
-
```swift
|
|
130
|
-
import AlarmKit
|
|
131
|
-
import SwiftUI
|
|
132
|
-
|
|
133
|
-
struct ShiftInfo: AlarmMetadata {
|
|
134
|
-
var shiftName: String
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
@available(iOS 26.1, *)
|
|
138
|
-
func scheduleShiftAlarm() async throws -> Alarm {
|
|
139
|
-
let dawn = Alarm.Schedule.Relative.Time(hour: 5, minute: 30)
|
|
140
|
-
let alert = AlarmPresentation.Alert(
|
|
141
|
-
title: "Early shift",
|
|
142
|
-
secondaryButton: AlarmButton(text: "Later", textColor: .white, systemImageName: "zzz"),
|
|
143
|
-
secondaryButtonBehavior: .countdown
|
|
144
|
-
)
|
|
145
|
-
let attributes = AlarmAttributes(
|
|
146
|
-
presentation: AlarmPresentation(alert: alert),
|
|
147
|
-
metadata: ShiftInfo(shiftName: "Warehouse A"),
|
|
148
|
-
tintColor: .teal
|
|
149
|
-
)
|
|
150
|
-
let config = AlarmManager.AlarmConfiguration(
|
|
151
|
-
countdownDuration: Alarm.CountdownDuration(preAlert: nil, postAlert: 9 * 60),
|
|
152
|
-
schedule: .relative(.init(time: dawn, repeats: .never)),
|
|
153
|
-
attributes: attributes,
|
|
154
|
-
sound: .default
|
|
155
|
-
)
|
|
156
|
-
let center = AlarmManager.shared
|
|
157
|
-
return try await center.schedule(id: UUID(), configuration: config)
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
102
|
Here `postAlert` is what makes the secondary button a snooze: pressing it
|
|
162
103
|
starts a nine-minute countdown and then rings again.
|
|
163
104
|
|
|
@@ -170,6 +111,8 @@ right:
|
|
|
170
111
|
`secondaryButtonBehavior: .countdown` plus `CountdownDuration.postAlert`.
|
|
171
112
|
Pass one only with `.custom` behavior or when the app must do its own work.
|
|
172
113
|
|
|
114
|
+
Code for this section: [AlarmKit code](references/alarmkit-code.md).
|
|
115
|
+
|
|
173
116
|
### Lifecycle and transitions
|
|
174
117
|
|
|
175
118
|
The normal path is scheduled, then countdown, then alerting. From countdown
|
|
@@ -189,30 +132,7 @@ anywhere.
|
|
|
189
132
|
|
|
190
133
|
A timer rings once a duration has passed and always shows its countdown.
|
|
191
134
|
|
|
192
|
-
|
|
193
|
-
import AlarmKit
|
|
194
|
-
import SwiftUI
|
|
195
|
-
|
|
196
|
-
struct BrewInfo: AlarmMetadata {
|
|
197
|
-
var blend: String
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
@available(iOS 26.1, *)
|
|
201
|
-
func startSteepTimer() async throws {
|
|
202
|
-
let presentation = AlarmPresentation(
|
|
203
|
-
alert: .init(title: "Tea is ready"),
|
|
204
|
-
countdown: .init(title: "Steeping"),
|
|
205
|
-
paused: .init(title: "Steeping paused",
|
|
206
|
-
resumeButton: AlarmButton(text: "Resume", textColor: .white, systemImageName: "play.fill"))
|
|
207
|
-
)
|
|
208
|
-
let attributes = AlarmAttributes(presentation: presentation,
|
|
209
|
-
metadata: BrewInfo(blend: "Sencha"),
|
|
210
|
-
tintColor: .green)
|
|
211
|
-
let threeMinutes = AlarmManager.AlarmConfiguration.timer(duration: 180, attributes: attributes, sound: .default)
|
|
212
|
-
let center = AlarmManager.shared
|
|
213
|
-
_ = try await center.schedule(id: UUID(), configuration: threeMinutes)
|
|
214
|
-
}
|
|
215
|
-
```
|
|
135
|
+
Code for this section: [AlarmKit code](references/alarmkit-code.md).
|
|
216
136
|
|
|
217
137
|
### CountdownDuration
|
|
218
138
|
|
|
@@ -292,46 +212,17 @@ the alerting UI from it; the widget extension may draw countdown and paused.
|
|
|
292
212
|
| `AlarmPresentation.Countdown(title:pauseButton:)` | counting down | no |
|
|
293
213
|
| `AlarmPresentation.Paused(title:resumeButton:)` | paused | no |
|
|
294
214
|
|
|
295
|
-
Combine them with `AlarmPresentation(alert:countdown:paused:)
|
|
215
|
+
Combine them with `AlarmPresentation(alert:countdown:paused:)`.
|
|
296
216
|
|
|
297
|
-
|
|
298
|
-
import AlarmKit
|
|
299
|
-
import SwiftUI
|
|
300
|
-
|
|
301
|
-
@available(iOS 26.1, *)
|
|
302
|
-
func workoutPresentation() -> AlarmPresentation {
|
|
303
|
-
let again = AlarmButton(text: "Again", textColor: .white, systemImageName: "repeat")
|
|
304
|
-
let hold = AlarmButton(text: "Hold", textColor: .orange, systemImageName: "pause.fill")
|
|
305
|
-
let go = AlarmButton(text: "Go", textColor: .orange, systemImageName: "play.fill")
|
|
306
|
-
return AlarmPresentation(
|
|
307
|
-
alert: .init(title: "Rest over", secondaryButton: again, secondaryButtonBehavior: .countdown),
|
|
308
|
-
countdown: .init(title: "Resting", pauseButton: hold),
|
|
309
|
-
paused: .init(title: "Rest on hold", resumeButton: go)
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
```
|
|
217
|
+
Code for this section: [AlarmKit code](references/alarmkit-code.md).
|
|
313
218
|
|
|
314
219
|
### Metadata
|
|
315
220
|
|
|
316
|
-
```swift
|
|
317
|
-
import AlarmKit
|
|
318
|
-
import SwiftUI
|
|
319
|
-
|
|
320
|
-
struct PlantInfo: AlarmMetadata { var plantName: String; var litres: Double }
|
|
321
|
-
struct NoAlarmData: AlarmMetadata {}
|
|
322
|
-
|
|
323
|
-
@available(iOS 26.1, *)
|
|
324
|
-
func plantAttributes() -> (AlarmAttributes<PlantInfo>, AlarmAttributes<NoAlarmData>) {
|
|
325
|
-
let look = AlarmPresentation(alert: .init(title: "Water the fern"))
|
|
326
|
-
let withData = AlarmAttributes(presentation: look, metadata: PlantInfo(plantName: "Fern", litres: 0.5), tintColor: .mint)
|
|
327
|
-
let plain = AlarmAttributes<NoAlarmData>(presentation: look, metadata: nil, tintColor: .mint)
|
|
328
|
-
return (withData, plain)
|
|
329
|
-
}
|
|
330
|
-
```
|
|
331
|
-
|
|
332
221
|
When there is nothing to carry, declare an empty type that conforms to
|
|
333
222
|
`AlarmMetadata` and pass `metadata: nil`.
|
|
334
223
|
|
|
224
|
+
Code for this section: [AlarmKit code](references/alarmkit-code.md).
|
|
225
|
+
|
|
335
226
|
### AlarmPresentationState
|
|
336
227
|
|
|
337
228
|
`AlarmPresentationState` is the alarm Live Activity's `ContentState`, owned and
|
|
@@ -398,50 +289,7 @@ Setup stays with what Apple documents: `NSAlarmKitUsageDescription` and
|
|
|
398
289
|
`AlarmManager` authorization. Do not require extra keys or a
|
|
399
290
|
`com.apple.developer.alarmkit` entitlement unless a current Apple source says so.
|
|
400
291
|
|
|
401
|
-
|
|
402
|
-
import ActivityKit
|
|
403
|
-
import AlarmKit
|
|
404
|
-
import SwiftUI
|
|
405
|
-
import WidgetKit
|
|
406
|
-
|
|
407
|
-
struct CoachInfo: AlarmMetadata {
|
|
408
|
-
var drill: String
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
struct CoachAlarmWidget: Widget {
|
|
412
|
-
var body: some WidgetConfiguration {
|
|
413
|
-
ActivityConfiguration(for: AlarmAttributes<CoachInfo>.self) { context in
|
|
414
|
-
Text(context.attributes.metadata?.drill ?? "Timer")
|
|
415
|
-
.padding()
|
|
416
|
-
} dynamicIsland: { context in
|
|
417
|
-
DynamicIsland {
|
|
418
|
-
DynamicIslandExpandedRegion(.center) {
|
|
419
|
-
let heading = context.attributes.presentation.alert.title
|
|
420
|
-
Text(heading)
|
|
421
|
-
}
|
|
422
|
-
DynamicIslandExpandedRegion(.bottom) {
|
|
423
|
-
if case .countdown(let run) = context.state.mode {
|
|
424
|
-
Text(timerInterval: Date.now...run.fireDate, countsDown: true)
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
} compactLeading: {
|
|
428
|
-
Image(systemName: "alarm.fill")
|
|
429
|
-
} compactTrailing: {
|
|
430
|
-
Image(systemName: "alarm.fill")
|
|
431
|
-
} minimal: {
|
|
432
|
-
Image(systemName: "alarm.fill")
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
@main
|
|
439
|
-
struct CoachWidgets: WidgetBundle {
|
|
440
|
-
var body: some Widget {
|
|
441
|
-
CoachAlarmWidget()
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
```
|
|
292
|
+
Code for this section: [AlarmKit code](references/alarmkit-code.md).
|
|
445
293
|
|
|
446
294
|
## Common mistakes
|
|
447
295
|
|
|
@@ -485,6 +333,7 @@ struct CoachWidgets: WidgetBundle {
|
|
|
485
333
|
|
|
486
334
|
## References
|
|
487
335
|
|
|
336
|
+
- [AlarmKit code](references/alarmkit-code.md): open for the code behind authorization, scheduling, countdown timers, presentation, metadata and the Live Activity widget.
|
|
488
337
|
- [AlarmKit patterns](references/alarmkit-patterns.md) - complete alarm and timer flows, authorization manager, state store, widget extension, recurrence, snooze and custom actions, Info.plist, errors
|
|
489
338
|
- [AlarmKit](https://developer.apple.com/documentation/alarmkit)
|
|
490
339
|
- [AlarmManager](https://developer.apple.com/documentation/alarmkit/alarmmanager)
|