@olegkoval/agent-skills 1.22.0 โ†’ 1.24.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.
Files changed (38) hide show
  1. package/.claude-plugin/plugin.json +4 -2
  2. package/.cursor-plugin/index.json +10 -0
  3. package/.grok-plugin/index.json +10 -0
  4. package/.kiro/steering/garmin-watchface.md +7 -0
  5. package/.windsurf/rules/garmin-watchface.md +7 -0
  6. package/README.md +3 -1
  7. package/catalog/skills.json +44 -0
  8. package/package.json +1 -1
  9. package/packages/software-development/ci-fix-loop/SKILL.md +202 -0
  10. package/packages/software-development/ci-fix-loop/adapters/claude/plugin.json +5 -0
  11. package/packages/software-development/ci-fix-loop/adapters/claude/skills/ci-fix-loop/SKILL.md +203 -0
  12. package/packages/software-development/ci-fix-loop/adapters/codex/README.md +20 -0
  13. package/packages/software-development/ci-fix-loop/adapters/cursor/plugin.json +6 -0
  14. package/packages/software-development/ci-fix-loop/adapters/cursor/skills/ci-fix-loop/SKILL.md +203 -0
  15. package/packages/software-development/ci-fix-loop/adapters/grok/plugin.json +6 -0
  16. package/packages/software-development/ci-fix-loop/adapters/grok/skills/ci-fix-loop/SKILL.md +203 -0
  17. package/packages/software-development/pr-description-writer/SKILL.md +152 -0
  18. package/packages/software-development/pr-description-writer/adapters/claude/plugin.json +5 -0
  19. package/packages/software-development/pr-description-writer/adapters/claude/skills/pr-description-writer/SKILL.md +153 -0
  20. package/packages/software-development/pr-description-writer/adapters/codex/README.md +19 -0
  21. package/packages/software-development/pr-description-writer/adapters/cursor/plugin.json +6 -0
  22. package/packages/software-development/pr-description-writer/adapters/cursor/skills/pr-description-writer/SKILL.md +153 -0
  23. package/packages/software-development/pr-description-writer/adapters/grok/plugin.json +6 -0
  24. package/packages/software-development/pr-description-writer/adapters/grok/skills/pr-description-writer/SKILL.md +153 -0
  25. package/packages/wearables/garmin-watchface/SKILL.md +7 -0
  26. package/packages/wearables/garmin-watchface/adapters/claude/skills/garmin-watchface/SKILL.md +7 -0
  27. package/packages/wearables/garmin-watchface/adapters/claude/skills/garmin-watchface/references/publishing.md +145 -0
  28. package/packages/wearables/garmin-watchface/adapters/claude/skills/garmin-watchface/scripts/ciq-release +333 -0
  29. package/packages/wearables/garmin-watchface/adapters/cursor/skills/garmin-watchface/SKILL.md +7 -0
  30. package/packages/wearables/garmin-watchface/adapters/cursor/skills/garmin-watchface/references/publishing.md +145 -0
  31. package/packages/wearables/garmin-watchface/adapters/cursor/skills/garmin-watchface/scripts/ciq-release +333 -0
  32. package/packages/wearables/garmin-watchface/adapters/grok/skills/garmin-watchface/SKILL.md +7 -0
  33. package/packages/wearables/garmin-watchface/adapters/grok/skills/garmin-watchface/references/publishing.md +145 -0
  34. package/packages/wearables/garmin-watchface/adapters/grok/skills/garmin-watchface/scripts/ciq-release +333 -0
  35. package/packages/wearables/garmin-watchface/adapters/kiro/steering/garmin-watchface.md +7 -0
  36. package/packages/wearables/garmin-watchface/adapters/windsurf/rules/garmin-watchface.md +7 -0
  37. package/packages/wearables/garmin-watchface/references/publishing.md +145 -0
  38. package/packages/wearables/garmin-watchface/scripts/ciq-release +333 -0
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: pr-description-writer
3
+ description: >
4
+ Draft and post a GitHub PR title and body from git diff and commit history. Use when
5
+ opening a new PR, when the user asks to "write a PR description", "draft a PR", "open
6
+ a PR for this branch", or after running the git-commit skill and pushing the branch.
7
+ Chains naturally after git-commit and before qodoloop / coderabbitloop.
8
+ license: MIT
9
+ allowed-tools: Bash, Read, Write
10
+ compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
11
+ metadata:
12
+ targets: [_source-only]
13
+ author: Oleg Koval
14
+ tags:
15
+ - git
16
+ - github
17
+ - pull-request
18
+ - description
19
+ - pr
20
+ - workflow
21
+ source: weekly-pattern-learner
22
+ source_reason: "qodoloop and coderabbitloop both open with gh pr view โ€” the PR creation/description step was never codified as its own skill"
23
+ source_date: "2026-07-28"
24
+ ---
25
+ <!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
26
+
27
+ > ๐Ÿค– *Auto-generated by **weekly-pattern-learner** ยท qodoloop and coderabbitloop both open with `gh pr view` โ€” the PR creation/description step was never codified as its own skill*
28
+
29
+ # PR Description Writer
30
+
31
+ Draft a GitHub-ready PR title and body from the branch's commit history and diff, then
32
+ create or update the PR so reviewers and AI tools have full context.
33
+
34
+ ## Inputs
35
+
36
+ - **Base branch** (optional, default: `main` or `master` โ€” detect from `gh repo view`)
37
+ - **Draft mode** (optional, default: off)
38
+ - **Template** (optional): if `.github/pull_request_template.md` exists, use its section headings
39
+
40
+ ## Workflow
41
+
42
+ ### 1. Gather branch context
43
+
44
+ ```bash
45
+ # Current branch
46
+ git rev-parse --abbrev-ref HEAD
47
+
48
+ # Base branch
49
+ gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'
50
+
51
+ # Commits since base
52
+ git log <base>..<head> --oneline --no-merges
53
+
54
+ # Diff summary (full diff for small PRs, stat-only for large)
55
+ git diff <base>..<head> --stat
56
+ git diff <base>..<head> # only if total changes < ~500 lines
57
+ ```
58
+
59
+ If the diff is large (>500 changed lines), read file-by-file rather than all at once.
60
+
61
+ ### 2. Check for existing PR
62
+
63
+ ```bash
64
+ gh pr view --json number,title,body,state 2>/dev/null
65
+ ```
66
+
67
+ - If a PR exists in `OPEN` state: update it with `gh pr edit`.
68
+ - If no PR exists: create one with `gh pr create`.
69
+
70
+ ### 3. Check for a PR template
71
+
72
+ ```bash
73
+ cat .github/pull_request_template.md 2>/dev/null \
74
+ || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null \
75
+ || cat PULL_REQUEST_TEMPLATE.md 2>/dev/null
76
+ ```
77
+
78
+ If a template exists, mirror its section headings and populate them. Skip sections
79
+ that ask for credentials, tokens, internal hostnames, or content unrelated to the diff.
80
+
81
+ ### 4. Draft title and body
82
+
83
+ **Title rules:**
84
+ - Use Conventional Commits prefix when the branch/commits use it: `feat(scope):`, `fix:`, etc.
85
+ - โ‰ค 70 characters
86
+ - Imperative mood ("Add X", "Fix Y", not "Added X")
87
+ - Include ticket number if present in branch name (e.g. `LIN-123`, `GH-456`)
88
+
89
+ **Body sections (use the template if one was found, otherwise use this structure):**
90
+
91
+ ```markdown
92
+ ## Summary
93
+ - <bullet: what changed>
94
+ - <bullet: why>
95
+
96
+ ## Changes
97
+ - `<file or subsystem>`: <what changed and why>
98
+
99
+ ## Test plan
100
+ - [ ] <what to run and what result to expect>
101
+ - [ ] <manual steps if automated tests don't cover it>
102
+
103
+ ## Notes
104
+ <optional: anything a reviewer should watch for, known gaps, follow-up issues>
105
+ ```
106
+
107
+ Rules:
108
+ - Describe *intent*, not what the diff already shows line-by-line.
109
+ - If commits already have good conventional messages, use them as the skeleton.
110
+ - Skip any section that has nothing meaningful to say.
111
+ - Reference specific files, functions, or lines only when they aid navigation.
112
+
113
+ ### 5. Create or update the PR
114
+
115
+ Always pass the body via a heredoc or temp file โ€” never interpolate it into the command
116
+ string (quotes and newlines will break the shell):
117
+
118
+ ```bash
119
+ # Create new PR
120
+ gh pr create \
121
+ --title "<title>" \
122
+ --body "$(cat <<'PRBODY'
123
+ <body>
124
+ PRBODY
125
+ )" \
126
+ --base <base> \
127
+ [--draft]
128
+
129
+ # Update existing PR
130
+ gh pr edit <number> \
131
+ --title "<title>" \
132
+ --body "$(cat <<'PRBODY'
133
+ <body>
134
+ PRBODY
135
+ )"
136
+ ```
137
+
138
+ ### 6. Confirm and report
139
+
140
+ ```bash
141
+ gh pr view --json number,title,url -q '"PR #\(.number): \(.title)\n\(.url)"'
142
+ ```
143
+
144
+ Print the PR number, title, and URL. If the PR was newly created, note whether
145
+ CI triggered automatically.
146
+
147
+ ## Chaining
148
+
149
+ | Before this skill | After this skill |
150
+ |---|---|
151
+ | `olko:git-commit` + `git push` | `olko:qodoloop` |
152
+ | `git push -u origin <branch>` | `olko:coderabbitloop` |
153
+ | โ€” | `olko:open-source-publisher` (for new repos) |
@@ -0,0 +1,19 @@
1
+ # Codex Adapter for pr-description-writer
2
+
3
+ This is a Codex-specific adapter for the `olko:pr-description-writer` skill.
4
+ The canonical skill definition is in `../../SKILL.md`.
5
+
6
+ ## Usage
7
+
8
+ Invoke in a Codex session:
9
+
10
+ ```text
11
+ Use the olko:pr-description-writer skill to draft a PR description for this branch.
12
+ ```
13
+
14
+ ## Workflow
15
+
16
+ See `../../SKILL.md` for the full workflow: gather branch context (commits since base,
17
+ diff summary), check for an existing PR template, draft a structured title and body, then
18
+ create or update the GitHub PR using `gh pr create` / `gh pr edit`. The procedure is
19
+ plain `git`/`gh` and is agent-agnostic.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "olko:pr-description-writer",
3
+ "version": "0.1.0",
4
+ "description": "Draft and post a GitHub PR title and body from git diff and commit history. Chains after git-commit and before qodoloop / coderabbitloop.",
5
+ "skills": "skills/"
6
+ }
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: pr-description-writer
3
+ description: >
4
+ Draft and post a GitHub PR title and body from git diff and commit history. Use when
5
+ opening a new PR, when the user asks to "write a PR description", "draft a PR", "open
6
+ a PR for this branch", or after running the git-commit skill and pushing the branch.
7
+ Chains naturally after git-commit and before qodoloop / coderabbitloop.
8
+ license: MIT
9
+ allowed-tools: Bash, Read, Write
10
+ compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
11
+ metadata:
12
+ targets: ["cursor"]
13
+ author: Oleg Koval
14
+ tags:
15
+ - git
16
+ - github
17
+ - pull-request
18
+ - description
19
+ - pr
20
+ - workflow
21
+ source: weekly-pattern-learner
22
+ source_reason: "qodoloop and coderabbitloop both open with gh pr view โ€” the PR creation/description step was never codified as its own skill"
23
+ source_date: "2026-07-28"
24
+ ---
25
+ <!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
26
+
27
+ > ๐Ÿค– *Auto-generated by **weekly-pattern-learner** ยท qodoloop and coderabbitloop both open with `gh pr view` โ€” the PR creation/description step was never codified as its own skill*
28
+
29
+ # PR Description Writer
30
+
31
+ Draft a GitHub-ready PR title and body from the branch's commit history and diff, then
32
+ create or update the PR so reviewers and AI tools have full context.
33
+
34
+ ## Inputs
35
+
36
+ - **Base branch** (optional, default: `main` or `master` โ€” detect from `gh repo view`)
37
+ - **Draft mode** (optional, default: off)
38
+ - **Template** (optional): if `.github/pull_request_template.md` exists, use its section headings
39
+
40
+ ## Workflow
41
+
42
+ ### 1. Gather branch context
43
+
44
+ ```bash
45
+ # Current branch
46
+ git rev-parse --abbrev-ref HEAD
47
+
48
+ # Base branch
49
+ gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'
50
+
51
+ # Commits since base
52
+ git log <base>..<head> --oneline --no-merges
53
+
54
+ # Diff summary (full diff for small PRs, stat-only for large)
55
+ git diff <base>..<head> --stat
56
+ git diff <base>..<head> # only if total changes < ~500 lines
57
+ ```
58
+
59
+ If the diff is large (>500 changed lines), read file-by-file rather than all at once.
60
+
61
+ ### 2. Check for existing PR
62
+
63
+ ```bash
64
+ gh pr view --json number,title,body,state 2>/dev/null
65
+ ```
66
+
67
+ - If a PR exists in `OPEN` state: update it with `gh pr edit`.
68
+ - If no PR exists: create one with `gh pr create`.
69
+
70
+ ### 3. Check for a PR template
71
+
72
+ ```bash
73
+ cat .github/pull_request_template.md 2>/dev/null \
74
+ || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null \
75
+ || cat PULL_REQUEST_TEMPLATE.md 2>/dev/null
76
+ ```
77
+
78
+ If a template exists, mirror its section headings and populate them. Skip sections
79
+ that ask for credentials, tokens, internal hostnames, or content unrelated to the diff.
80
+
81
+ ### 4. Draft title and body
82
+
83
+ **Title rules:**
84
+ - Use Conventional Commits prefix when the branch/commits use it: `feat(scope):`, `fix:`, etc.
85
+ - โ‰ค 70 characters
86
+ - Imperative mood ("Add X", "Fix Y", not "Added X")
87
+ - Include ticket number if present in branch name (e.g. `LIN-123`, `GH-456`)
88
+
89
+ **Body sections (use the template if one was found, otherwise use this structure):**
90
+
91
+ ```markdown
92
+ ## Summary
93
+ - <bullet: what changed>
94
+ - <bullet: why>
95
+
96
+ ## Changes
97
+ - `<file or subsystem>`: <what changed and why>
98
+
99
+ ## Test plan
100
+ - [ ] <what to run and what result to expect>
101
+ - [ ] <manual steps if automated tests don't cover it>
102
+
103
+ ## Notes
104
+ <optional: anything a reviewer should watch for, known gaps, follow-up issues>
105
+ ```
106
+
107
+ Rules:
108
+ - Describe *intent*, not what the diff already shows line-by-line.
109
+ - If commits already have good conventional messages, use them as the skeleton.
110
+ - Skip any section that has nothing meaningful to say.
111
+ - Reference specific files, functions, or lines only when they aid navigation.
112
+
113
+ ### 5. Create or update the PR
114
+
115
+ Always pass the body via a heredoc or temp file โ€” never interpolate it into the command
116
+ string (quotes and newlines will break the shell):
117
+
118
+ ```bash
119
+ # Create new PR
120
+ gh pr create \
121
+ --title "<title>" \
122
+ --body "$(cat <<'PRBODY'
123
+ <body>
124
+ PRBODY
125
+ )" \
126
+ --base <base> \
127
+ [--draft]
128
+
129
+ # Update existing PR
130
+ gh pr edit <number> \
131
+ --title "<title>" \
132
+ --body "$(cat <<'PRBODY'
133
+ <body>
134
+ PRBODY
135
+ )"
136
+ ```
137
+
138
+ ### 6. Confirm and report
139
+
140
+ ```bash
141
+ gh pr view --json number,title,url -q '"PR #\(.number): \(.title)\n\(.url)"'
142
+ ```
143
+
144
+ Print the PR number, title, and URL. If the PR was newly created, note whether
145
+ CI triggered automatically.
146
+
147
+ ## Chaining
148
+
149
+ | Before this skill | After this skill |
150
+ |---|---|
151
+ | `olko:git-commit` + `git push` | `olko:qodoloop` |
152
+ | `git push -u origin <branch>` | `olko:coderabbitloop` |
153
+ | โ€” | `olko:open-source-publisher` (for new repos) |
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "olko:pr-description-writer",
3
+ "version": "0.1.0",
4
+ "description": "Draft and post a GitHub PR title and body from git diff and commit history. Chains after git-commit and before qodoloop / coderabbitloop.",
5
+ "skills": "skills/"
6
+ }
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: pr-description-writer
3
+ description: >
4
+ Draft and post a GitHub PR title and body from git diff and commit history. Use when
5
+ opening a new PR, when the user asks to "write a PR description", "draft a PR", "open
6
+ a PR for this branch", or after running the git-commit skill and pushing the branch.
7
+ Chains naturally after git-commit and before qodoloop / coderabbitloop.
8
+ license: MIT
9
+ allowed-tools: Bash, Read, Write
10
+ compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
11
+ metadata:
12
+ targets: [_source-only]
13
+ author: Oleg Koval
14
+ tags:
15
+ - git
16
+ - github
17
+ - pull-request
18
+ - description
19
+ - pr
20
+ - workflow
21
+ source: weekly-pattern-learner
22
+ source_reason: "qodoloop and coderabbitloop both open with gh pr view โ€” the PR creation/description step was never codified as its own skill"
23
+ source_date: "2026-07-28"
24
+ ---
25
+ <!-- Generated by scripts/build-adapters.sh. Do not edit directly. -->
26
+
27
+ > ๐Ÿค– *Auto-generated by **weekly-pattern-learner** ยท qodoloop and coderabbitloop both open with `gh pr view` โ€” the PR creation/description step was never codified as its own skill*
28
+
29
+ # PR Description Writer
30
+
31
+ Draft a GitHub-ready PR title and body from the branch's commit history and diff, then
32
+ create or update the PR so reviewers and AI tools have full context.
33
+
34
+ ## Inputs
35
+
36
+ - **Base branch** (optional, default: `main` or `master` โ€” detect from `gh repo view`)
37
+ - **Draft mode** (optional, default: off)
38
+ - **Template** (optional): if `.github/pull_request_template.md` exists, use its section headings
39
+
40
+ ## Workflow
41
+
42
+ ### 1. Gather branch context
43
+
44
+ ```bash
45
+ # Current branch
46
+ git rev-parse --abbrev-ref HEAD
47
+
48
+ # Base branch
49
+ gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'
50
+
51
+ # Commits since base
52
+ git log <base>..<head> --oneline --no-merges
53
+
54
+ # Diff summary (full diff for small PRs, stat-only for large)
55
+ git diff <base>..<head> --stat
56
+ git diff <base>..<head> # only if total changes < ~500 lines
57
+ ```
58
+
59
+ If the diff is large (>500 changed lines), read file-by-file rather than all at once.
60
+
61
+ ### 2. Check for existing PR
62
+
63
+ ```bash
64
+ gh pr view --json number,title,body,state 2>/dev/null
65
+ ```
66
+
67
+ - If a PR exists in `OPEN` state: update it with `gh pr edit`.
68
+ - If no PR exists: create one with `gh pr create`.
69
+
70
+ ### 3. Check for a PR template
71
+
72
+ ```bash
73
+ cat .github/pull_request_template.md 2>/dev/null \
74
+ || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null \
75
+ || cat PULL_REQUEST_TEMPLATE.md 2>/dev/null
76
+ ```
77
+
78
+ If a template exists, mirror its section headings and populate them. Skip sections
79
+ that ask for credentials, tokens, internal hostnames, or content unrelated to the diff.
80
+
81
+ ### 4. Draft title and body
82
+
83
+ **Title rules:**
84
+ - Use Conventional Commits prefix when the branch/commits use it: `feat(scope):`, `fix:`, etc.
85
+ - โ‰ค 70 characters
86
+ - Imperative mood ("Add X", "Fix Y", not "Added X")
87
+ - Include ticket number if present in branch name (e.g. `LIN-123`, `GH-456`)
88
+
89
+ **Body sections (use the template if one was found, otherwise use this structure):**
90
+
91
+ ```markdown
92
+ ## Summary
93
+ - <bullet: what changed>
94
+ - <bullet: why>
95
+
96
+ ## Changes
97
+ - `<file or subsystem>`: <what changed and why>
98
+
99
+ ## Test plan
100
+ - [ ] <what to run and what result to expect>
101
+ - [ ] <manual steps if automated tests don't cover it>
102
+
103
+ ## Notes
104
+ <optional: anything a reviewer should watch for, known gaps, follow-up issues>
105
+ ```
106
+
107
+ Rules:
108
+ - Describe *intent*, not what the diff already shows line-by-line.
109
+ - If commits already have good conventional messages, use them as the skeleton.
110
+ - Skip any section that has nothing meaningful to say.
111
+ - Reference specific files, functions, or lines only when they aid navigation.
112
+
113
+ ### 5. Create or update the PR
114
+
115
+ Always pass the body via a heredoc or temp file โ€” never interpolate it into the command
116
+ string (quotes and newlines will break the shell):
117
+
118
+ ```bash
119
+ # Create new PR
120
+ gh pr create \
121
+ --title "<title>" \
122
+ --body "$(cat <<'PRBODY'
123
+ <body>
124
+ PRBODY
125
+ )" \
126
+ --base <base> \
127
+ [--draft]
128
+
129
+ # Update existing PR
130
+ gh pr edit <number> \
131
+ --title "<title>" \
132
+ --body "$(cat <<'PRBODY'
133
+ <body>
134
+ PRBODY
135
+ )"
136
+ ```
137
+
138
+ ### 6. Confirm and report
139
+
140
+ ```bash
141
+ gh pr view --json number,title,url -q '"PR #\(.number): \(.title)\n\(.url)"'
142
+ ```
143
+
144
+ Print the PR number, title, and URL. If the PR was newly created, note whether
145
+ CI triggered automatically.
146
+
147
+ ## Chaining
148
+
149
+ | Before this skill | After this skill |
150
+ |---|---|
151
+ | `olko:git-commit` + `git push` | `olko:qodoloop` |
152
+ | `git push -u origin <branch>` | `olko:coderabbitloop` |
153
+ | โ€” | `olko:open-source-publisher` (for new repos) |
@@ -25,6 +25,7 @@ looked like success first.
25
25
  | `references/simulator.md` | Screenshots, settings not applying, monkeydo hanging |
