@jenga-ai/agent 1.0.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 (177) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +340 -0
  3. package/agents/ai_engineer.md +113 -0
  4. package/agents/developer.md +236 -0
  5. package/agents/scrum-master.md +349 -0
  6. package/agents/scrutiny-agent.md +137 -0
  7. package/agents/solution-assessor.md +185 -0
  8. package/agents/tester.md +339 -0
  9. package/bin/jenga.js +70 -0
  10. package/hooks/copilot_session_end.sh +29 -0
  11. package/hooks/on_session_end.sh +238 -0
  12. package/hooks/prompt_router.sh +11 -0
  13. package/hooks/prompt_router_helper.js +52 -0
  14. package/hooks/session_end_helper.js +29 -0
  15. package/hooks/session_end_watcher.sh +24 -0
  16. package/lib/commands/attach.js +47 -0
  17. package/lib/commands/init.js +207 -0
  18. package/lib/commands/start.js +16 -0
  19. package/lib/commands/status.js +53 -0
  20. package/lib/config-schema.js +72 -0
  21. package/lib/inject-settings.js +61 -0
  22. package/lib/mirror.js +244 -0
  23. package/lib/resolve-project-dir.sh +47 -0
  24. package/mcp/execute-ticket/index.js +10 -0
  25. package/mcp/execute-ticket/package.json +5 -0
  26. package/mcp/help/index.js +79 -0
  27. package/mcp/help/package.json +14 -0
  28. package/mcp/router/README.md +19 -0
  29. package/mcp/router/embedder.js +23 -0
  30. package/mcp/router/index.js +204 -0
  31. package/mcp/router/matcher.js +87 -0
  32. package/mcp/router/package-lock.json +1048 -0
  33. package/mcp/router/package.json +11 -0
  34. package/mcp/router/skill-index.js +104 -0
  35. package/package.json +47 -0
  36. package/scripts/board_resolver.sh +46 -0
  37. package/scripts/e25_s01_extract_board_graph.py +292 -0
  38. package/scripts/e25_s01_generate_synthetic_board.py +90 -0
  39. package/scripts/measurement-10x.json +50 -0
  40. package/scripts/measurement-10x.txt +4 -0
  41. package/scripts/measurement-real.json +50 -0
  42. package/scripts/measurement-real.txt +4 -0
  43. package/scripts/postinstall.js +165 -0
  44. package/scripts/todo_cleanup.sh +22 -0
  45. package/scripts/todo_manager.sh +86 -0
  46. package/scripts/validate-board.sh +190 -0
  47. package/scripts/validate-story-format.sh +53 -0
  48. package/skills/brainstorm/SKILL.md +47 -0
  49. package/skills/btw/SKILL.md +42 -0
  50. package/skills/commit/SKILL.md +29 -0
  51. package/skills/commit/assets/user_instructions_template.md +22 -0
  52. package/skills/continue/SKILL.md +29 -0
  53. package/skills/convert/SKILL.md +124 -0
  54. package/skills/convert/convert_cli.py +235 -0
  55. package/skills/convert/tests/sample.csv +4 -0
  56. package/skills/convert/tests/sample.json +5 -0
  57. package/skills/convert/tests/sample.jsonl +3 -0
  58. package/skills/convert/tests/sample.yaml +18 -0
  59. package/skills/convert/tests/sample_obj.csv +2 -0
  60. package/skills/convert/tests/sample_obj.json +9 -0
  61. package/skills/deep-dive/SKILL.md +167 -0
  62. package/skills/do/SKILL.md +88 -0
  63. package/skills/do/assets/sender_template.json +12 -0
  64. package/skills/doc/SKILL.md +314 -0
  65. package/skills/doc/assets/path-objectives.yaml +38 -0
  66. package/skills/doc-sync/SKILL.md +167 -0
  67. package/skills/doc-sync/assets/default_excludes.txt +21 -0
  68. package/skills/doc-sync/assets/doc_targets.md +14 -0
  69. package/skills/dooo/SKILL.md +60 -0
  70. package/skills/error/SKILL.md +29 -0
  71. package/skills/evaluate/SKILL.md +45 -0
  72. package/skills/evaluate/assets/evaluation_invokation_template.yml +3 -0
  73. package/skills/evaluate/assets/evaluation_rapport_template.md +24 -0
  74. package/skills/examplify/SKILL.md +42 -0
  75. package/skills/help/SKILL.md +36 -0
  76. package/skills/improve/SKILL.md +55 -0
  77. package/skills/index/scripts/board-index +4 -0
  78. package/skills/index/scripts/board_index.py +615 -0
  79. package/skills/index/scripts/smoke_test.sh +86 -0
  80. package/skills/init/SKILL.md +44 -0
  81. package/skills/init/assets/.gitignore_template +15 -0
  82. package/skills/init/assets/PROJECT_SUMMARY_template.md +13 -0
  83. package/skills/init/assets/directory_structure.txt +13 -0
  84. package/skills/init/assets/test-config_template.json +4 -0
  85. package/skills/init/assets/workflow_template.json +30 -0
  86. package/skills/init/scripts/init.sh +48 -0
  87. package/skills/jbp/SKILL.md +25 -0
  88. package/skills/jenga/SKILL.md +68 -0
  89. package/skills/lgtm/SKILL.md +21 -0
  90. package/skills/mirror-public/SKILL.md +237 -0
  91. package/skills/mirror-public/assets/config.json +5 -0
  92. package/skills/mirror-public/scripts/mirror.sh +374 -0
  93. package/skills/pi-plan/SKILL.md +62 -0
  94. package/skills/pi-plan/assets/epic.json +7 -0
  95. package/skills/pi-plan/assets/story_template.md +18 -0
  96. package/skills/proceed/SKILL.md +29 -0
  97. package/skills/publish/SKILL.md +351 -0
  98. package/skills/publish/adapters/droplet.md +200 -0
  99. package/skills/publish/adapters/mobile-ios.md +114 -0
  100. package/skills/publish/adapters/npm-ci.md +223 -0
  101. package/skills/publish/adapters/npm.md +121 -0
  102. package/skills/publish/assets/ExportOptions.plist.template +19 -0
  103. package/skills/publish/assets/ci-contract.md +111 -0
  104. package/skills/publish/assets/ownership-matrix.md +17 -0
  105. package/skills/publish/assets/publish.example.json +85 -0
  106. package/skills/publish/assets/publish.example.npm-ci.json +40 -0
  107. package/skills/publish/assets/publish.example.npm.json +41 -0
  108. package/skills/publish/assets/secrets-guide.md +104 -0
  109. package/skills/publish/schemas/fixtures/npm-ci-minimal.json +17 -0
  110. package/skills/publish/schemas/fixtures/npm-ci-with-empty-secrets.json +18 -0
  111. package/skills/publish/schemas/fixtures/npm-ci-with-workflow-path.json +18 -0
  112. package/skills/publish/schemas/publish.schema.json +428 -0
  113. package/skills/publish/scripts/check_target_config.sh +96 -0
  114. package/skills/publish/scripts/droplet_pipeline.sh +208 -0
  115. package/skills/publish/scripts/generate_release_notes.sh +200 -0
  116. package/skills/publish/scripts/ios_pipeline.sh +486 -0
  117. package/skills/publish/scripts/npm_ci_pipeline.sh +225 -0
  118. package/skills/publish/scripts/npm_pipeline.sh +249 -0
  119. package/skills/publish/scripts/publish_common.sh +253 -0
  120. package/skills/publish/scripts/publish_deploy.sh +538 -0
  121. package/skills/publish/scripts/reconcile_tags.sh +135 -0
  122. package/skills/publish/scripts/run_gates.sh +616 -0
  123. package/skills/publish/scripts/setup_wizard.sh +394 -0
  124. package/skills/publish/scripts/show_history.sh +95 -0
  125. package/skills/publish/scripts/suggest_semver_bump.sh +105 -0
  126. package/skills/publish/scripts/validate_config.sh +163 -0
  127. package/skills/publish/scripts/validate_droplet_env.sh +45 -0
  128. package/skills/publish/scripts/validate_ios_env.sh +68 -0
  129. package/skills/publish/scripts/validate_npm_ci_env.sh +71 -0
  130. package/skills/publish/scripts/validate_npm_env.sh +22 -0
  131. package/skills/publish/scripts/write_ledger_entry.sh +126 -0
  132. package/skills/publish/wizards/droplet.md +275 -0
  133. package/skills/publish/wizards/mobile-ios.md +157 -0
  134. package/skills/publish/wizards/npm-ci.md +240 -0
  135. package/skills/publish/wizards/npm.md +224 -0
  136. package/skills/reconcile/SKILL.md +93 -0
  137. package/skills/reconcile/assets/report_format.md +44 -0
  138. package/skills/reconcile-origin/SKILL.md +75 -0
  139. package/skills/reconcile-origin/scripts/reconcile-origin.sh +372 -0
  140. package/skills/redo/SKILL.md +70 -0
  141. package/skills/route/SKILL.md +180 -0
  142. package/skills/self-sync/SKILL.md +73 -0
  143. package/skills/self-sync/scripts/run.js +136 -0
  144. package/skills/skillify/SKILL.md +68 -0
  145. package/skills/skillify/assets/init-new/SKILL.md +35 -0
  146. package/skills/skillify/assets/init-new/assets/.gitignore_template +15 -0
  147. package/skills/skillify/assets/init-new/assets/PROJECT_SUMMARY_template.md +13 -0
  148. package/skills/skillify/assets/init-new/assets/directory_structure.txt +10 -0
  149. package/skills/skillify/assets/init-new/assets/test-config_template.json +4 -0
  150. package/skills/skillify/assets/init-new/assets/workflow_template.json +17 -0
  151. package/skills/skillify/assets/init-new/scripts/init.sh +48 -0
  152. package/skills/skillify/assets/init-old/SKILL.md +124 -0
  153. package/skills/spinoff/SKILL.md +48 -0
  154. package/skills/status/SKILL.md +33 -0
  155. package/skills/status/assets/output_format.md +41 -0
  156. package/skills/todo/SKILL.md +46 -0
  157. package/skills/todo/assets/todo_handoff_template.md +22 -0
  158. package/skills/todo/assets/todo_template.md +3 -0
  159. package/skills/train/SKILL.md +116 -0
  160. package/skills/train/assets/dashboard-templates/classifiers.html +106 -0
  161. package/skills/train/assets/dashboard-templates/nlp.html +102 -0
  162. package/skills/train/assets/dashboard-templates/transformers.html +98 -0
  163. package/skills/train/assets/results-parsers/__init__.py +9 -0
  164. package/skills/train/assets/results-parsers/classifiers.py +84 -0
  165. package/skills/train/assets/results-parsers/nlp.py +88 -0
  166. package/skills/train/assets/results-parsers/reporter.py +154 -0
  167. package/skills/train/assets/results-parsers/transformers.py +120 -0
  168. package/skills/train/train_cli.py +786 -0
  169. package/templates/EXECUTION_PLAN_TEMPLATE.md +43 -0
  170. package/templates/EXECUTION_SUMMARY_TEMPLATE.md +50 -0
  171. package/templates/JENGA_CONFIG_TEMPLATE.json +23 -0
  172. package/templates/PROBLEM_RAPPORT_TEMPLATE.md +88 -0
  173. package/templates/SCRUM_BOARD_SCHEMA.md +311 -0
  174. package/templates/SKILL.md +16 -0
  175. package/templates/SKILL_TEMPLATE.md +28 -0
  176. package/templates/USER_INSTRUCTIONS_TEMPLATE.md +22 -0
  177. package/templates/copilot-instructions.md.tpl +55 -0
