arcane-cli 0.14.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/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/assets/.arcane/agents/agent-policies-template.md +414 -0
- package/dist/assets/.arcane/governance/agent-approved-paths.md +60 -0
- package/dist/assets/.arcane/governance/agent-policies.md +414 -0
- package/dist/assets/.arcane/governance/agent-work-queue-model.md +61 -0
- package/dist/assets/.arcane/governance/authentication-strategy.md +220 -0
- package/dist/assets/.arcane/governance/cicd-standards.md +227 -0
- package/dist/assets/.arcane/governance/decision-documentation-standard.md +335 -0
- package/dist/assets/.arcane/governance/development-methodology.md +384 -0
- package/dist/assets/.arcane/governance/git-conventions.md +759 -0
- package/dist/assets/.arcane/governance/hardening-checklist.md +117 -0
- package/dist/assets/.arcane/governance/naming-conventions.md +142 -0
- package/dist/assets/.arcane/governance/new-business-setup.md +182 -0
- package/dist/assets/.arcane/governance/poc-management-pattern.md +190 -0
- package/dist/assets/.arcane/governance/portable-bootstrap.md +101 -0
- package/dist/assets/.arcane/governance/product-excellence-standards.md +211 -0
- package/dist/assets/.arcane/governance/rca-process-standard.md +157 -0
- package/dist/assets/.arcane/governance/spell-authoring-standards.md +129 -0
- package/dist/assets/.arcane/governance/testing-standards.md +158 -0
- package/dist/assets/.arcane/governance/threat-model.md +104 -0
- package/dist/assets/.arcane/governance/universal-agent-rules.md +108 -0
- package/dist/assets/.arcane/image-prompts/adelaide-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/alexander-image-prompt.md +138 -0
- package/dist/assets/.arcane/image-prompts/bess-image-prompt.md +139 -0
- package/dist/assets/.arcane/image-prompts/circe-image-prompt.md +143 -0
- package/dist/assets/.arcane/image-prompts/custodio-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/iris-image-prompt.md +139 -0
- package/dist/assets/.arcane/image-prompts/kellar-image-prompt.md +141 -0
- package/dist/assets/.arcane/image-prompts/lafayette-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/lince-image-prompt.md +142 -0
- package/dist/assets/.arcane/image-prompts/mercurio-image-prompt.md +140 -0
- package/dist/assets/.arcane/image-prompts/merlin-image-prompt.md +139 -0
- package/dist/assets/.arcane/image-prompts/prospero-image-prompt.md +141 -0
- package/dist/assets/.arcane/templates/venture-template/overview.md +66 -0
- package/dist/assets/.claude/commands/spell-address-review.md +9 -0
- package/dist/assets/.claude/commands/spell-arcane-version.md +9 -0
- package/dist/assets/.claude/commands/spell-architect.md +9 -0
- package/dist/assets/.claude/commands/spell-bootstrap-business.md +9 -0
- package/dist/assets/.claude/commands/spell-brainstorm.md +9 -0
- package/dist/assets/.claude/commands/spell-bug.md +9 -0
- package/dist/assets/.claude/commands/spell-bump.md +9 -0
- package/dist/assets/.claude/commands/spell-check-drift.md +9 -0
- package/dist/assets/.claude/commands/spell-close-session.md +9 -0
- package/dist/assets/.claude/commands/spell-commit-work.md +9 -0
- package/dist/assets/.claude/commands/spell-create-pull-request.md +9 -0
- package/dist/assets/.claude/commands/spell-document.md +9 -0
- package/dist/assets/.claude/commands/spell-dotnet-expert.md +9 -0
- package/dist/assets/.claude/commands/spell-eas-ios-deploy.md +9 -0
- package/dist/assets/.claude/commands/spell-enchant.md +9 -0
- package/dist/assets/.claude/commands/spell-explain-concept.md +9 -0
- package/dist/assets/.claude/commands/spell-feedback.md +9 -0
- package/dist/assets/.claude/commands/spell-full-cycle.md +9 -0
- package/dist/assets/.claude/commands/spell-generate-bot-icons.md +9 -0
- package/dist/assets/.claude/commands/spell-implement.md +9 -0
- package/dist/assets/.claude/commands/spell-open-session.md +9 -0
- package/dist/assets/.claude/commands/spell-plan.md +9 -0
- package/dist/assets/.claude/commands/spell-present-arcane.md +9 -0
- package/dist/assets/.claude/commands/spell-product-review.md +9 -0
- package/dist/assets/.claude/commands/spell-review-batch.md +9 -0
- package/dist/assets/.claude/commands/spell-review.md +9 -0
- package/dist/assets/.claude/commands/spell-save-idea.md +9 -0
- package/dist/assets/.claude/commands/spell-scope.md +9 -0
- package/dist/assets/.claude/commands/spell-security-review.md +9 -0
- package/dist/assets/.claude/commands/spell-ship.md +9 -0
- package/dist/assets/.claude/commands/spell-status.md +9 -0
- package/dist/assets/.claude/commands/spell-suggest-feature.md +9 -0
- package/dist/assets/.claude/commands/spell-test.md +9 -0
- package/dist/assets/.claude/commands/spell-todo.md +9 -0
- package/dist/assets/.github/agents/adelaide.agent.md +44 -0
- package/dist/assets/.github/agents/alexander.agent.md +43 -0
- package/dist/assets/.github/agents/bess.agent.md +42 -0
- package/dist/assets/.github/agents/circe.agent.md +43 -0
- package/dist/assets/.github/agents/custodio.agent.md +44 -0
- package/dist/assets/.github/agents/iris.agent.md +43 -0
- package/dist/assets/.github/agents/kellar.agent.md +43 -0
- package/dist/assets/.github/agents/lafayette.agent.md +42 -0
- package/dist/assets/.github/agents/lince.agent.md +43 -0
- package/dist/assets/.github/agents/mercurio.agent.md +43 -0
- package/dist/assets/.github/agents/merlin.agent.md +44 -0
- package/dist/assets/.github/agents/prospero.agent.md +43 -0
- package/dist/assets/.github/instructions/agent-output.instructions.md +48 -0
- package/dist/assets/.github/prompts/spell-address-review.prompt.md +114 -0
- package/dist/assets/.github/prompts/spell-arcane-version.prompt.md +82 -0
- package/dist/assets/.github/prompts/spell-architect.prompt.md +116 -0
- package/dist/assets/.github/prompts/spell-bootstrap-business.prompt.md +73 -0
- package/dist/assets/.github/prompts/spell-brainstorm.prompt.md +124 -0
- package/dist/assets/.github/prompts/spell-bug.prompt.md +109 -0
- package/dist/assets/.github/prompts/spell-bump.prompt.md +73 -0
- package/dist/assets/.github/prompts/spell-check-drift.prompt.md +97 -0
- package/dist/assets/.github/prompts/spell-close-session.prompt.md +189 -0
- package/dist/assets/.github/prompts/spell-commit-work.prompt.md +211 -0
- package/dist/assets/.github/prompts/spell-create-pull-request.prompt.md +170 -0
- package/dist/assets/.github/prompts/spell-document.prompt.md +83 -0
- package/dist/assets/.github/prompts/spell-dotnet-expert.prompt.md +117 -0
- package/dist/assets/.github/prompts/spell-eas-ios-deploy.prompt.md +183 -0
- package/dist/assets/.github/prompts/spell-enchant.prompt.md +385 -0
- package/dist/assets/.github/prompts/spell-explain-concept.prompt.md +69 -0
- package/dist/assets/.github/prompts/spell-feedback.prompt.md +113 -0
- package/dist/assets/.github/prompts/spell-full-cycle.prompt.md +201 -0
- package/dist/assets/.github/prompts/spell-generate-bot-icons.prompt.md +84 -0
- package/dist/assets/.github/prompts/spell-implement.prompt.md +101 -0
- package/dist/assets/.github/prompts/spell-open-session.prompt.md +116 -0
- package/dist/assets/.github/prompts/spell-plan.prompt.md +145 -0
- package/dist/assets/.github/prompts/spell-present-arcane.prompt.md +188 -0
- package/dist/assets/.github/prompts/spell-product-review.prompt.md +97 -0
- package/dist/assets/.github/prompts/spell-review-batch.prompt.md +94 -0
- package/dist/assets/.github/prompts/spell-review.prompt.md +131 -0
- package/dist/assets/.github/prompts/spell-save-idea.prompt.md +83 -0
- package/dist/assets/.github/prompts/spell-scope.prompt.md +263 -0
- package/dist/assets/.github/prompts/spell-security-review.prompt.md +129 -0
- package/dist/assets/.github/prompts/spell-ship.prompt.md +104 -0
- package/dist/assets/.github/prompts/spell-status.prompt.md +85 -0
- package/dist/assets/.github/prompts/spell-suggest-feature.prompt.md +110 -0
- package/dist/assets/.github/prompts/spell-test.prompt.md +87 -0
- package/dist/assets/.github/prompts/spell-todo.prompt.md +126 -0
- package/dist/assets/DECISIONS.md +19 -0
- package/dist/assets/TODO.md +7 -0
- package/dist/assets/agents/architecture-lead.yaml +61 -0
- package/dist/assets/agents/collaborator.yaml +59 -0
- package/dist/assets/agents/devops.yaml +60 -0
- package/dist/assets/agents/frontend-dev.yaml +60 -0
- package/dist/assets/agents/fullstack-dev.yaml +59 -0
- package/dist/assets/agents/marketing-strategist.yaml +60 -0
- package/dist/assets/agents/mobile-dev.yaml +59 -0
- package/dist/assets/agents/operations-comms.yaml +58 -0
- package/dist/assets/agents/orchestrator.yaml +60 -0
- package/dist/assets/agents/qa-lead.yaml +60 -0
- package/dist/assets/agents/research-analyst.yaml +59 -0
- package/dist/assets/agents/security-ops.yaml +61 -0
- package/dist/assets/ai-context/system-prompt-context.md +32 -0
- package/dist/assets/journal/.gitkeep +0 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +2313 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Spell — Create Pull Request
|
|
3
|
+
description: Open a pull request for the current branch with an auto-generated title and description from commit history. Provider-agnostic (GitHub or Azure DevOps).
|
|
4
|
+
argument-hint: '[--draft] [--reviewers <name,...>] [--target <branch>] [--docs-only]'
|
|
5
|
+
agent: agent
|
|
6
|
+
last_updated: 2026-07-05
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Executive Summary
|
|
10
|
+
|
|
11
|
+
- This spell creates a pull request for the current feature branch — no manual title/description writing.
|
|
12
|
+
- It auto-generates a Conventional-Commits title and a structured description from the commit log.
|
|
13
|
+
- It is provider-agnostic: it detects GitHub vs Azure DevOps from the git remote and uses the right CLI.
|
|
14
|
+
- The PR is the only path to `main` (direct pushes are blocked by policy). See `.arcane/governance/git-conventions.md`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
Create a pull request for the current branch.
|
|
19
|
+
|
|
20
|
+
Context to consult:
|
|
21
|
+
|
|
22
|
+
- `.arcane/governance/git-conventions.md` — PR requirements, branch policy, merge strategy (the no-squash rule).
|
|
23
|
+
- `.arcane/governance/testing-standards.md` — coverage thresholds to cite in the description.
|
|
24
|
+
|
|
25
|
+
Related spells:
|
|
26
|
+
|
|
27
|
+
- `spell-commit-work` — land your work as Conventional-Commits commits before opening the PR.
|
|
28
|
+
- `spell-ship` — the broader release flow that records the PR URL after this spell creates it.
|
|
29
|
+
- `spell-address-review` — resolve reviewer feedback once the PR is open.
|
|
30
|
+
|
|
31
|
+
## Arguments
|
|
32
|
+
|
|
33
|
+
- `--draft` — create the PR as a draft (work-in-progress / early feedback).
|
|
34
|
+
- `--reviewers <name,...>` — comma-separated reviewers. Optional.
|
|
35
|
+
- `--target <branch>` — target branch (default `main`).
|
|
36
|
+
- `--docs-only` — lightweight mode for documentation-only changes: prefixes `[docs]` in the title, skips test-evidence/review sections, and enables auto-complete/auto-merge where the provider supports it.
|
|
37
|
+
|
|
38
|
+
## Step 0 — Guard checks
|
|
39
|
+
|
|
40
|
+
> **🛑 AGENT-MANDATORY PRE-PR CHECKLIST — READ FIRST.** Before *any* PR-creation call (this spell, raw `az repos pr create`, raw `gh pr create`, the `create_pull_request` MCP tool, REST, web hook, or anything else):
|
|
41
|
+
>
|
|
42
|
+
> 1. `git fetch origin`
|
|
43
|
+
> 2. `git rebase origin/<target-branch>` (default `main`) and resolve conflicts locally
|
|
44
|
+
> 3. `git push --force-with-lease` if the branch was already on origin
|
|
45
|
+
> 4. *Then* run the PR-creation call
|
|
46
|
+
>
|
|
47
|
+
> This rule is on the **agent**, not on the spell. Calling `az repos pr create` / `gh pr create` directly is **not** an escape hatch — it is a governance violation. See `.arcane/governance/git-conventions.md` → **🛑 Agent-mandatory pre-PR guard**.
|
|
48
|
+
|
|
49
|
+
1. Run `git branch --show-current`. **STOP** if on `main`/`master` — you cannot PR the integration branch into itself. Also **STOP** if detached HEAD (empty output) — check out a named branch first.
|
|
50
|
+
2. **Verify the target exists:** `git rev-parse --verify origin/<target>`. If it fails, `git fetch origin <target>`; if still missing, **STOP** and ask the user for the correct `--target`.
|
|
51
|
+
3. **Ensure the branch is on origin (upstream):** if `git rev-parse --abbrev-ref --symbolic-full-name @{u}` fails, the branch was never pushed — run `git push -u origin <branch>`. The provider CLIs can only open a PR for a branch that exists on the remote.
|
|
52
|
+
4. **STOP** if the branch has no commits ahead of the target: `git log origin/<target>..HEAD --oneline` is empty → nothing to PR.
|
|
53
|
+
5. Check for an existing **open** PR for this branch (provider-specific, Step 2). If one exists, print its URL and stop — never create duplicates.
|
|
54
|
+
6. **Mandatory rebase on target (governance guard):** `git fetch origin` then `git rebase origin/<target>`. On clean rebase, `git push --force-with-lease` (only if the branch existed remotely before the rebase). On conflicts: **STOP**, list conflicting files, ask the user to resolve; never push a branch that will produce a merge conflict on the target (see git-conventions "🛑 Agent-mandatory pre-PR guard"). This step is not optional and is not skippable by calling a different PR-creation tool.
|
|
55
|
+
7. **Auto-suggest `--docs-only`** (only if not already passed): if every changed file vs target is documentation/session files (`*.md`, `TODO.md`, `DECISIONS.md`, `journal/**`, `IDEAS.md`, `FEEDBACK.md`), print a one-line hint suggesting `--docs-only` and proceed with the standard path.
|
|
56
|
+
|
|
57
|
+
## Step 1 — Gather context
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git branch --show-current
|
|
61
|
+
git log origin/<target>..HEAD --format="%h %s" --reverse # commit list
|
|
62
|
+
git diff origin/<target>..HEAD --stat | tail -1 # files / insertions / deletions
|
|
63
|
+
git remote get-url origin # provider detection
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Step 2 — Detect provider
|
|
67
|
+
|
|
68
|
+
| Remote URL contains | Provider |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `github.com` | GitHub (`gh`) |
|
|
71
|
+
| `dev.azure.com` / `visualstudio.com` | Azure DevOps (`az repos`) |
|
|
72
|
+
| anything else | unknown — **STOP** and ask the user which provider/CLI to use |
|
|
73
|
+
|
|
74
|
+
If the detected provider's CLI is missing or unauthenticated (`gh auth status` / `az account show` fails), **STOP** with a clear message — do not silently fall back to the other provider.
|
|
75
|
+
|
|
76
|
+
Check for an existing **open** PR before creating (filter by state so a previously merged/closed PR for the same branch does not falsely block):
|
|
77
|
+
|
|
78
|
+
- **GitHub:** `gh pr list --head <branch> --base <target> --state open --json url --jq '.[0].url'`
|
|
79
|
+
- **Azure DevOps:** `az repos pr list --source-branch <branch> --target-branch <target> --status active --output json`
|
|
80
|
+
|
|
81
|
+
If an open PR is found, print its URL and stop.
|
|
82
|
+
|
|
83
|
+
## Step 3 — Build the title
|
|
84
|
+
|
|
85
|
+
Format: `type(scope): summary`
|
|
86
|
+
|
|
87
|
+
1. `type` = the majority commit type in the log (e.g. `feat`, `fix`, `chore`).
|
|
88
|
+
2. `scope` = optional; derive from the dominant changed area if obvious, else omit the parens.
|
|
89
|
+
3. `summary` = a concise one-line synthesis of the commits (≤ 72 chars per git-conventions), lowercase, imperative, no trailing period.
|
|
90
|
+
4. With `--docs-only`, prepend `[docs] `.
|
|
91
|
+
|
|
92
|
+
## Step 4 — Build the description
|
|
93
|
+
|
|
94
|
+
Write the body to a **temp file** and pass it to the provider CLI by file reference — never pass multiline content as a shell argument (this avoids shell/PowerShell truncation, quoting, and newline-mangling). Resolve the scratch path with `git rev-parse --git-dir` (handles worktrees and non-default `.git` locations) and write to `<git-dir>/arcane-pr-body.md`. The `.git` directory is never committed, so the body file is safe and ignored. Delete it after a successful create (Step 6).
|
|
95
|
+
|
|
96
|
+
Standard template:
|
|
97
|
+
|
|
98
|
+
```markdown
|
|
99
|
+
## Summary
|
|
100
|
+
|
|
101
|
+
<1–3 sentences synthesized from the commits — not copied verbatim.>
|
|
102
|
+
|
|
103
|
+
## Changes
|
|
104
|
+
|
|
105
|
+
### Features
|
|
106
|
+
- <feat summaries>
|
|
107
|
+
### Fixes
|
|
108
|
+
- <fix summaries>
|
|
109
|
+
### Infrastructure / Chores
|
|
110
|
+
- <chore/docs/ci/refactor summaries>
|
|
111
|
+
|
|
112
|
+
> Omit empty sections.
|
|
113
|
+
|
|
114
|
+
## Testing
|
|
115
|
+
|
|
116
|
+
- <coverage / test status if known, else "See CI pipeline results.">
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`--docs-only` template (skip Testing):
|
|
120
|
+
|
|
121
|
+
```markdown
|
|
122
|
+
## Summary
|
|
123
|
+
<1–2 sentences on the doc changes.>
|
|
124
|
+
|
|
125
|
+
## Changes
|
|
126
|
+
- <changed files or sections>
|
|
127
|
+
|
|
128
|
+
## Notes
|
|
129
|
+
Documentation-only PR. No functional code changed.
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Step 5 — Create the PR
|
|
133
|
+
|
|
134
|
+
- **GitHub:**
|
|
135
|
+
```bash
|
|
136
|
+
gh pr create --title "<title>" --body-file <temp> --base <target> --head <branch> [--draft] [--reviewer <r1,r2>]
|
|
137
|
+
```
|
|
138
|
+
With `--docs-only` and auto-merge enabled: `gh pr merge --auto <PR#>` (use the repo's configured merge method; do **not** force squash — see git-conventions).
|
|
139
|
+
- **Azure DevOps:**
|
|
140
|
+
```bash
|
|
141
|
+
az repos pr create --title "<title>" --description "@<temp>" --source-branch <branch> --target-branch <target> [--draft] [--reviewers "<r1> <r2>"]
|
|
142
|
+
```
|
|
143
|
+
With `--docs-only`, add `--auto-complete`. Respect the repo merge strategy — never enable squash (see git-conventions).
|
|
144
|
+
|
|
145
|
+
**Reviewers:** pass `--reviewers`/`--reviewer` values through as given. If a reviewer cannot be resolved by the provider, do **not** abort the create — let the PR be created and surface the unresolved name(s) in the Step 6 report so the user can add them manually.
|
|
146
|
+
|
|
147
|
+
**Post-create verification (both providers):** read the PR back (`gh pr view <PR#> --json url,title,body` / `az repos pr show --id <PR#>`). If the title or description is empty or does not match the temp file, patch it (`gh pr edit` / `az repos pr update`) from the temp file, then re-verify once. This guards against silent body truncation/drop on either CLI.
|
|
148
|
+
|
|
149
|
+
## Step 6 — Report
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
✓ PR created: <URL>
|
|
153
|
+
Title: <title>
|
|
154
|
+
PR #: <number>
|
|
155
|
+
Source → Target: <branch> → <target>
|
|
156
|
+
Reviewers: <list or "none assigned">
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
- If no reviewers were resolved (none passed, or names the provider could not match): `⚠ No reviewers assigned — add them in the PR or re-run with --reviewers`.
|
|
160
|
+
- If `--draft`: note it was created as a draft.
|
|
161
|
+
- Delete the body temp file (`<git-dir>/arcane-pr-body.md`) once the PR is confirmed created and verified.
|
|
162
|
+
|
|
163
|
+
## Rules
|
|
164
|
+
|
|
165
|
+
- Never create duplicate PRs — always check first (Step 2).
|
|
166
|
+
- Never push directly to `main` — the PR is the only path.
|
|
167
|
+
- Always write the description to a file before passing it to the provider CLI.
|
|
168
|
+
- Respect the repo merge strategy in `.arcane/governance/git-conventions.md` — **do not squash** (it breaks per-commit attribution).
|
|
169
|
+
- Print the PR URL clearly so it can be recorded by `spell-ship` / `spell-close-session`.
|
|
170
|
+
- Never include secrets or tokens in the title or description.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Spell — Document
|
|
3
|
+
description: Formalize valuable insights, analysis, or decisions from the current conversation into polished, permanent reference documents.
|
|
4
|
+
argument-hint: Topics and output paths (e.g., "capability inventory → docs/capabilities.md")
|
|
5
|
+
agent: agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Executive Summary
|
|
9
|
+
|
|
10
|
+
- This spell extracts substantive analysis from the current conversation and structures it into formal, durable documents.
|
|
11
|
+
- It bridges ephemeral chat context and lasting project documentation.
|
|
12
|
+
- Use it when a session produces reference material that deserves a proper home (inventories, comparisons, rationale, guides).
|
|
13
|
+
- For a quick one-line idea instead, use `spell-save-idea`. For session continuity, use `spell-close-session`.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Capture conversation insights and formalize them into well-structured documents.
|
|
18
|
+
|
|
19
|
+
The user's input describes what to capture and where. If no argument was provided, ask what they want to capture and stop until they answer.
|
|
20
|
+
|
|
21
|
+
**Before doing anything else, check that there is durable material to formalize.** Scan the conversation for substantive analysis, decisions, comparisons, or reference data. If the session holds nothing beyond small talk or trivial exchanges, say so plainly, suggest `spell-save-idea` for a quick capture instead, and stop — do not manufacture content to fill a document.
|
|
22
|
+
|
|
23
|
+
## Step 1 — Parse the Request
|
|
24
|
+
|
|
25
|
+
Identify:
|
|
26
|
+
|
|
27
|
+
- **Topics** — what conversation insights to extract (e.g., "naming analysis", "architecture comparison").
|
|
28
|
+
- **Target paths** — where to write (e.g., `docs/...`, `.arcane/governance/...`). If the user gives only topics, propose sensible paths from the project structure.
|
|
29
|
+
- **Document type** — reference doc, decision record, analysis report, inventory, or guide.
|
|
30
|
+
|
|
31
|
+
## Step 2 — Extract from Conversation
|
|
32
|
+
|
|
33
|
+
Gather all relevant material from context: tables, structured data, analysis results, comparisons, conclusions, recommendations, metrics/counts, and reasoning chains. Do not leave valuable insight behind in the chat.
|
|
34
|
+
|
|
35
|
+
## Step 3 — Structure into Documents
|
|
36
|
+
|
|
37
|
+
For each target, produce a polished structure:
|
|
38
|
+
|
|
39
|
+
- Title + metadata (clear heading, date, one-line context). Get the real date from the system (e.g., run `date`) rather than guessing.
|
|
40
|
+
- Table of contents for documents longer than ~3 sections.
|
|
41
|
+
- Proper sections with headers and logical flow.
|
|
42
|
+
- Tables and lists formatted for readability.
|
|
43
|
+
- Cross-references to related project files where relevant.
|
|
44
|
+
- A short provenance note (e.g., _"Captured from a development session on YYYY-MM-DD."_) so future readers know its origin.
|
|
45
|
+
|
|
46
|
+
Match the tone, frontmatter, and structure of files already in the target directory before inventing your own format.
|
|
47
|
+
|
|
48
|
+
## Step 4 — Show Proposal
|
|
49
|
+
|
|
50
|
+
Present before writing. For each target, check whether the file already exists and label it `(new)` or `(exists — will diff before writing)` so approval is informed, not blind:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
## Document Proposal
|
|
54
|
+
|
|
55
|
+
### 1. <path/to/file.md> (new)
|
|
56
|
+
- Type: <reference / analysis / inventory / guide>
|
|
57
|
+
- Sections: <list>
|
|
58
|
+
- Preview:
|
|
59
|
+
<first 10–15 lines>
|
|
60
|
+
|
|
61
|
+
### 2. <another path> (exists — will diff before writing)
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
Approve? (yes / edit / skip)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Step 5 — Apply (after approval)
|
|
68
|
+
|
|
69
|
+
1. Write each new document to its target path.
|
|
70
|
+
2. If a target already exists, do not silently overwrite. Show a diff preview of the proposed change against the current file and confirm. Prefer merging the new content into the existing structure (append a section, update a table) over replacing the whole file, unless the user asked for a full rewrite. State which mode you are using before writing.
|
|
71
|
+
3. Do NOT commit — leave that to `spell-commit-work`.
|
|
72
|
+
4. Confirm what was written and where (path + new-vs-updated per file).
|
|
73
|
+
|
|
74
|
+
## Rules
|
|
75
|
+
|
|
76
|
+
- Only formalize material actually present in the conversation — do not invent, infer, or pad content to fill a section.
|
|
77
|
+
- If nothing substantive is in the conversation, stop and route to `spell-save-idea` rather than producing an empty document.
|
|
78
|
+
- Follow existing documentation patterns in the target directory.
|
|
79
|
+
- Never overwrite an existing file without an explicit diff confirmation; prefer merging over clobbering.
|
|
80
|
+
- Never include secrets, tokens, or credentials in a document.
|
|
81
|
+
- Do not commit the changes — that is `spell-commit-work`'s job.
|
|
82
|
+
|
|
83
|
+
> **Tip:** Run `spell-close-session` afterward to log the session, or `spell-commit-work` to commit the new documents.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Spell — .NET Expert
|
|
3
|
+
description: Load .NET best practices and patterns for any development agent working on .NET projects
|
|
4
|
+
argument-hint: Specific .NET topic or question (e.g., "Azure Functions isolated worker", "EF Core migrations")
|
|
5
|
+
agent: agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Executive Summary
|
|
9
|
+
|
|
10
|
+
- This prompt loads .NET expertise into any agent's context — no dedicated .NET agent needed, per your org's decision/security log if one exists.
|
|
11
|
+
- Covers .NET 10, ASP.NET Core, Azure Functions (isolated worker), Entity Framework Core, and xUnit testing.
|
|
12
|
+
- Use this when any dev agent is working on `{BUSINESS_NAME}` or other .NET projects. (`{BUSINESS_NAME}`: resolve from `.arcane.json` / the feature or PRD frontmatter; ask if unset.) For the dev-agent roster, reference [[agent-policies]] / [[naming-conventions]] rather than assuming specific personas.
|
|
13
|
+
- Combines with `spell-implement` for .NET-specific autonomous development loops.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Load .NET expert context and assist with the specified topic.
|
|
18
|
+
|
|
19
|
+
Context to apply:
|
|
20
|
+
|
|
21
|
+
### .NET Project Standards
|
|
22
|
+
|
|
23
|
+
- **Target Framework:** .NET 10 (latest LTS)
|
|
24
|
+
- **API Pattern:** ASP.NET Core Minimal APIs (preferred) or Controllers (existing projects)
|
|
25
|
+
- **Serverless:** Azure Functions v4 isolated worker model (NOT in-process)
|
|
26
|
+
- **ORM:** Entity Framework Core with code-first migrations
|
|
27
|
+
- **Testing:** xUnit + FluentAssertions + Moq (or NSubstitute)
|
|
28
|
+
- **DI:** Built-in Microsoft.Extensions.DependencyInjection
|
|
29
|
+
- **Logging:** Serilog with structured logging (JSON output)
|
|
30
|
+
- **Configuration:** Options pattern (`IOptions<T>`) — never read config directly
|
|
31
|
+
|
|
32
|
+
### Code Patterns
|
|
33
|
+
|
|
34
|
+
```csharp
|
|
35
|
+
// Minimal API pattern
|
|
36
|
+
app.MapGet("/api/items/{id}", async (int id, IItemService service) =>
|
|
37
|
+
{
|
|
38
|
+
var item = await service.GetByIdAsync(id);
|
|
39
|
+
return item is null ? Results.NotFound() : Results.Ok(item);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Service registration
|
|
43
|
+
builder.Services.AddScoped<IItemService, ItemService>();
|
|
44
|
+
builder.Services.Configure<ItemOptions>(builder.Configuration.GetSection("Items"));
|
|
45
|
+
|
|
46
|
+
// Azure Function (isolated worker)
|
|
47
|
+
[Function("ProcessItem")]
|
|
48
|
+
public async Task<HttpResponseData> Run(
|
|
49
|
+
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
|
|
50
|
+
{
|
|
51
|
+
var item = await req.ReadFromJsonAsync<ItemRequest>();
|
|
52
|
+
// Process...
|
|
53
|
+
var response = req.CreateResponse(HttpStatusCode.OK);
|
|
54
|
+
await response.WriteAsJsonAsync(result);
|
|
55
|
+
return response;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Testing Patterns
|
|
60
|
+
|
|
61
|
+
```csharp
|
|
62
|
+
// xUnit test with FluentAssertions
|
|
63
|
+
public class ItemServiceTests
|
|
64
|
+
{
|
|
65
|
+
[Fact]
|
|
66
|
+
public async Task GetById_WhenExists_ReturnsItem()
|
|
67
|
+
{
|
|
68
|
+
// Arrange
|
|
69
|
+
var mockRepo = new Mock<IItemRepository>();
|
|
70
|
+
mockRepo.Setup(r => r.GetByIdAsync(1))
|
|
71
|
+
.ReturnsAsync(new Item { Id = 1, Name = "Test" });
|
|
72
|
+
var service = new ItemService(mockRepo.Object);
|
|
73
|
+
|
|
74
|
+
// Act
|
|
75
|
+
var result = await service.GetByIdAsync(1);
|
|
76
|
+
|
|
77
|
+
// Assert
|
|
78
|
+
result.Should().NotBeNull();
|
|
79
|
+
result!.Name.Should().Be("Test");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Common Pitfalls to Avoid
|
|
85
|
+
|
|
86
|
+
- **Don't use `HttpClient` directly** — use `IHttpClientFactory` with named/typed clients.
|
|
87
|
+
- **Don't catch `Exception`** — catch specific types. Let unhandled exceptions bubble to middleware.
|
|
88
|
+
- **Don't use `async void`** — always `async Task`. Exception: event handlers.
|
|
89
|
+
- **Don't block on async** — never use `.Result` or `.Wait()`. Use `await`.
|
|
90
|
+
- **Don't put business logic in controllers/endpoints** — use a service layer.
|
|
91
|
+
- **Don't use `DateTime.Now`** — use `DateTimeOffset.UtcNow` or inject `TimeProvider`.
|
|
92
|
+
- **Don't store secrets in appsettings.json** — use User Secrets (dev) or Azure Key Vault (prod).
|
|
93
|
+
|
|
94
|
+
### NuGet Package Standards
|
|
95
|
+
|
|
96
|
+
Always pin exact versions. Preferred packages:
|
|
97
|
+
- `Microsoft.EntityFrameworkCore` — ORM
|
|
98
|
+
- `Serilog.AspNetCore` — logging
|
|
99
|
+
- `FluentValidation` — input validation
|
|
100
|
+
- `Polly` — resilience and retry policies
|
|
101
|
+
- `Mapster` or `AutoMapper` — object mapping
|
|
102
|
+
- `Swashbuckle.AspNetCore` — OpenAPI/Swagger
|
|
103
|
+
|
|
104
|
+
### Azure-Specific Patterns
|
|
105
|
+
|
|
106
|
+
- Use Managed Identity for Azure service authentication (no connection strings with keys).
|
|
107
|
+
- Use Azure Key Vault references in App Service/Functions configuration.
|
|
108
|
+
- Use Application Insights for telemetry (`AddApplicationInsightsTelemetry()`).
|
|
109
|
+
- Use Azure Storage Queue or Service Bus for async messaging (not HTTP callbacks).
|
|
110
|
+
|
|
111
|
+
Workflow:
|
|
112
|
+
|
|
113
|
+
1. **Identify the .NET topic** — what does the developer need help with?
|
|
114
|
+
2. **Apply the patterns above** — use the standards as constraints.
|
|
115
|
+
3. **Provide implementation guidance** — specific code, not just concepts.
|
|
116
|
+
4. **Include tests** — every code suggestion includes corresponding xUnit tests.
|
|
117
|
+
5. **Flag deviations** — if the existing codebase doesn't follow these patterns, note it but don't refactor without approval.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Spell — EAS iOS Deploy
|
|
3
|
+
description: Ship an Expo/React Native app to TestFlight and the App Store via EAS Build + EAS Submit — initial one-time setup and every deploy after that
|
|
4
|
+
argument-hint: What you need — "initial setup", "deploy" (cut + submit a new build), or a specific symptom (e.g. "capability sync failed", "build stuck")
|
|
5
|
+
agent: agent
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Executive Summary
|
|
9
|
+
|
|
10
|
+
- This prompt ships an Expo/React Native app to Apple TestFlight/App Store using **EAS Build + EAS
|
|
11
|
+
Submit** — Expo's cloud build service. No local Mac or Xcode install is required.
|
|
12
|
+
- Covers two flows: **initial one-time setup** (Apple enrollment → credentials → first build →
|
|
13
|
+
first submit) and **repeat deployments** (the two-command loop you run for every release after that).
|
|
14
|
+
- Produces a signed production build uploaded to App Store Connect, visible in TestFlight once Apple
|
|
15
|
+
finishes processing it, with the app's native build number bumped and committed to the repo.
|
|
16
|
+
- **Not** a general CI/CD ship spell — see `spell-ship` for the branch-merge / backend-deploy
|
|
17
|
+
lifecycle. This spell is the mobile-app-store-specific leaf step, and it is scoped deliberately to
|
|
18
|
+
the **EAS Build/Submit** tech stack — it does not cover local Xcode builds, Xcode Cloud, or Fastlane.
|
|
19
|
+
A team on one of those instead needs a different spell; the steps below assume EAS.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
Ship the app to TestFlight/App Store, or troubleshoot an EAS deploy issue, per the request in the
|
|
24
|
+
prompt argument. If no argument was given, ask whether this is initial setup or a repeat deploy.
|
|
25
|
+
|
|
26
|
+
### Placeholders
|
|
27
|
+
|
|
28
|
+
Resolve each from `.arcane.json` / the project's `app.json` / `eas.json` / frontmatter; **ask the
|
|
29
|
+
user rather than guessing or inventing a value** if any is unset. Never proceed with an unresolved
|
|
30
|
+
placeholder still in a command you're about to run.
|
|
31
|
+
|
|
32
|
+
| Placeholder | What it is | Where it lives once resolved |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `{APP_NAME}` | Display name shown on the App Store / home screen | `app.json` → `expo.name` |
|
|
35
|
+
| `{BUNDLE_ID}` | iOS bundle identifier (and Android package, if shipping both) | `app.json` → `expo.ios.bundleIdentifier` |
|
|
36
|
+
| `{APPLE_TEAM_ID}` | Apple Developer Team ID | `eas.json` → `submit.production.ios.appleTeamId` |
|
|
37
|
+
| `{ASC_APP_ID}` | Numeric App Store Connect app ID | `eas.json` → `submit.production.ios.ascAppId` |
|
|
38
|
+
| `{APPLE_ID_EMAIL}` | Apple ID used for the Developer/ASC account | `eas.json` → `submit.production.ios.appleId` |
|
|
39
|
+
| `{EAS_PROJECT_ID}` | EAS/Expo project ID | `app.json` → `expo.extra.eas.projectId` |
|
|
40
|
+
| `{EAS_ACCOUNT}` | EAS/Expo account or org slug the project lives under | `eas build`/`eas submit` output, or `eas whoami` |
|
|
41
|
+
|
|
42
|
+
### Context files this spell reads
|
|
43
|
+
|
|
44
|
+
- **`app.json`/`app.config.js`** (Expo config) — bundle identifier, current `version`, native
|
|
45
|
+
`buildNumber`, EAS project ID. If it doesn't exist, this isn't an Expo project — stop and say so.
|
|
46
|
+
- **`eas.json`** — build + submit profiles. **If missing**, run `eas build:configure` first (it
|
|
47
|
+
scaffolds a starter `eas.json` interactively) before continuing with the steps below.
|
|
48
|
+
- **Apple Developer Program membership** for `{APPLE_ID_EMAIL}` — must be an active, paid enrollment.
|
|
49
|
+
If you don't know whether it's active, ask the user to confirm at
|
|
50
|
+
developer.apple.com/account before starting initial setup — everything downstream depends on it.
|
|
51
|
+
|
|
52
|
+
If **none** of these exist yet (a brand-new Expo project with no `eas.json` and no App Store Connect
|
|
53
|
+
app record), start at **Phase A, step 1** — every step is written to work from that empty state.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Phase A — Initial one-time setup
|
|
58
|
+
|
|
59
|
+
Run once per app. Skip to Phase B if `eas.json` already has a `submit.production.ios` block and a
|
|
60
|
+
first build has already reached TestFlight.
|
|
61
|
+
|
|
62
|
+
1. **Confirm Apple Developer Program enrollment** is active for `{APPLE_ID_EMAIL}` (paid,
|
|
63
|
+
developer.apple.com/account). Nothing below works without it.
|
|
64
|
+
2. **Create the App Store Connect app record** — appstoreconnect.apple.com → My Apps → "+" → New App.
|
|
65
|
+
Fill in `{APP_NAME}`, `{BUNDLE_ID}` (create a matching Identifier first if one doesn't exist yet),
|
|
66
|
+
a SKU, and user access. Capture the numeric app ID it's assigned — that's `{ASC_APP_ID}`.
|
|
67
|
+
3. **Log in to EAS**: `npx eas-cli login` (skip if already authenticated — `eas whoami` confirms).
|
|
68
|
+
4. **Configure `eas.json`** if it doesn't already have what's needed:
|
|
69
|
+
```jsonc
|
|
70
|
+
{
|
|
71
|
+
"cli": { "appVersionSource": "local" },
|
|
72
|
+
"build": {
|
|
73
|
+
"production": { "channel": "production", "autoIncrement": true }
|
|
74
|
+
},
|
|
75
|
+
"submit": {
|
|
76
|
+
"production": {
|
|
77
|
+
"ios": {
|
|
78
|
+
"appleId": "{APPLE_ID_EMAIL}",
|
|
79
|
+
"ascAppId": "{ASC_APP_ID}",
|
|
80
|
+
"appleTeamId": "{APPLE_TEAM_ID}"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
`appVersionSource: "local"` + `autoIncrement: true` on the build profile means EAS bumps the
|
|
87
|
+
native build number in `app.json` for you on every build — no manual version-bump step, ever.
|
|
88
|
+
5. **First build**: `eas build --platform ios --profile production`. On a project with no
|
|
89
|
+
credentials yet, EAS interactively generates everything it needs **remotely** — Distribution
|
|
90
|
+
Certificate, Provisioning Profile, and (if the app uses push) an APNs key. No local keychain, no
|
|
91
|
+
Mac. Confirm each prompt; let EAS manage the private key material — you should never need to see
|
|
92
|
+
or copy it.
|
|
93
|
+
6. **First submit**: `eas submit --platform ios --profile production --latest`. First time through,
|
|
94
|
+
it also sets up an **App Store Connect API key** for non-interactive submits (EAS-managed is
|
|
95
|
+
simplest — pick that unless there's a reason to upload your own). Confirm the role it grants when
|
|
96
|
+
asked (App Manager is enough for build submission).
|
|
97
|
+
7. **Confirm it landed**: App Store Connect → your app → TestFlight → iOS builds. Apple's binary
|
|
98
|
+
processing takes ~5–10 minutes after a successful `eas submit` before the build appears there.
|
|
99
|
+
|
|
100
|
+
## Phase B — Repeat deployments
|
|
101
|
+
|
|
102
|
+
The two-command loop for every release after Phase A:
|
|
103
|
+
|
|
104
|
+
1. Land the code changes; typecheck/build clean locally first.
|
|
105
|
+
2. `eas build --platform ios --profile production --non-interactive`
|
|
106
|
+
(add `EXPO_NO_CAPABILITY_SYNC=1` up front if you know a capability-sync failure is coming —
|
|
107
|
+
see **Known pitfalls** below).
|
|
108
|
+
3. `eas submit --platform ios --profile production --latest --non-interactive`
|
|
109
|
+
4. **Commit the build-number bump**: step 2's `autoIncrement` rewrote `app.json`'s native build
|
|
110
|
+
number locally — `git add`/`git commit` it so the repo matches the binary that just shipped.
|
|
111
|
+
5. Confirm in TestFlight (same as Phase A step 7).
|
|
112
|
+
|
|
113
|
+
Re-running either command is always safe: `eas build` reuses existing valid credentials rather than
|
|
114
|
+
regenerating them (it only creates new ones when something actually changed, like a new capability),
|
|
115
|
+
and re-running `eas submit` after a failed attempt is a normal retry, not a duplicate submission risk.
|
|
116
|
+
|
|
117
|
+
## Known pitfalls (verified, not hypothetical)
|
|
118
|
+
|
|
119
|
+
- **"Failed to patch capabilities: X ON, Y OFF"** — happens when the App Store Connect app record is
|
|
120
|
+
already linked to `{BUNDLE_ID}` and Apple rejects EAS's automatic capability sync. Fix: set
|
|
121
|
+
`EXPO_NO_CAPABILITY_SYNC=1` for the build command, **and** manually toggle the capability (Push
|
|
122
|
+
Notifications, Sign in with Apple, Associated Domains, whatever the app just added) on in the Apple
|
|
123
|
+
Developer console under Identifiers → `{BUNDLE_ID}` → Capabilities. EAS syncing capabilities and you
|
|
124
|
+
toggling them by hand are two ways to the same end state; when the app is already linked, only the
|
|
125
|
+
manual toggle works.
|
|
126
|
+
- **"Command must be re-run to pick up new updates configuration"** — EAS auto-installed
|
|
127
|
+
`expo-updates` mid-build because the config needed it and it wasn't present. Just re-run the exact
|
|
128
|
+
same build command once; it picks up cleanly the second time.
|
|
129
|
+
- **A brand-new entitlement was just added** (e.g. Associated Domains, Sign in with Apple) — confirm
|
|
130
|
+
the App ID capability is toggled on in the Apple Developer console *before* building. A successful
|
|
131
|
+
build with a fresh "Provisioning Profile ... Updated: N seconds ago" in the credentials output is
|
|
132
|
+
itself the confirmation that the new entitlement is correctly provisioned — if the capability isn't
|
|
133
|
+
on yet, the build will fail at the signing step instead.
|
|
134
|
+
- **Apple "Internal Server Error"** during API key creation or submission — Apple's servers are
|
|
135
|
+
occasionally flaky. Retry the identical command; no code or config change needed.
|
|
136
|
+
- **Build succeeds but nothing changed on-device** — before assuming the deploy is broken, rule out
|
|
137
|
+
the mundane cause first: the tester didn't force-quit and reopen the app after installing the new
|
|
138
|
+
TestFlight build (a backgrounded process can survive an update). Confirm the visible build/version
|
|
139
|
+
number inside the app (a settings screen, an About row) matches what you just shipped before
|
|
140
|
+
debugging further.
|
|
141
|
+
|
|
142
|
+
## Acceptance checklist
|
|
143
|
+
|
|
144
|
+
- [ ] `eas build` output ends with "Build finished" and an artifact URL.
|
|
145
|
+
- [ ] `eas submit` output ends with "Submitted your app to Apple App Store Connect!"
|
|
146
|
+
- [ ] App Store Connect → TestFlight → iOS builds shows the new build number (allow 5–10 min for
|
|
147
|
+
Apple's processing).
|
|
148
|
+
- [ ] The `autoIncrement`-bumped build number in `app.json` is committed — `git status` is clean.
|
|
149
|
+
- [ ] If an entitlement changed this deploy, it visibly works on a fresh install of the new build.
|
|
150
|
+
|
|
151
|
+
## Cross-references
|
|
152
|
+
|
|
153
|
+
- **`spell-ship`** — the surrounding branch-merge / backend-CI-CD lifecycle, if this app ships
|
|
154
|
+
alongside a paired backend. This spell is the mobile-store-specific leaf step; run it after
|
|
155
|
+
`spell-ship`'s checklist is green for anything the app depends on, not instead of it.
|
|
156
|
+
- **`spell-dotnet-expert`** and other stack-expert spells — the sibling "load expertise into any
|
|
157
|
+
agent" pattern. This spell goes one step further: it doesn't just load context, it executes the
|
|
158
|
+
actual build/submit commands.
|
|
159
|
+
- **`spell-bump`** — coordinate with it if the app's marketing `version` (not just the native build
|
|
160
|
+
number this spell auto-increments) also needs a bump before shipping.
|
|
161
|
+
- **`spell-todo`** — if a pitfall or gap surfaces mid-deploy that shouldn't block shipping today,
|
|
162
|
+
capture it there rather than scope-creeping this deploy.
|
|
163
|
+
|
|
164
|
+
## Rules
|
|
165
|
+
|
|
166
|
+
- **Never guess a placeholder.** If `{BUNDLE_ID}`, `{APPLE_TEAM_ID}`, `{ASC_APP_ID}`, or
|
|
167
|
+
`{APPLE_ID_EMAIL}` is unresolved, ask — do not invent a value or proceed with a literal placeholder
|
|
168
|
+
string in a real command.
|
|
169
|
+
- **Never handle real credential material.** You should never need to see, paste, or commit a
|
|
170
|
+
Distribution Certificate private key, an App Store Connect API private key (`.p8`), or any
|
|
171
|
+
password — EAS manages all of it remotely. If a step seems to require pasting one, stop; something
|
|
172
|
+
is set up wrong.
|
|
173
|
+
- **Confirm before `eas submit`.** Submitting puts a real binary in front of Apple's review /
|
|
174
|
+
TestFlight testers — it's outward-facing and not something to undo casually. Say what you're about
|
|
175
|
+
to submit and to which environment before running it.
|
|
176
|
+
- **Confirm before setting `EXPO_NO_CAPABILITY_SYNC=1`.** Explain why it's needed (it disables an
|
|
177
|
+
automatic sync that would otherwise silently turn a capability off) rather than setting it
|
|
178
|
+
silently.
|
|
179
|
+
- **Never force-regenerate credentials** (revoke + recreate a Distribution Certificate or
|
|
180
|
+
Provisioning Profile) without explicit confirmation — revoking a certificate invalidates every
|
|
181
|
+
build ever signed with it, including ones already live.
|
|
182
|
+
- **A backend/API prod deploy the app depends on is a separate, separately-confirmed action.** Do
|
|
183
|
+
not fold it into a mobile build/submit step just because they're related.
|