26
26
  | `references/devices.md` | Adding device support, launcher icons, API levels |
27
27
  | `references/store.md` | Publishing, listing copy, IP questions |
28
+ | `references/publishing.md` | Driving the store portal in a browser; upload/update flow, validator rejections |
28
29
 
29
30
  ## Tools
30
31
 
@@ -37,8 +38,14 @@ Run these rather than reinventing them. All are standalone.
37
38
  <skill-dir>/scripts/ciq-capture out.png # calibrated simulator screenshot
38
39
  <skill-dir>/scripts/ciq-capture out.png --face --size 260 # cropped + masked to the round display
39
40
  <skill-dir>/scripts/ciq-calibrate # re-derive the display rect if capture looks wrong
41
+ <skill-dir>/scripts/ciq-release # pre-submission check: package, screenshots, icon, keys, copy
40
42
  ```
41
43
 
44
+ `<skill-dir>/scripts/ciq-release` is what you run before opening the store
45
+ portal. Every check in it is something otherwise discovered halfway through the
46
+ submission form -- a stale screenshot set, an icon still copied from the last
47
+ project, or copy containing a character the description validator rejects.
48
+
42
49
  `<skill-dir>/scripts/ciq-capture` exists because `screencapture -R` grabs a screen *region*, not
43
50
  a window: without a frontmost check it silently photographs whatever is on top,
44
51
  and the window moves between simulator restarts. Both failure modes produce a
@@ -26,6 +26,7 @@ looked like success first.
26
26
  | `references/simulator.md` | Screenshots, settings not applying, monkeydo hanging |
27
27
  | `references/devices.md` | Adding device support, launcher icons, API levels |
28
28
  | `references/store.md` | Publishing, listing copy, IP questions |
29
+ | `references/publishing.md` | Driving the store portal in a browser; upload/update flow, validator rejections |
29
30
 
30
31
  ## Tools
31
32
 
@@ -38,8 +39,14 @@ Run these rather than reinventing them. All are standalone.
38
39
  <skill-dir>/scripts/ciq-capture out.png # calibrated simulator screenshot
39
40
  <skill-dir>/scripts/ciq-capture out.png --face --size 260 # cropped + masked to the round display
40
41
  <skill-dir>/scripts/ciq-calibrate # re-derive the display rect if capture looks wrong
42
+ <skill-dir>/scripts/ciq-release # pre-submission check: package, screenshots, icon, keys, copy
41
43
  ```
