Skip to content

Commit 6274d74

Browse files
Initial commit
0 parents  commit 6274d74

80 files changed

Lines changed: 18656 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/pull_request_template.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!--
2+
Thanks for opening a PR. Pick the section below that matches your change
3+
type and delete the others.
4+
5+
Full reviewer guide: REVIEW.md
6+
-->
7+
8+
## Type
9+
10+
- [ ] Docs refresh (automated, opened by `refresh-docs.yml`)
11+
- [ ] Manual polished-content edit
12+
- [ ] Pipeline / schema / CI / skill change
13+
14+
---
15+
16+
## If this is a docs refresh
17+
18+
**Touched slugs:** <!-- auto-filled by refresh-docs.yml -->
19+
20+
Reviewer checklist (see [`REVIEW.md`](../REVIEW.md) for the full version):
21+
22+
- [ ] Source diff looks sane; `source_ref` is a commit SHA, not a branch
23+
- [ ] `pnpm snapshot:refresh` committed
24+
- [ ] `pnpm check:all` green locally
25+
- [ ] Corpus diff read against `sources/`: the transform only reshaped (boilerplate stripped, callouts converted) — no content added, weakened, or reversed
26+
- [ ] Upstream snippet bugs (if any) tracked as separate issues against `Iterable/iterable-docs`**not** hand-fixed here
27+
28+
---
29+
30+
## If this is a manual polished-content edit
31+
32+
Why is the deterministic transform insufficient for this change? (One sentence.)
33+
34+
<!-- e.g. "Foreign-language stripping of a cross-platform doc — the transform
35+
doesn't do this yet." -->
36+
37+
- [ ] `pnpm recompute:manifest` run for every edited corpus file
38+
- [ ] `pnpm snapshot:refresh` committed
39+
- [ ] `pnpm check:all` green locally
40+
- [ ] Considered whether the transform (`pipeline/src/lib/layer-a.ts`) could be updated instead of editing by hand
41+
42+
---
43+
44+
## If this is a pipeline / schema / CI / skill change
45+
46+
- [ ] `pnpm typecheck` green
47+
- [ ] `pnpm check:all` green
48+
- [ ] If changing the schema or a validator, tested both the success and the failure case locally
49+
- [ ] If changing `iterable-android/SKILL.md`, sanity-checked the routing table against `polished/<platform>/`
50+
- [ ] If changing the snippet manifest format, ran `pnpm recompute:manifest polished/**/*.polished.md` and confirmed no semantic drift
51+
52+
---
53+
54+
## Anything reviewers should know
55+
56+
<!-- Context that doesn't fit a checkbox: blocked-on, follow-up, gotchas. -->
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Publish to Context7
2+
3+
# Fires after a refresh PR merges and the published surface (polished docs
4+
# or skill) actually changed. Tells Context7 to re-index our library so
5+
# updates land in agent results without waiting for the scheduled crawl.
6+
#
7+
# STUB: the POST below targets a placeholder endpoint. The real reindex
8+
# URL and the payload shape are pending confirmation from Context7
9+
# (Lauren). The CONTEXT7_API_KEY repo secret is not provisioned yet —
10+
# until it is, the curl call will fail and the job will exit non-zero.
11+
# That's intentional so a missing secret is loud rather than silent.
12+
13+
on:
14+
push:
15+
branches: [main]
16+
paths:
17+
- polished/**
18+
- iterable-android/**
19+
- context7.json
20+
workflow_dispatch:
21+
22+
permissions:
23+
contents: read
24+
25+
jobs:
26+
publish:
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 5
29+
steps:
30+
- name: Reindex Context7 library
31+
env:
32+
CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY }}
33+
# TODO: replace once Lauren / Context7 confirm the endpoint shape.
34+
CONTEXT7_REINDEX_URL: https://context7.com/api/v1/libraries/iterable/sdks/reindex
35+
run: |
36+
set -euo pipefail
37+
if [[ -z "${CONTEXT7_API_KEY:-}" ]]; then
38+
echo "::error::CONTEXT7_API_KEY secret is not set on this repo."
39+
echo "Provision the secret once Context7 issues a token, then re-run."
40+
exit 1
41+
fi
42+
echo "Triggering Context7 reindex for commit ${GITHUB_SHA}"
43+
curl --fail-with-body --silent --show-error \
44+
-X POST "${CONTEXT7_REINDEX_URL}" \
45+
-H "Authorization: Bearer ${CONTEXT7_API_KEY}" \
46+
-H "Content-Type: application/json" \
47+
-d "$(cat <<EOF
48+
{
49+
"ref": "${GITHUB_SHA}",
50+
"source": "github.com/${GITHUB_REPOSITORY}"
51+
}
52+
EOF
53+
)"

.github/workflows/refresh-docs.yml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: Refresh docs
2+
3+
# Triggered when Iterable/iterable-docs publishes a change to an SDK doc
4+
# path. The docs repo dispatches `iterable-docs-changed`; this workflow
5+
# pulls the fresh markdown, runs the deterministic transform, and opens a
6+
# PR. There is no LLM step — the corpus is the docs reshaped. A reviewer
7+
# refreshes the snapshot and merges.
8+
#
9+
# `workflow_dispatch` is kept as a manual fallback for re-running a
10+
# refresh outside of a docs-side trigger (e.g. when validating a config
11+
# change on this repo).
12+
13+
on:
14+
repository_dispatch:
15+
types: [iterable-docs-changed]
16+
workflow_dispatch:
17+
inputs:
18+
platform:
19+
description: "Platform to refresh"
20+
required: true
21+
default: "android"
22+
type: choice
23+
options:
24+
- android
25+
26+
permissions:
27+
contents: write
28+
pull-requests: write
29+
30+
jobs:
31+
refresh:
32+
runs-on: ubuntu-latest
33+
steps:
34+
- name: Checkout
35+
uses: actions/checkout@v4
36+
37+
- name: Setup pnpm
38+
uses: pnpm/action-setup@v4
39+
with:
40+
version: 9
41+
42+
- name: Setup Node
43+
uses: actions/setup-node@v4
44+
with:
45+
node-version: 20
46+
cache: pnpm
47+
cache-dependency-path: pipeline/pnpm-lock.yaml
48+
49+
- name: Install pipeline deps
50+
working-directory: pipeline
51+
run: pnpm install --frozen-lockfile
52+
53+
- name: Fetch sources (uses GITHUB_TOKEN for gh api)
54+
working-directory: pipeline
55+
env:
56+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57+
run: pnpm fetch:sources -- ${{ github.event.inputs.platform || github.event.client_payload.platform || 'android' }}
58+
59+
- name: Polish Layer A
60+
working-directory: pipeline
61+
run: pnpm polish:a -- --platform=${{ github.event.inputs.platform || github.event.client_payload.platform || 'android' }}
62+
63+
- name: Detect changes
64+
id: changes
65+
run: |
66+
if git diff --quiet sources/ polished/; then
67+
echo "changed=false" >> "$GITHUB_OUTPUT"
68+
exit 0
69+
fi
70+
echo "changed=true" >> "$GITHUB_OUTPUT"
71+
# Slugs touched in sources/ this run
72+
slugs=$(git diff --name-only sources/ \
73+
| sed -E 's|sources/[^/]+/([^/]+)\.md|\1|' \
74+
| sort -u | paste -sd ', ' -)
75+
echo "slugs=${slugs}" >> "$GITHUB_OUTPUT"
76+
77+
- name: Open refresh PR
78+
if: steps.changes.outputs.changed == 'true'
79+
uses: peter-evans/create-pull-request@v6
80+
with:
81+
token: ${{ secrets.GITHUB_TOKEN }}
82+
branch: refresh/${{ github.event.inputs.platform || github.event.client_payload.platform || 'android' }}-${{ github.run_id }}
83+
base: main
84+
delete-branch: true
85+
title: "docs refresh (${{ github.event.inputs.platform || github.event.client_payload.platform || 'android' }}): ${{ steps.changes.outputs.slugs }}"
86+
commit-message: |
87+
docs refresh (${{ github.event.inputs.platform || github.event.client_payload.platform || 'android' }}): Layer A only
88+
89+
Slugs: ${{ steps.changes.outputs.slugs }}
90+
body: |
91+
Automated refresh of `sources/` and the deterministic `polished/`
92+
corpus (Layer A). **No LLM rewrite step** — the polished corpus is
93+
a deterministic transform of the docs.
94+
95+
**Slugs touched:** ${{ steps.changes.outputs.slugs }}
96+
97+
## Reviewer steps
98+
99+
1. Check out this branch.
100+
2. Spot-check the diff against `sources/` for content fidelity —
101+
the transform only strips boilerplate / normalizes structure,
102+
so headings and code should match the upstream docs.
103+
3. Run `pnpm snapshot:refresh` and commit the resulting
104+
`iterable-android/snapshot/` changes. CI's `snapshot:verify`
105+
gate will fail the build otherwise.
106+
4. Confirm `pnpm check:all` is green locally.
107+
5. Merge to `main`. Context7 picks up the change on its next
108+
crawl (`context7.json` controls scope).
109+
labels: |
110+
docs-refresh
111+
automated

.github/workflows/validate.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Validate polished corpus
2+
3+
# Runs the pipeline's full validation suite on every push to main and every PR.
4+
# Blocking gates: typecheck, polished-frontmatter schema, layer-a vs polished
5+
# structural diff. Advisory (always exit 0): chunking lint and kotlinc snippet
6+
# check. The snippet check is advisory in v1 because kotlinc -script runs full
7+
# semantic analysis and floods on "unresolved reference" without a classpath;
8+
# tracked follow-up loads the Iterable SDK + android.jar so it can become
9+
# blocking in v2.
10+
11+
on:
12+
push:
13+
branches: [main]
14+
paths:
15+
- polished/**
16+
- pipeline/**
17+
- iterable-android/snapshot/**
18+
- .github/workflows/validate.yml
19+
pull_request:
20+
branches: [main]
21+
paths:
22+
- polished/**
23+
- pipeline/**
24+
- iterable-android/snapshot/**
25+
- .github/workflows/validate.yml
26+
workflow_dispatch:
27+
28+
permissions:
29+
contents: read
30+
31+
jobs:
32+
validate:
33+
runs-on: ubuntu-latest
34+
timeout-minutes: 10
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
39+
- name: Setup pnpm
40+
uses: pnpm/action-setup@v4
41+
with:
42+
version: 9
43+
44+
- name: Setup Node
45+
uses: actions/setup-node@v4
46+
with:
47+
node-version: 20
48+
cache: pnpm
49+
cache-dependency-path: pipeline/pnpm-lock.yaml
50+
51+
- name: Setup Java (kotlinc dependency)
52+
uses: actions/setup-java@v4
53+
with:
54+
distribution: temurin
55+
java-version: "17"
56+
57+
- name: Install Kotlin compiler
58+
run: |
59+
set -euo pipefail
60+
curl -sL "https://github.com/JetBrains/kotlin/releases/download/v1.9.24/kotlin-compiler-1.9.24.zip" -o /tmp/kotlinc.zip
61+
unzip -q /tmp/kotlinc.zip -d "$HOME"
62+
echo "$HOME/kotlinc/bin" >> "$GITHUB_PATH"
63+
64+
- name: Verify kotlinc
65+
run: kotlinc -version
66+
67+
- name: Install pipeline deps
68+
working-directory: pipeline
69+
run: pnpm install --frozen-lockfile
70+
71+
- name: Run all gates
72+
working-directory: pipeline
73+
run: pnpm check:all

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.DS_Store
2+
scaffold.sh
3+
*.local
4+
node_modules/
5+
pipeline/dist/
6+
proposals/
7+
8+
# Eval derived artifacts — regenerated from scenarios/ + transcripts/.
9+
# Committed: scenarios, *.sample.md transcripts, eval/README.md.
10+
eval/prompts/
11+
eval/results/
12+
eval/report/

README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# iterable-sdk-skill
2+
3+
A skill that turns your AI coding assistant (Cursor, Claude Code) into a
4+
reliable guide for integrating the **Iterable Android SDK**. It's derived from
5+
Iterable's official documentation, so the code your assistant writes matches how
6+
the SDK actually works — not the model's stale guess at it.
7+
8+
It also adds the one thing the docs don't have: hand-written **pitfalls** for the
9+
silent-failure traps that quietly break integrations (JWT keys with no auth
10+
handler, missing `POST_NOTIFICATIONS` on Android 13+, `setEmail` inside the init
11+
callback, and more).
12+
13+
## Install
14+
15+
The skill is a single directory you symlink into your assistant's skills folder.
16+
17+
```bash
18+
git clone --depth 1 git@github.com:Iterable/iterable-sdk-skill.git ~/iterable-skills
19+
20+
# Cursor
21+
ln -s ~/iterable-skills/iterable-android ~/.cursor/skills/iterable-android
22+
23+
# Claude Code
24+
ln -s ~/iterable-skills/iterable-android ~/.claude/skills/iterable-android
25+
```
26+
27+
That's it. The skill activates automatically whenever you mention Iterable: it
28+
loads its always-on rules and `PITFALLS.md`, then pulls the documentation for
29+
whatever feature you're working on (see [How it works](#how-it-works)).
30+
31+
## How it works
32+
33+
The Iterable documentation that powers the skill is published to
34+
[Context7](https://context7.com), a service that hosts docs for AI assistants to
35+
query. When you ask the skill to build something, it fetches the relevant
36+
articles from Context7 on demand, so it works from the current documentation
37+
rather than what the model happened to memorize.
38+
39+
A copy of the same docs ships inside the skill (`iterable-android/snapshot/`),
40+
which it falls back to if Context7 is unreachable or your assistant is offline.
41+
This snapshot is the active source today; the Context7 library comes online in an
42+
upcoming release.
43+
44+
## What it covers
45+
46+
Push notifications, in-app messages, mobile inbox, embedded messaging, deep
47+
linking, JWT authentication, event tracking, user profiles, and unknown-user
48+
activation. Snippets are Kotlin-first and version-pinned to the SDK release each
49+
was validated against.
50+
51+
See [`iterable-android/SKILL.md`](iterable-android/SKILL.md) for the full
52+
routing table.
53+
54+
## Repo layout
55+
56+
```
57+
iterable-android/ the installable skill (SKILL.md + PITFALLS.md + snapshot/)
58+
polished/ the docs in agent-ready form (what gets published to Context7)
59+
pipeline/ tooling that builds polished/ from sources/, CI-gated
60+
sources/ raw Iterable docs, fetched at pinned commits
61+
context7.json Context7 manifest
62+
```
63+
64+
## Staying current
65+
66+
When Iterable's docs change, a workflow rebuilds the skill's content and opens a
67+
PR for a reviewer to check and merge — updates are never applied automatically.
68+
See [`REVIEW.md`](REVIEW.md).
69+
70+
## Limitations
71+
72+
- **Android only.** iOS, React Native, and Web are not yet covered.
73+
- **Some docs carry foreign snippets.** A few articles come from shared "Mobile
74+
SDKs" pages and still contain iOS/JS code an Android agent must ignore.
75+
- **Context7 fetch is not live yet.** The skill works today from its bundled
76+
snapshot; on-demand Context7 fetching turns on in an upcoming release.

0 commit comments

Comments
 (0)