@@ -0,0 +1,351 @@
1
+ ---
2
+ name: publish
3
+ description: Configure, validate, and orchestrate scaffolded release workflows through a single `/publish` entry point with bounded sub-commands.
4
+ keywords:
5
+ - publish
6
+ - deploy
7
+ - release
8
+ - app store
9
+ - npm
10
+ - registry
11
+ - release notes
12
+ examples:
13
+ - "publish setup --target staging-appstore"
14
+ - "publish setup --type mobile-ios"
15
+ - "publish setup --type npm"
16
+ - "publish deploy --target staging-appstore --yes --dry-run"
17
+ - "publish deploy --target npm-registry"
18
+ - "publish deploy --target npm-registry --dry-run"
19
+ - "publish setup --type droplet"
20
+ - "publish deploy --target my-droplet"
21
+ - "publish deploy --target my-droplet --dry-run"
22
+ - "publish history --limit 5"
23
+ - "publish release-notes --target staging-appstore"
24
+ metadata:
25
+ scope: multi-target-v2
26
+ primary_target: multi
27
+ primary_platform: multi
28
+ supported_target_types:
29
+ - mobile-ios
30
+ - npm
31
+ - npm-ci
32
+ - droplet
33
+ ---
34
+
35
+ # Publish — Deployment Pipeline Orchestrator
36
+
37
+ `/publish` is the single entry point for release workflows in this repository. It wires configuration validation, setup, gated deployment, release-note drafting, and ledger history into one end-to-end flow, and dispatches the final publish step to a per-type adapter.
38
+
39
+ Four target types are currently supported:
40
+
41
+ - **`mobile-ios`** — publishes an iOS build to App Store Connect via the iOS adapter. See the [iOS App Store](#ios-app-store) section for iOS-specific configuration.
42
+ - **`npm`** — publishes a package to an npm registry via the npm adapter. See the npm adapter (`skills/publish/adapters/npm.md`) and the npm wizard (`skills/publish/wizards/npm.md`) for npm-specific configuration.
43
+ - **`npm-ci`** — publishes a package to npmjs.com via GitHub Actions OIDC (Trusted Publishers), with no `NPM_TOKEN` stored. The adapter generates a GitHub Actions workflow, commits it to the repository, and triggers it via `gh workflow run`. See the npm-ci adapter (`skills/publish/adapters/npm-ci.md`) and the npm-ci wizard (`skills/publish/wizards/npm-ci.md`) for configuration details.
44
+ - **`droplet`** — deploys a website or app to any SSH-reachable Linux host (including DigitalOcean Droplets) using a generated GitHub Actions workflow. The workflow SSHes into the host, pulls the deploy branch, runs an optional build command, and restarts the service. See [Droplet (GitHub Actions → SSH)](#droplet-github-actions--ssh) for configuration details.
45
+
46
+ Every sub-command validates the config before doing anything else, so behaviour is identical regardless of which target type a project uses.
47
+
48
+ ## Invocation Contract
49
+
50
+ Before any sub-command executes, validate the config with:
51
+
52
+ ```bash
53
+ bash skills/publish/scripts/validate_config.sh <path-to-publish.json>
54
+ ```
55
+
56
+ For deploy-oriented flows, validate the selected target with:
57
+
58
+ ```bash
59
+ bash skills/publish/scripts/check_target_config.sh <target-name> <path-to-publish.json>
60
+ ```
61
+
62
+ - Default config resolution: prefer repo-root `publish.json`, fall back to `project/configs/publish.json`
63
+ - Schema: `skills/publish/schemas/publish.schema.json`
64
+ - Example config: `skills/publish/assets/publish.example.json`
65
+ - Secrets guide: `skills/publish/assets/secrets-guide.md`
66
+ - Deploy contract and exit codes: `skills/publish/assets/ci-contract.md`
67
+ - iOS adapter template: `skills/publish/adapters/mobile-ios.md`
68
+ - npm adapter template: `skills/publish/adapters/npm.md`
69
+ - Ownership matrix: `skills/publish/assets/ownership-matrix.md`
70
+
71
+ If config or env validation fails, the skill exits with code `4` and does not continue.
72
+
73
+ ## Sub-Commands
74
+
75
+ | Command | Purpose | Implementation script | Notes |
76
+ |---|---|---|---|
77
+ | `/publish setup` | Prepare or refresh target configuration | `skills/publish/scripts/setup_wizard.sh` | Supported types: `mobile-ios`, `npm`, `npm-ci`, `droplet` |
78
+ | `/publish deploy` | Run the full 11-step deploy orchestration | `skills/publish/scripts/publish_deploy.sh` | Dispatches to the adapter for the target's `type` (`mobile-ios`, `npm`, `npm-ci`, or `droplet`); `--dry-run` is honoured end-to-end |
79
+ | `/publish history` | Read the canonical publish ledger | `skills/publish/scripts/show_history.sh` | Target-agnostic; filter by `--target <name>` |
80
+ | `/publish release-notes` | Generate release notes without publishing | `skills/publish/scripts/generate_release_notes.sh` | Target-agnostic |
81
+
82
+ ## Quality Gate Policy
83
+
84
+ The deploy flow invokes `skills/publish/scripts/run_gates.sh` at two fixed points:
85
+
86
+ 1. **Pre-deploy:** `run_gates.sh pre <target> <publish.json> [--non-interactive]`
87
+ 2. **Post-deploy:** `run_gates.sh post <target> <publish.json> [--non-interactive]`
88
+
89
+ - `build` and `test` are **mandatory global** pre-deploy gates — always run, cannot be disabled via config
90
+ - Per-target `checks.pre` and `checks.post` can add optional gates: `lint`, `type-check`, `custom-script`, `smoke-test`, `ping`
91
+ - Any pre-deploy gate failure exits with code `2` and surfaces the full error output
92
+ - Post-deploy gate failure records a `partial` publish result instead of rolling back the adapter upload
93
+ - `--non-interactive` suppresses retry prompts and aborts immediately on failure
94
+
95
+ See `skills/publish/assets/ci-contract.md` for the full quality-gate policy.
96
+
97
+ ## Usage Signatures
98
+
99
+ ### `/publish setup`
100
+
101
+ ```text
102
+ /publish setup [<target>] [--type mobile-ios|npm|droplet] [--config <path>]
103
+ ```
104
+
105
+ Implementation: `bash skills/publish/scripts/setup_wizard.sh [<target>] [--type <deployment_type>] [--config <path>]`
106
+
107
+ Wizard flow:
108
+ 1. Resolve or prompt for the target name.
109
+ 2. Resolve or prompt for the deployment type. Supported values: `mobile-ios`, `npm`, `droplet`.
110
+ 3. Print the secrets guide path and the opening warning from `skills/publish/assets/secrets-guide.md`.
111
+ 4. Load `skills/publish/wizards/<type>.md` and render each `## Question:` section as a prompt.
112
+ 5. Preview the generated target config as JSON.
113
+ 6. Save on confirmation by merging or creating `publish.json`.
114
+ 7. Validate the saved file with `validate_config.sh`; if validation fails, roll back the write.
115
+
116
+ During setup, env-var reference answers are checked against the current shell. Missing variables only warn; they do not block save.
117
+
118
+ Example invocations:
119
+
120
+ ```bash
121
+ /publish setup # interactive, prompts for target and type
122
+ /publish setup --type mobile-ios # scaffold an iOS App Store target
123
+ /publish setup --type npm # scaffold an npm registry target
124
+ /publish setup npm-registry --type npm # scaffold a target named "npm-registry"
125
+ /publish setup --type npm-ci # scaffold an npm CI (Trusted Publisher) target
126
+ /publish setup npm-ci-pkg --type npm-ci # scaffold a target named "npm-ci-pkg"
127
+ /publish setup --type droplet # scaffold a Droplet SSH deploy target
128
+ /publish setup my-droplet --type droplet # scaffold a target named "my-droplet"
129
+ ```
130
+
131
+ ### `/publish deploy`
132
+
133
+ ```text
134
+ /publish deploy [--target <name>] [--config <path>] [--yes] [--dry-run] [--minor | --major] [--release-notes <path>]
135
+ ```
136
+
137
+ Implementation: `bash skills/publish/scripts/publish_deploy.sh [flags...]`
138
+
139
+ Deploy flow:
140
+ 1. Select the target from config or `--target`
141
+ 2. Check target completeness; interactive runs auto-launch the setup wizard on missing fields
142
+ 3. Validate target environment variables
143
+ 4. Print a best-effort scrum-board summary since the last publish tag
144
+ 5. Run pre-deploy gates
145
+ 6. Generate a release-note draft and review it unless `--yes` is set
146
+ 7. Suggest and confirm the semver bump (`patch` by default in non-interactive mode unless `--minor` or `--major` is passed)
147
+ 8. Print final confirmation: `Deploy v<x.y.z> to <target>? [y/N]`
148
+ 9. Execute the adapter pipeline for the target's `type` (`ios_pipeline.sh` for `mobile-ios`, `npm_pipeline.sh` for `npm`, `npm_ci_pipeline.sh` for `npm-ci`, `droplet_pipeline.sh` for `droplet`)
149
+ 10. Run post-deploy gates and downgrade the ledger state to `partial` on failure
150
+ 11. Append the publish ledger entry, create the git tag (unless `--dry-run`), and print post-deploy manual steps
151
+
152
+ Non-interactive rule: when `--yes` is used, deploy must not auto-run setup after a failure. It exits `4` and surfaces the missing fields.
153
+
154
+ #### `--dry-run`
155
+
156
+ `--dry-run` runs the full deploy orchestration end-to-end without producing a real release:
157
+
158
+ - Every step from target selection through gates, release-note generation, and semver bump runs normally.
159
+ - The adapter is invoked with `--dry-run` so it performs its full pipeline but skips the destructive publish step (no App Store upload for `mobile-ios`, no `npm publish` for `npm`).
160
+ - The real git tag is **not** created.
161
+ - A ledger entry is still appended with `platform_state: "dry-run"` so the run is auditable.
162
+
163
+ Example invocations:
164
+
165
+ ```bash
166
+ /publish deploy --target staging-appstore --dry-run
167
+ /publish deploy --target npm-registry --dry-run
168
+ /publish deploy --target npm-ci-pkg --dry-run
169
+ ```
170
+
171
+ Use `--dry-run` to rehearse a release, validate that gates pass, and confirm the generated release notes without publishing.
172
+
173
+ ### `/publish history`
174
+
175
+ ```text
176
+ /publish history [--config <path>] [--limit <count>] [--target <name>] [--json]
177
+ ```
178
+
179
+ Implementation: `bash skills/publish/scripts/show_history.sh [--limit <count>] [--target <name>] [--json] [--config <path>]`
180
+
181
+ ### `/publish release-notes`
182
+
183
+ ```text
184
+ /publish release-notes --target <name> [--config <path>] [--from-tag <tag>] [--to-ref <git-ref>] [--output <path>]
185
+ ```
186
+
187
+ Implementation: `bash skills/publish/scripts/generate_release_notes.sh [--target <name>] [--from-tag <tag>] [--to-ref <git-ref>] [--output <path>] [<publish_json_path>]`
188
+
189
+ Release-note rules:
190
+ - The last publish tag is the highest semver tag on the current branch that also has a matching ledger entry in `project/logs/publish-history.json`.
191
+ - If no prior ledger-backed tag exists, the draft includes `> First release — full history included`.
192
+ - Scrum-board enrichment is best-effort only; missing or unreadable board data never fails the command.
193
+
194
+ ## Ledger & Tagging
195
+
196
+ - `project/logs/publish-history.json` is append-only. New publishes add new rows; existing rows are never edited in-place.
197
+ - `bash skills/publish/scripts/suggest_semver_bump.sh` suggests `major`, `minor`, or `patch` based on git history since the last ledger-backed publish tag.
198
+ - `bash skills/publish/scripts/write_ledger_entry.sh <target> <adapter> <platform_state> <notes_path> [--yes] [--dry-run] [--version <vX.Y.Z>] [--config <path>]` appends the canonical publish entry and creates the matching annotated git tag.
199
+ - `bash skills/publish/scripts/reconcile_tags.sh [--dry-run] [--config <path>]` repairs drift:
200
+ - git tag without ledger entry → append `partial` ledger row with note `Manually tagged without /publish`
201
+ - ledger entry without git tag → create the missing tag retroactively
202
+
203
+ ## Agent Roles
204
+
205
+ See `skills/publish/assets/ownership-matrix.md` for the action-by-action ownership matrix.
206
+
207
+ Summary:
208
+ - **Developer** initiates `/publish setup`, `/publish deploy`, and release-note review
209
+ - **Tester** may run staging deploys as part of validation and uses publish history as test context
210
+ - **Scrum Master** never deploys directly and only reviews publish context through workflow status surfaces
211
+
212
+ ## Configuration Model
213
+
214
+ The canonical config must validate against `skills/publish/schemas/publish.schema.json`.
215
+
216
+ ### Required top-level structure
217
+
218
+ - `version` — schema version for the publish contract
219
+ - `defaults` — global defaults, including the canonical publish ledger path and mandatory checks
220
+ - `targets[]` — named deployment targets
221
+
222
+ ### Common target structure
223
+
224
+ Every target — regardless of `type` — must define:
225
+ - `name`
226
+ - `type` — one of `mobile-ios`, `npm`, `droplet`
227
+ - `checks.pre[]` / `checks.post[]`
228
+ - `secrets` — env-var references only, never credential values
229
+
230
+ Type-specific fields are documented below.
231
+
232
+ ## iOS App Store
233
+
234
+ The `mobile-ios` adapter publishes iOS builds to App Store Connect.
235
+
236
+ ### Required target fields for `mobile-ios`
237
+
238
+ - `type: mobile-ios`
239
+ - `platform: ios-app-store`
240
+ - `ios` — scheme/build/export/upload metadata used by the adapter
241
+
242
+ ### Required iOS env references
243
+
244
+ The `mobile-ios` target must provide env-var references for:
245
+ - `APP_STORE_CONNECT_API_KEY_ID`
246
+ - `APP_STORE_CONNECT_ISSUER_ID`
247
+ - `APP_STORE_CONNECT_PRIVATE_KEY_PATH`
248
+ - `CODE_SIGN_IDENTITY`
249
+ - `PROVISIONING_PROFILE_UUID`
250
+
251
+ ### iOS scope guardrails
252
+
253
+ This story set intentionally does **not** implement automated App Store review submission.
254
+
255
+ The iOS adapter trust boundary is explicit: publish-side external commands are limited to direct `xcodebuild` and `xcrun` invocations.
256
+
257
+ ## npm Registry
258
+
259
+ The `npm` adapter publishes a Node package to an npm-compatible registry.
260
+
261
+ - Adapter template: `skills/publish/adapters/npm.md`
262
+ - Wizard template: `skills/publish/wizards/npm.md`
263
+
264
+ See those files for the required target fields (registry URL, access, tag, `--dry-run` behaviour) and env references. Additional npm-specific schema details are owned by the npm settings block in `skills/publish/schemas/publish.schema.json`.
265
+
266
+ ## npm CI (OIDC Trusted Publisher)
267
+
268
+ The `npm-ci` adapter publishes a Node package to npmjs.com via **GitHub Actions OIDC (Trusted Publishers)** — no `NPM_TOKEN` is stored anywhere.
269
+
270
+ > Use `npm` for local publishes with a token; use `npm-ci` for CI-only publishing with OIDC (no token required).
271
+
272
+ - Adapter template: `skills/publish/adapters/npm-ci.md`
273
+ - Wizard template: `skills/publish/wizards/npm-ci.md`
274
+ - Example config: `skills/publish/assets/publish.example.npm-ci.json`
275
+
276
+ ### Required target fields for `npm-ci`
277
+
278
+ - `type: npm-ci`
279
+ - `github_repo` — repository in `owner/name` format (e.g. `acme-org/my-package`)
280
+ - `workflow_path` — path to the workflow file to generate and trigger (default: `.github/workflows/npm-publish.yml`)
281
+ - `npm.package_name`, `npm.access`, `npm.registry`, `npm.dist_tag` — same as the `npm` adapter
282
+
283
+ No `secrets` block is required. Any `secrets` block present is ignored by this adapter.
284
+
285
+ ### One-time prerequisite (manual)
286
+
287
+ Before the first deploy, link the package to the repository on npmjs.com:
288
+
289
+ 1. Sign in to npmjs.com → navigate to the package page
290
+ 2. Settings → Publishing → Trusted Publishers → Add publisher
291
+ 3. Select GitHub Actions; enter `owner/repo` and the workflow file path
292
+ 4. Save
293
+
294
+ Once configured, only the linked workflow can publish this package — local `npm publish` with a token will be rejected by npmjs.com for that package.
295
+
296
+ ### Usage examples
297
+
298
+ ```bash
299
+ /publish setup --type npm-ci
300
+ /publish deploy --target npm-ci-pkg --dry-run
301
+ /publish deploy --target npm-ci-pkg
302
+ ```
303
+
304
+ ## Droplet (GitHub Actions → SSH)
305
+
306
+ The `droplet` adapter deploys a project to any SSH-reachable Linux host by generating a GitHub Actions workflow that SSHes into the host on each trigger.
307
+
308
+ **Trust boundary**: `publish.json` holds only *references* to GitHub Actions secret names — never the actual SSH key or host credentials. Real secrets live in GitHub Actions secrets.
309
+
310
+ ### Required target fields for `droplet`
311
+
312
+ - `type: droplet`
313
+ - `platform: droplet-ssh`
314
+ - `droplet.host` — IP address or FQDN of the target host
315
+ - `droplet.ssh_user` — SSH login username
316
+ - `droplet.ssh_port` — SSH port (default 22)
317
+ - `droplet.deploy_path` — absolute path to the app directory on the host
318
+ - `droplet.github_repo` — repository in `owner/name` format
319
+ - `droplet.deploy_branch` — branch to pull on each deploy
320
+ - `droplet.start_cmd` — command to (re)start the service (e.g. `pm2 reload ecosystem.config.js`, `sudo systemctl restart myapp`)
321
+ - `droplet.build_cmd` — optional build step run after `git pull`
322
+ - `secrets.ssh_key_secret` — name of the GH Actions secret holding the SSH private key
323
+ - `secrets.known_hosts_secret` — name of the GH Actions secret holding `ssh-keyscan` output
324
+
325
+ ### Required GitHub Actions secrets
326
+
327
+ The generated workflow reads these from GitHub Actions secrets:
328
+ - `DROPLET_SSH_HOST` — host IP or FQDN
329
+ - `DROPLET_SSH_USER` — SSH username
330
+ - `DROPLET_SSH_PORT` — SSH port
331
+ - `DROPLET_SSH_KEY` (or value of `ssh_key_secret`) — private key contents
332
+ - `DROPLET_KNOWN_HOSTS` (or value of `known_hosts_secret`) — `ssh-keyscan` output
333
+
334
+ See `skills/publish/assets/secrets-guide.md` for setup instructions.
335
+
336
+ ### First-run prerequisites (manual)
337
+
338
+ Before the first deploy, the target host must already have:
339
+ - The deploy path created (`mkdir -p /var/www/myapp`)
340
+ - An initial `git clone` of the repo at the deploy path
341
+ - Any runtime dependencies installed (Node, PM2, etc.)
342
+
343
+ The adapter does not bootstrap the host — it only drives the continuous-deploy loop.
344
+
345
+ ### Usage examples
346
+
347
+ ```bash
348
+ /publish setup --type droplet
349
+ /publish deploy --target my-droplet --dry-run
350
+ /publish deploy --target my-droplet
351
+ ```
@@ -0,0 +1,200 @@
1
+ # `droplet` Adapter
2
+
3
+ The `droplet` adapter drives the `/publish deploy` flow for SSH-reachable Linux
4
+ host targets. Despite the name, nothing in the flow is DigitalOcean-specific — it
5
+ works against any Linux host reachable via SSH. The adapter generates a GitHub
6
+ Actions workflow that performs all deploy orchestration remotely; the local machine
7
+ never SSHes directly into the host.
8
+
9
+ ## Purpose
10
+
11
+ Deploy a web application or service from a GitHub repository to a Linux host
12
+ (DigitalOcean Droplet, VPS, bare-metal server, or any SSH-reachable machine) by:
13
+
14
+ 1. Generating a GitHub Actions workflow that SSHes into the host using
15
+ `appleboy/ssh-action`.
16
+ 2. Committing the workflow file (`.github/workflows/publish-droplet.yml`) to the
17
+ repository.
18
+ 3. Triggering the workflow via `gh workflow run`.
19
+
20
+ The host stays passive — it does not poll; all orchestration originates from
21
+ GitHub Actions. The user supplies `build_cmd` and `start_cmd`; the adapter makes
22
+ no assumptions about the runtime stack (no PM2 templates, no nginx config, no
23
+ systemd unit generation in v1).
24
+
25
+ ## Trust Boundary
26
+
27
+ `publish.json` holds **only** configuration values and secret name references —
28
+ never actual secrets. The five secret values (SSH private key, host, user, port,
29
+ known_hosts) live exclusively in GitHub Actions secrets.
30
+
31
+ ```
32
+ publish.json GitHub Actions secrets
33
+ ────────────── ──────────────────────────────
34
+ ssh_key_secret: "DROPLET_SSH_KEY" → ${{ secrets.DROPLET_SSH_KEY }} ← private key
35
+ known_hosts_secret: "DROPLET_KNOWN_HOSTS" → ${{ secrets.DROPLET_KNOWN_HOSTS }}
36
+ host: "192.168.1.10" (baked into workflow — not a secret)
37
+ ```
38
+
39
+ `host`, `ssh_user`, `ssh_port`, `deploy_path`, `deploy_branch`, `build_cmd`, and
40
+ `start_cmd` are non-sensitive configuration values stored in `publish.json` and
41
+ expanded into the generated workflow YAML. If you prefer to keep the host address
42
+ private too, supply it via a GitHub Actions secret and reference it in `start_cmd`.
43
+
44
+ ## Invocation Contract
45
+
46
+ ### Inputs from `publish.json`
47
+
48
+ A `droplet` target must define:
49
+
50
+ - `name`
51
+ - `type: droplet`
52
+ - `platform: droplet-ssh`
53
+ - `checks.pre[]` / `checks.post[]`
54
+ - `secrets.ssh_key_secret` — GitHub Actions secret name for the SSH private key
55
+ - `secrets.known_hosts_secret` — GitHub Actions secret name for known_hosts
56
+ - `droplet.host` — IP or FQDN of the target host
57
+ - `droplet.ssh_user` — SSH username
58
+ - `droplet.ssh_port` — SSH port (default: 22)
59
+ - `droplet.deploy_path` — absolute path on the remote host
60
+ - `droplet.github_repo` — `owner/name` format
61
+ - `droplet.deploy_branch` — branch to pull during deploy
62
+ - `droplet.start_cmd` — required; command to (re)start the service
63
+ - `droplet.build_cmd` — optional; build command to run before starting
64
+
65
+ ### Required environment and tools
66
+
67
+ The adapter requires the following tools at invocation time:
68
+
69
+ - `jq` — to read `publish.json` target config
70
+ - `git` — to commit the generated workflow file
71
+ - `gh` — GitHub CLI, to trigger the workflow via `gh workflow run`
72
+
73
+ The `gh` CLI must be authenticated (`gh auth login`) before running
74
+ `/publish deploy` against a droplet target.
75
+
76
+ ### Pipeline entrypoint
77
+
78
+ ```bash
79
+ bash skills/publish/scripts/droplet_pipeline.sh \
80
+ --target <name> \
81
+ --config <path-to-publish.json> \
82
+ [--dry-run]
83
+ ```
84
+
85
+ ## Execution Phases
86
+
87
+ Run the adapter phases in this exact order:
88
+
89
+ 1. **`validate`** — call `validate_droplet_env.sh`; abort with exit 4 if any
90
+ required field in the target config is missing or empty.
91
+
92
+ 2. **`generate-workflow`** — produce the GitHub Actions YAML in memory using a
93
+ here-doc. The `appleboy/ssh-action` step is pinned to a specific commit SHA
94
+ (not a floating tag) to prevent supply-chain surprises. In `--dry-run` mode,
95
+ print the YAML to stdout and exit 0 without writing any file.
96
+
97
+ 3. **`commit-workflow`** — write the YAML to
98
+ `.github/workflows/publish-droplet.yml` (creating the directory if needed)
99
+ and commit it with:
100
+ ```
101
+ git add .github/workflows/publish-droplet.yml
102
+ git commit -m "chore(publish): update droplet workflow for target <name>"
103
+ ```
104
+ If the file already exists and the content is unchanged (`git diff --quiet`),
105
+ skip the commit — the operation is idempotent.
106
+
107
+ 4. **`trigger`** — invoke `gh workflow run publish-droplet.yml --repo <github_repo>`
108
+ to start the workflow. After dispatching, retrieve the run URL via
109
+ `gh run list --workflow publish-droplet.yml --limit 1 --json url`.
110
+
111
+ 5. **`triggered`** — print the workflow run URL to stdout. The caller
112
+ (`publish_deploy.sh`) writes the ledger entry with `platform_state: "triggered"`.
113
+
114
+ ## Dry-run Mode
115
+
116
+ `--dry-run` is supported for safe end-to-end rehearsals without triggering a
117
+ real deploy.
118
+
119
+ Behavior in dry-run mode:
120
+
121
+ - The `validate` phase runs normally; config errors still surface.
122
+ - The `generate-workflow` phase runs normally; the YAML is printed to stdout.
123
+ - The `commit-workflow` phase is **skipped** — no file is written, no git commit
124
+ is made.
125
+ - The `trigger` phase is **skipped** — `gh workflow run` is not called.
126
+ - The adapter exits 0 after printing the YAML.
127
+ - The ledger entry written by `publish_deploy.sh` will have
128
+ `platform_state: "dry-run"`.
129
+
130
+ ## Exit Codes
131
+
132
+ | Code | Meaning |
133
+ |------|-------------------------------------------------------------------|
134
+ | `0` | Pipeline completed successfully, or `--dry-run` finished cleanly |
135
+ | `4` | Config or env invalid — required field missing or `jq`/`gh` absent|
136
+ | `3` | Workflow trigger failure (`gh workflow run` exited non-zero) |
137
+
138
+ ## Output Artefacts
139
+
140
+ A successful non-dry-run produces:
141
+
142
+ - `.github/workflows/publish-droplet.yml` committed to the repository
143
+ - A `gh workflow run` dispatch recorded in GitHub Actions history
144
+ - A workflow run URL printed to stdout
145
+ - A history entry in `project/logs/publish-history.json` written by
146
+ `publish_deploy.sh` with `platform_state: "triggered"`
147
+
148
+ ## Post-deploy manual steps
149
+
150
+ After a successful deploy trigger, the deploy flow must print:
151
+
152
+ Deploy triggered. Next manual steps:
153
+ 1. Monitor the workflow run at the URL printed above.
154
+ 2. If the run fails, check the GitHub Actions logs for SSH or script errors.
155
+ 3. Push a commit to `<deploy_branch>` to auto-trigger future deploys once the
156
+ generated workflow has been merged into the branch.
157
+
158
+ Print the same block regardless of interactive/non-interactive mode so CI logs
159
+ capture it.
160
+
161
+ ## First-run bootstrap caveat
162
+
163
+ Creating the deploy path and performing the initial `git clone` on the remote
164
+ host is **out of scope for v1** and must be done manually before the first
165
+ `/publish deploy` invocation.
166
+
167
+ Minimum bootstrap on the host:
168
+
169
+ ```bash
170
+ # SSH into the host
171
+ ssh <ssh_user>@<host>
172
+
173
+ # Clone the repository into deploy_path
174
+ git clone https://github.com/<github_repo>.git <deploy_path>
175
+ cd <deploy_path>
176
+
177
+ # Install runtime dependencies (example for Node.js)
178
+ npm install
179
+
180
+ # Verify start_cmd works
181
+ # e.g.: pm2 reload ecosystem.config.js
182
+ ```
183
+
184
+ Document these steps for your team. The wizard emits a post-setup instructions
185
+ file at `project/instructions/E22_S07_INSTRUCTIONS.md` with a bootstrap checklist.
186
+
187
+ ## Runtime agnosticism
188
+
189
+ The adapter does not generate PM2 configs, nginx virtual-host files, or systemd
190
+ unit files. Users embed runtime-specific commands directly in `build_cmd` and
191
+ `start_cmd`. Examples:
192
+
193
+ | Runtime | start_cmd example |
194
+ |-----------|-----------------------------------------------------|
195
+ | PM2 | `pm2 reload ecosystem.config.js` |
196
+ | systemd | `sudo systemctl restart myapp` |
197
+ | Docker | `docker compose up -d --build` |
198
+ | Custom | `./scripts/restart.sh` |
199
+
200
+ Opinionated runtime templates are deferred to future adapter versions.
@@ -0,0 +1,114 @@
1
+ # `mobile-ios` Adapter
2
+
3
+ The `mobile-ios` adapter drives the `/publish deploy` flow for iOS App Store targets.
4
+ It is a prompt/template contract for the agent layer and delegates concrete execution to
5
+ `skills/publish/scripts/ios_pipeline.sh`.
6
+
7
+ ## Invocation Contract
8
+
9
+ ### Inputs from `publish.json`
10
+
11
+ A `mobile-ios` target must define:
12
+
13
+ - `name`
14
+ - `type: mobile-ios`
15
+ - `platform: ios-app-store`
16
+ - `checks.pre[]` / `checks.post[]`
17
+ - `secrets.app_store_connect_api_key_id`
18
+ - `secrets.app_store_connect_issuer_id`
19
+ - `secrets.app_store_connect_private_key_path`
20
+ - `secrets.code_sign_identity`
21
+ - `secrets.provisioning_profile_uuid`
22
+ - `ios.scheme`
23
+ - `ios.configuration`
24
+ - `ios.archive_path`
25
+ - `ios.export_path`
26
+ - `ios.export_method` (`ad-hoc` or `app-store`)
27
+ - `ios.bundle_id`
28
+ - `ios.team_id`
29
+ - `ios.app_store_app_id`
30
+ - exactly one of `ios.project_path` or `ios.workspace_path`
31
+
32
+ ### Required environment variables
33
+
34
+ The adapter uses env-var references only and never stores secret values in repo files.
35
+ The required env vars are:
36
+
37
+ - `APP_STORE_CONNECT_API_KEY_ID`
38
+ - `APP_STORE_CONNECT_ISSUER_ID`
39
+ - `APP_STORE_CONNECT_PRIVATE_KEY_PATH`
40
+ - `CODE_SIGN_IDENTITY`
41
+ - `PROVISIONING_PROFILE_UUID`
42
+
43
+ Validate them before execution with:
44
+
45
+ ```bash
46
+ bash skills/publish/scripts/validate_ios_env.sh <path-to-publish.json>
47
+ ```
48
+
49
+ ### Pipeline entrypoint
50
+
51
+ ```bash
52
+ bash skills/publish/scripts/ios_pipeline.sh <target> <path-to-publish.json> [--dry-run] [--non-interactive]
53
+ ```
54
+
55
+ ## Execution Phases
56
+
57
+ Run the adapter phases in this exact order:
58
+
59
+ 1. `validate`
60
+ 2. `build`
61
+ 3. `sign`
62
+ 4. `export`
63
+ 5. `upload`
64
+
65
+ Quality gates run outside this adapter. Once control enters the adapter, external publish-side commands are restricted to direct `xcodebuild` and `xcrun` invocations.
66
+
67
+ ## State Machine
68
+
69
+ The adapter records these transitions in `project/logs/publish-history.json`:
70
+
71
+ ```text
72
+ idle → building → signing → exporting → uploading → uploaded
73
+ └──────────────────────→ failed
74
+ ```
75
+
76
+ ### State meanings
77
+
78
+ - `idle` — conceptual pre-start state before a history row is appended
79
+ - `building` — archive command is about to run or is running
80
+ - `signing` — export options are being generated using env refs and config
81
+ - `exporting` — `xcodebuild -exportArchive` is running
82
+ - `uploading` — the IPA is being uploaded with `xcrun`
83
+ - `uploaded` — upload finished successfully
84
+ - `failed` — any build/export/upload failure; `completed_at` must be set
85
+
86
+ ## Dry-run Mode
87
+
88
+ `--dry-run` is mandatory for safe CI validation without live Apple credentials.
89
+
90
+ Behavior:
91
+
92
+ - All `xcodebuild` / `xcrun` commands are printed with a `[DRY RUN]` prefix.
93
+ - Commands are **not** executed.
94
+ - State-machine writes still happen so reviewers can inspect the planned flow.
95
+ - The adapter exits `0` after simulating a successful upload.
96
+
97
+ ## Exit Codes
98
+
99
+ | Code | Meaning |
100
+ |---|---|
101
+ | `0` | Pipeline completed successfully or dry-run finished successfully |
102
+ | `3` | Build, sign, export, upload, or history-update failure |
103
+ | `4` | Config or env validation failure |
104
+
105
+ ## Post-deploy manual steps
106
+
107
+ After a successful upload, the deploy flow must print:
108
+
109
+ ✅ Upload complete. Next manual steps:
110
+ 1. Go to App Store Connect → Apps → [Your App] → TestFlight (or App Store)
111
+ 2. Find the new build and submit for review / release
112
+ 3. Set release notes if required
113
+
114
+ Print the same block in `--non-interactive` mode so CI logs capture it.