42
44
 
45
+ `<skill-dir>/scripts/ciq-release` is what you run before opening the store
46
+ portal. Every check in it is something otherwise discovered halfway through the
47
+ submission form -- a stale screenshot set, an icon still copied from the last
48
+ project, or copy containing a character the description validator rejects.
49
+
43
50
  `<skill-dir>/scripts/ciq-capture` exists because `screencapture -R` grabs a screen *region*, not
44
51
  a window: without a frontmost check it silently photographs whatever is on top,
45
52
  and the window moves between simulator restarts. Both failure modes produce a
@@ -0,0 +1,145 @@
1
+ # Publishing through the browser
2
+
3
+ `references/store.md` covers *what* the listing needs. This covers *driving the
4
+ portal*, which is the only way in โ€” Garmin publishes no submission API.
5
+
6
+ Run `scripts/ciq-release` before opening a browser. Everything it checks is
7
+ something you would otherwise discover halfway through the form.
8
+
9
+ ## The portal is automatable
10
+
11
+ The obvious conclusion is that it is not: `apps.garmin.com/developer/dashboard`
12
+ sits behind Garmin SSO *and* Cloudflare bot protection, and a headless browser
13
+ lands on a "Performing security verification" interstitial. That is what you see
14
+ if you navigate cold.
15
+
16
+ It works anyway, because the session is already sitting in your own browser.
17
+ Import the cookies:
18
+
19
+ ```bash
20
+ B=~/.claude/skills/gstack/browse/dist/browse
21
+
22
+ $B cookie-import-browser comet --domain .garmin.com # note the LEADING DOT
23
+ $B goto https://apps.garmin.com/ # host-scoped cookies
24
+ $B cookie-import-browser comet --domain apps.garmin.com # need you to be on
25
+ $B goto https://sso.garmin.com/ # the host first
26
+ $B cookie-import-browser comet --domain sso.garmin.com
27
+
28
+ $B goto https://apps.garmin.com/developer/dashboard # no SSO redirect
29
+ ```
30
+
31
+ Three separate traps in that block:
32
+
33
+ - **`garmin.com` imports nothing. `.garmin.com` imports everything.** The cookie
34
+ is stored under the dotted domain and the filter is an exact match, so the
35
+ obvious spelling silently returns `Imported 0 cookies` and looks like "not
36
+ logged in".
37
+ - **Host-scoped cookies need you on that host first**, or the import refuses
38
+ with *"does not match current page domain"*. The `.garmin.com` set alone is
39
+ NOT enough to authenticate โ€” the session only holds once
40
+ `apps.` and `sso.` are imported too.
41
+ - **Substitute your browser.** `comet`, `chrome`, `brave`, `arc`, `edge`,
42
+ `chromium` are supported. Whichever one you actually signed into.
43
+
44
+ Verify by checking the URL after `goto`: an unauthenticated session is bounced
45
+ to `sso.garmin.com/portal/sso/...`, an authenticated one stays put.
46
+
47
+ ## "The Connect IQ store is currently in maintenance mode"
48
+
49
+ This string is in the DOM of the dashboard and of every app page, next to
50
+ *Upload New Version*, *Edit Details* and *Remove*. Reading the page text makes
51
+ it look like every action is blocked.
52
+
53
+ **It is pre-rendered hidden markup, not an active block.** Click the button and
54
+ the real form loads. Do not report the store as down on the strength of a text
55
+ dump โ€” click first, then check for a *visible* dialog:
56
+
57
+ ```bash
58
+ $B js "(function(){var o=[];document.querySelectorAll('[role=dialog],.modal').forEach(function(x){if(x.offsetParent!==null)o.push(x.innerText.slice(0,120))});return o.join('|')||'no visible modal'})()"
59
+ ```
60
+
61
+ ## The two-step update flow
62
+
63
+ *Upload New Version* โ†’ `/apps/<uuid>/update`, which is two steps.
64
+
65
+ **Step 1 โ€” attach.** A file input and an *App Version* textbox. Publish stays
66
+ disabled until both are set; the page shows the current version so you can pick
67
+ the next one.
68
+
69
+ ```bash
70
+ $B upload "input[type=file]" "$(pwd)/bin/<name>.iq"
71
+ $B fill "input[id*='version'],input[name*='version']" "2.0"
72
+ $B click "button:has-text('Upload and publish')"
73
+ ```
74
+
75
+ On success the page reports **Status: Verified, Signature: Verified** and
76
+ expands the product list โ€” a manifest naming one product can resolve to several
77
+ store devices (`fenix6pro` becomes fฤ“nix 6 Pro, 6 Pro Dual Power, 6 Pro Solar
78
+ and quatix 6).
79
+
80
+ **Step 2 โ€” details.** Title, description, What's New, images, category, contact
81
+ email. Ends in *Submit*.
82
+
83
+ The description arrives pre-filled with the copy from the PREVIOUS version.
84
+ After a redesign it describes a face that no longer exists, and nothing prompts
85
+ you about it. Re-paste from `docs/store/listing.md` every time.
86
+
87
+ ## Image slots, in DOM order
88
+
89
+ There are seven `input[type=file]` elements and none of them carry a name, id
90
+ or label. Order is the only way to tell them apart, so confirm it before
91
+ uploading rather than trusting this table:
92
+
93
+ ```bash
94
+ $B js "(function(){var f=document.querySelectorAll('input[type=file]');var o=[];f.forEach(function(x,i){var n=x,c='';for(var k=0;k<8&&n;k++){n=n.parentElement;if(n&&n.innerText.trim().length>25){c=n.innerText.replace(/\s+/g,' ').slice(0,60);break}}o.push(i+' >> '+c)});return o.join('\n')})()"
95
+ ```
96
+
97
+ | # | Slot | Size | Limit |
98
+ | --- | --- | --- | --- |
99
+ | 0 | Hero image | **1440ร—720** | 2048 KB |
100
+ | 1 | Cover image | **500ร—500** | 300 KB |
101
+ | 2โ€“6 | Screen images | any | **150 KB each** |
102
+
103
+ Getting the order wrong puts a 260px screenshot where the hero belongs, and the
104
+ form accepts it.
105
+
106
+ ## The description validator
107
+
108
+ Two rejections, both discovered only after filling the entire form and pressing
109
+ Submit:
110
+
111
+ - `Illegal characters found: <, >.` โ€” an ASCII `->` arrow is enough to trip it.
112
+ - `The app description is invalid. It should not contain emojis.` โ€” **U+2699
113
+ GEAR counts**, which is exactly the character you reach for when writing
114
+ "tap the gear icon". U+2192 RIGHTWARDS ARROW passes today but lives in the
115
+ same symbol space.
116
+
117
+ Write settings paths in words: *"Garmin Connect app, then: your device, Connect
118
+ IQ Apps, Watch Faces, the app name, settings"*. `scripts/ciq-release` checks the fenced
119
+ blocks of `listing.md` for both classes before you open a browser.
120
+
121
+ The error text renders as a leaf node with no `aria-invalid` anywhere, so find
122
+ it by scanning for childless visible elements rather than by form state:
123
+
124
+ ```bash
125
+ $B js "(function(){var o=[];document.querySelectorAll('*').forEach(function(x){if(!x.children.length&&x.offsetParent!==null&&/invalid|illegal/i.test(x.innerText))o.push(x.innerText.trim())});return Array.from(new Set(o)).join(' || ')})()"
126
+ ```
127
+
128
+ Success is a redirect to `apps.garmin.com/apps/<uuid>`. Staying on `/update`
129
+ means a validation failure.
130
+
131
+ ## Things not to click
132
+
133
+ **Remove** sits between *Edit Details* and *Download* in the same button row.
134
+ Never target buttons by index in that row.
135
+
136
+ **Upload and publish** and **Submit** are outward-facing: they push to a public
137
+ listing and accept the Developer License Agreement on the account holder's
138
+ behalf. Confirm with the human before either, even when they have asked for the
139
+ release โ€” version number and stale copy are both worth one question.
140
+
141
+ ## Account state
142
+
143
+ A developer account pending identity verification can still upload; approval
144
+ gates public visibility, not submission. A newly submitted app sits in preview
145
+ mode, visible only to its owner, for up to three days.