jonah-fleet 1.8.0 → 1.9.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 (43) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +3 -3
  3. package/dist/commands/labels.d.ts +1 -1
  4. package/dist/commands/labels.d.ts.map +1 -1
  5. package/dist/commands/status.d.ts.map +1 -1
  6. package/dist/commands/sync.d.ts.map +1 -1
  7. package/dist/commands/telemetry.d.ts.map +1 -1
  8. package/dist/index.js +666 -151
  9. package/dist/lib/daemon-keys.d.ts.map +1 -1
  10. package/dist/lib/daemon.d.ts.map +1 -1
  11. package/dist/lib/fleet-query.d.ts.map +1 -1
  12. package/dist/lib/labels.d.ts +20 -0
  13. package/dist/lib/labels.d.ts.map +1 -1
  14. package/dist/lib/manifest.d.ts.map +1 -1
  15. package/dist/lib/presets.d.ts +6 -1
  16. package/dist/lib/presets.d.ts.map +1 -1
  17. package/dist/lib/runner.d.ts +48 -0
  18. package/dist/lib/runner.d.ts.map +1 -1
  19. package/dist/lib/telemetry.d.ts.map +1 -1
  20. package/dist/lib/terminal-card.d.ts +15 -1
  21. package/dist/lib/terminal-card.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/schema.json +10 -5
  24. package/templates/prompts/ORCHESTRATION.md +49 -11
  25. package/templates/prompts/_prompt-template.md +10 -13
  26. package/templates/prompts/analytics-review.md +4 -2
  27. package/templates/prompts/autowork.md +43 -12
  28. package/templates/prompts/dependency-update-security-check.md +4 -2
  29. package/templates/prompts/design-review.md +125 -0
  30. package/templates/prompts/issues-housekeeping.md +9 -7
  31. package/templates/prompts/optimizer.md +31 -12
  32. package/templates/prompts/peer-review.md +29 -4
  33. package/templates/prompts/product-planning.md +14 -10
  34. package/templates/workflows/autowork-cron.yml +99 -39
  35. package/templates/workflows/dependency-check-cron.yml +89 -3
  36. package/templates/workflows/design-review-cron.yml +221 -0
  37. package/templates/workflows/issues-housekeeping-cron.yml +89 -3
  38. package/templates/workflows/prompt-optimizer-cron.yml +96 -10
  39. package/templates/workflows/sync-fleet.yml +4 -0
  40. package/templates/workflows/trigger-autowork-manual.yml +116 -12
  41. package/templates/workflows/trigger-autowork-on-bug.yml +135 -5
  42. package/templates/workflows/trigger-autowork-on-merge.yml +135 -5
  43. package/templates/workflows/trigger-review-routine.yml +119 -18
@@ -24,7 +24,7 @@ concurrency:
24
24
  jobs:
25
25
  run-autowork:
26
26
  runs-on: ubuntu-latest
27
- timeout-minutes: 65
27
+ timeout-minutes: 70
28
28
  permissions:
29
29
  contents: write
30
30
  issues: write
@@ -37,7 +37,7 @@ jobs:
37
37
  with:
38
38
  fetch-depth: 0
39
39
  token: ${{ secrets.GH_PAT || github.token }}
40
-
40
+ persist-credentials: false
41
41
 
42
42
  - name: Setup Node.js
43
43
  uses: actions/setup-node@v4
@@ -45,10 +45,13 @@ jobs:
45
45
  node-version: 22
46
46
 
47
47
  - name: Configure Git author identity
48
+ env:
49
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
48
50
  run: |
49
51
  git config --global user.name "github-actions[bot]"
50
52
  git config --global user.email "github-actions[bot]@users.noreply.github.com"
51
53
  git config --global --add safe.directory "$GITHUB_WORKSPACE"
54
+ gh auth setup-git
52
55
 
53
56
  - name: Cache Antigravity CLI
54
57
  id: cache-agy
@@ -109,7 +112,7 @@ jobs:
109
112
  id: routine-config
110
113
  run: |
111
114
  ROUTINE="autowork"
112
- DEFAULT_MODEL="gemini-3.7-flash-high"
115
+ DEFAULT_MODEL="gemini-3.8-flash-high"
113
116
  DEFAULT_TIMEOUT="60"
114
117
 
115
118
  MODEL="$DEFAULT_MODEL"
@@ -144,6 +147,35 @@ jobs:
144
147
  echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
145
148
  echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
146
149
 
150
+ - name: Initialize Routine Run Issue
151
+ id: run-issue
152
+ env:
153
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
154
+ TARGET_ARG: ${{ inputs.target_issue || inputs.issue_number }}
155
+ EVENT_NAME: ${{ github.event_name }}
156
+ RUN_ID: ${{ github.run_id }}
157
+ SERVER_URL: ${{ github.server_url }}
158
+ REPOSITORY: ${{ github.repository }}
159
+ run: |
160
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
161
+ if [ -n "$TARGET_ARG" ]; then
162
+ TITLE="[autowork] run ${TIMESTAMP} (Issue #${TARGET_ARG})"
163
+ else
164
+ TITLE="[autowork] run ${TIMESTAMP}"
165
+ fi
166
+ BODY="### Autonomous Routine Execution in Progress
167
+ - **Routine**: \`autowork\`
168
+ - **Timestamp**: \`${TIMESTAMP}\`
169
+ - **Trigger**: \`${EVENT_NAME}\`
170
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
171
+
172
+ ---
173
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
174
+ ISSUE_URL=$(gh issue create --title "$TITLE" --body "$BODY" --label "routine-log,routine:autowork,status:running,runner:github-actions")
175
+ ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
176
+ echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
177
+ echo "ROUTINE_ISSUE_NUMBER=$ISSUE_NUMBER" >> "$GITHUB_ENV"
178
+
147
179
  - name: Run Autowork
148
180
  timeout-minutes: 60
149
181
  env:
@@ -152,7 +184,10 @@ jobs:
152
184
  ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
153
185
  GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
154
186
  TARGET_ISSUE: ${{ inputs.target_issue || inputs.issue_number }}
187
+ ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
155
188
  SKILLS_PROMPT: ${{ steps.skills.outputs.skills_prompt }}
189
+ MODEL: ${{ steps.routine-config.outputs.model || 'gemini-3.8-flash-high' }}
190
+ PRINT_TIMEOUT: ${{ steps.routine-config.outputs.print_timeout || '60m' }}
156
191
  GITHUB_SERVER_URL: ${{ github.server_url }}
157
192
  GITHUB_REPOSITORY: ${{ github.repository }}
158
193
  GITHUB_RUN_ID: ${{ github.run_id }}
@@ -164,17 +199,17 @@ jobs:
164
199
  fi
165
200
 
166
201
  agy -p "$PROMPT" \
167
- --model "${{ steps.routine-config.outputs.model || 'gemini-3.7-flash-high' }}" \
202
+ --model "$MODEL" \
168
203
  --output-format text \
169
- --print-timeout "${{ steps.routine-config.outputs.print_timeout || '60m' }}" \
204
+ --print-timeout "$PRINT_TIMEOUT" \
170
205
  --dangerously-skip-permissions
171
206
 
172
207
  - name: Emit run summary
173
208
  if: always()
174
209
  run: |
175
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
176
- if [ -n "$LATEST_LOG" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
177
- cat "$LATEST_LOG" >> "$GITHUB_STEP_SUMMARY"
210
+ REPORT_FILE=".jonah-fleet/run-report.md"
211
+ if [ -f "$REPORT_FILE" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
212
+ cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
178
213
  fi
179
214
 
180
215
  - name: Emit Fleet Telemetry (Opt-in)
@@ -186,9 +221,9 @@ jobs:
186
221
  GITHUB_RUN_ID: ${{ github.run_id }}
187
222
  GITHUB_RUN_NUMBER: ${{ github.run_number }}
188
223
  run: |
189
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
190
- if [ -n "$LATEST_LOG" ] && [ -f "$LATEST_LOG" ]; then
191
- npx --yes jonah-fleet telemetry --emit --log "$LATEST_LOG" --endpoint "$TELEMETRY_ENDPOINT" || true
224
+ REPORT_FILE=".jonah-fleet/run-report.md"
225
+ if [ -f "$REPORT_FILE" ]; then
226
+ npx --yes jonah-fleet telemetry --emit --log "$REPORT_FILE" --endpoint "$TELEMETRY_ENDPOINT" || true
192
227
  fi
193
228
 
194
229
  - name: Verify Atomic Handoff Invariant (PR Existence Guard)
@@ -196,10 +231,10 @@ jobs:
196
231
  env:
197
232
  GH_TOKEN: ${{ github.token }}
198
233
  run: |
199
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
200
- if [ -n "$LATEST_LOG" ]; then
201
- if grep -q "Result.*SUCCESS" "$LATEST_LOG"; then
202
- WORKED_BRANCH=$(grep -E '^\s*-\s*(Pushed branch|Branch):' "$LATEST_LOG" | head -n 1 | sed -E 's/.*`([^`]+)`.*/\1/')
234
+ REPORT_FILE=".jonah-fleet/run-report.md"
235
+ if [ -f "$REPORT_FILE" ]; then
236
+ if grep -q "Result.*SUCCESS" "$REPORT_FILE"; then
237
+ WORKED_BRANCH=$(grep -E '^\s*-\s*(Pushed branch|Branch):' "$REPORT_FILE" | head -n 1 | sed -E 's/.*`([^`]+)`.*/\1/')
203
238
  if [ -n "$WORKED_BRANCH" ] && [[ "$WORKED_BRANCH" =~ (feat|fix)/ ]]; then
204
239
  echo "Verifying PR existence for branch: $WORKED_BRANCH"
205
240
  PR_COUNT=$(gh pr list --head "$WORKED_BRANCH" --state all --json number --jq 'length' 2>/dev/null || echo "0")
@@ -212,33 +247,58 @@ jobs:
212
247
  fi
213
248
  fi
214
249
 
215
- - name: Commit and push run log directly to main
250
+ - name: Reconcile Routine Run Issue
216
251
  if: always()
217
252
  env:
218
253
  GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
254
+ ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
255
+ JOB_STATUS: ${{ job.status }}
256
+ EVENT_NAME: ${{ github.event_name }}
257
+ RUN_ID: ${{ github.run_id }}
258
+ SERVER_URL: ${{ github.server_url }}
259
+ REPOSITORY: ${{ github.repository }}
219
260
  run: |
220
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
221
- if [ -n "$LATEST_LOG" ] && [ -f "$LATEST_LOG" ]; then
222
- TMP_LOG_FILE=$(mktemp)
223
- cp "$LATEST_LOG" "$TMP_LOG_FILE"
224
- LOG_REL_PATH="$LATEST_LOG"
225
- LOG_NAME=$(basename "$LATEST_LOG" .md)
226
-
227
- git fetch origin main:main || git fetch origin main || true
228
- git checkout main || git checkout -B main origin/main || true
229
-
230
- mkdir -p "$(dirname "$LOG_REL_PATH")"
231
- cp "$TMP_LOG_FILE" "$LOG_REL_PATH"
232
- rm -f "$TMP_LOG_FILE"
233
-
234
- git add "$LOG_REL_PATH"
235
- if ! git diff --cached --quiet; then
236
- git commit -m "docs(log): record autowork run ${LOG_NAME} [skip ci]" || true
237
- if [ -n "$GH_TOKEN" ]; then
238
- git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" main || git push origin main || true
239
- else
240
- git push origin main || true
241
- fi
242
- fi
261
+ if [ -z "$ISSUE_NUMBER" ]; then
262
+ echo "No routine issue to reconcile."
263
+ exit 0
264
+ fi
265
+
266
+ REPORT_FILE=".jonah-fleet/run-report.md"
267
+
268
+ if [ -f "$REPORT_FILE" ]; then
269
+ BODY_CONTENT=$(cat "$REPORT_FILE")
270
+ else
271
+ BODY_CONTENT="### Autonomous Routine Execution Completed (${JOB_STATUS})
272
+ - **Routine**: \`autowork\`
273
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
274
+ - **Trigger**: \`${EVENT_NAME}\`"
275
+ fi
276
+
277
+ FINAL_BODY="${BODY_CONTENT}
278
+
279
+ ---
280
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
281
+
282
+ TEMP_BODY=$(mktemp)
283
+ echo "$FINAL_BODY" > "$TEMP_BODY"
284
+ gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
285
+ rm -f "$TEMP_BODY"
286
+
287
+ if [ "$JOB_STATUS" = "success" ]; then
288
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:success" --remove-label "status:running"
289
+ gh issue close "$ISSUE_NUMBER" --reason completed
290
+ echo "✓ Routine run issue #$ISSUE_NUMBER closed as completed."
291
+ else
292
+ INTERRUPTION_BODY="### ❌ Milestone: Run Interrupted / Failed
293
+ - **Routine**: \`autowork\`
294
+ - **Status**: Workflow job failed or timed out (\`${JOB_STATUS}\`)
295
+ - **Step**: Actions execution halted before normal completion
296
+ - **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
297
+
298
+ ---
299
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
300
+ gh issue comment "$ISSUE_NUMBER" --body "$INTERRUPTION_BODY" || true
301
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:failure,needs-attention" --remove-label "status:running"
302
+ echo "⚠️ Routine run issue #$ISSUE_NUMBER left open for triage (status: $JOB_STATUS)."
243
303
  fi
244
304
 
@@ -25,6 +25,7 @@ jobs:
25
25
  uses: actions/checkout@v4
26
26
  with:
27
27
  fetch-depth: 0
28
+ persist-credentials: false
28
29
 
29
30
  - name: Setup Node.js
30
31
  uses: actions/setup-node@v4
@@ -32,10 +33,13 @@ jobs:
32
33
  node-version: 22
33
34
 
34
35
  - name: Configure Git author identity
36
+ env:
37
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
35
38
  run: |
36
39
  git config --global user.name "github-actions[bot]"
37
40
  git config --global user.email "github-actions[bot]@users.noreply.github.com"
38
41
  git config --global --add safe.directory "$GITHUB_WORKSPACE"
42
+ gh auth setup-git
39
43
 
40
44
  - name: Cache Antigravity CLI
41
45
  id: cache-agy
@@ -69,7 +73,7 @@ jobs:
69
73
  id: routine-config
70
74
  run: |
71
75
  ROUTINE="dependency-update-security-check"
72
- DEFAULT_MODEL="gemini-3.7-flash"
76
+ DEFAULT_MODEL="gemini-3.8-flash-medium"
73
77
  DEFAULT_TIMEOUT="25"
74
78
 
75
79
  MODEL="$DEFAULT_MODEL"
@@ -104,6 +108,30 @@ jobs:
104
108
  echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
105
109
  echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
106
110
 
111
+ - name: Initialize Routine Run Issue
112
+ id: run-issue
113
+ env:
114
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
115
+ EVENT_NAME: ${{ github.event_name }}
116
+ RUN_ID: ${{ github.run_id }}
117
+ SERVER_URL: ${{ github.server_url }}
118
+ REPOSITORY: ${{ github.repository }}
119
+ run: |
120
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
121
+ TITLE="[dependency-check] run ${TIMESTAMP}"
122
+ BODY="### Autonomous Routine Execution in Progress
123
+ - **Routine**: \`dependency-update-security-check\`
124
+ - **Timestamp**: \`${TIMESTAMP}\`
125
+ - **Trigger**: \`${EVENT_NAME}\`
126
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
127
+
128
+ ---
129
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
130
+ ISSUE_URL=$(gh issue create --title "$TITLE" --body "$BODY" --label "routine-log,routine:dependency-check,status:running,runner:github-actions")
131
+ ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
132
+ echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
133
+ echo "ROUTINE_ISSUE_NUMBER=$ISSUE_NUMBER" >> "$GITHUB_ENV"
134
+
107
135
  - name: Run Dependency Update Check
108
136
  timeout-minutes: 25
109
137
  env:
@@ -111,6 +139,9 @@ jobs:
111
139
  GOOGLE_API_KEY: ${{ secrets.GEMINI_API_KEY }}
112
140
  ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
113
141
  GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
142
+ ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
143
+ MODEL: ${{ steps.routine-config.outputs.model || 'gemini-3.8-flash-medium' }}
144
+ PRINT_TIMEOUT: ${{ steps.routine-config.outputs.print_timeout || '25m' }}
114
145
  GITHUB_SERVER_URL: ${{ github.server_url }}
115
146
  GITHUB_REPOSITORY: ${{ github.repository }}
116
147
  GITHUB_RUN_ID: ${{ github.run_id }}
@@ -118,7 +149,62 @@ jobs:
118
149
  PROMPT="You are the Dependency Update & Security Check routine. Read and follow .github/prompts/dependency-update-security-check.md exactly. Check dependencies for updates and vulnerabilities, and create or update tracking issues."
119
150
 
120
151
  agy -p "$PROMPT" \
121
- --model "${{ steps.routine-config.outputs.model || 'gemini-3.7-flash' }}" \
152
+ --model "$MODEL" \
122
153
  --output-format text \
123
- --print-timeout "${{ steps.routine-config.outputs.print_timeout || '25m' }}" \
154
+ --print-timeout "$PRINT_TIMEOUT" \
124
155
  --dangerously-skip-permissions
156
+
157
+ - name: Reconcile Routine Run Issue
158
+ if: always()
159
+ env:
160
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
161
+ ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
162
+ JOB_STATUS: ${{ job.status }}
163
+ EVENT_NAME: ${{ github.event_name }}
164
+ RUN_ID: ${{ github.run_id }}
165
+ SERVER_URL: ${{ github.server_url }}
166
+ REPOSITORY: ${{ github.repository }}
167
+ run: |
168
+ if [ -z "$ISSUE_NUMBER" ]; then
169
+ echo "No routine issue to reconcile."
170
+ exit 0
171
+ fi
172
+
173
+ REPORT_FILE=".jonah-fleet/run-report.md"
174
+
175
+ if [ -f "$REPORT_FILE" ]; then
176
+ BODY_CONTENT=$(cat "$REPORT_FILE")
177
+ else
178
+ BODY_CONTENT="### Autonomous Routine Execution Completed (${JOB_STATUS})
179
+ - **Routine**: \`dependency-update-security-check\`
180
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
181
+ - **Trigger**: \`${EVENT_NAME}\`"
182
+ fi
183
+
184
+ FINAL_BODY="${BODY_CONTENT}
185
+
186
+ ---
187
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
188
+
189
+ TEMP_BODY=$(mktemp)
190
+ echo "$FINAL_BODY" > "$TEMP_BODY"
191
+ gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
192
+ rm -f "$TEMP_BODY"
193
+
194
+ if [ "$JOB_STATUS" = "success" ]; then
195
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:success" --remove-label "status:running"
196
+ gh issue close "$ISSUE_NUMBER" --reason completed
197
+ echo "✓ Routine run issue #$ISSUE_NUMBER closed as completed."
198
+ else
199
+ INTERRUPTION_BODY="### ❌ Milestone: Run Interrupted / Failed
200
+ - **Routine**: \`dependency-check\`
201
+ - **Status**: Workflow job failed or timed out (\`${JOB_STATUS}\`)
202
+ - **Step**: Actions execution halted before normal completion
203
+ - **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
204
+
205
+ ---
206
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
207
+ gh issue comment "$ISSUE_NUMBER" --body "$INTERRUPTION_BODY" || true
208
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:failure,needs-attention" --remove-label "status:running"
209
+ echo "⚠️ Routine run issue #$ISSUE_NUMBER left open for triage (status: $JOB_STATUS)."
210
+ fi
@@ -0,0 +1,221 @@
1
+ name: Design Review Scheduled Cron (agy)
2
+
3
+ # Scheduled execution of the Design Review routine using Antigravity CLI on Gemini 3.7 Flash.
4
+ # Dispatches bi-weekly ahead of Product Planning, dynamically discovers player-facing surfaces,
5
+ # audits against DESIGN_SYSTEM.md and visual guardrails, files Autowork token cleanups,
6
+ # and stages pruning & redesign recommendations for Product Planning.
7
+
8
+ on:
9
+ schedule:
10
+ # Bi-weekly on the 1st and 15th of the month at 06:00 UTC (08:00 Paris CEST)
11
+ # 3 hours prior to Product Planning cron at 09:00 UTC
12
+ - cron: '0 6 1,15 * *'
13
+ workflow_dispatch:
14
+ inputs:
15
+ target_surface:
16
+ description: 'Target surface or route to review (optional, e.g. "pronostics", "groupes", "home"; leaves empty for dynamic rotation)'
17
+ required: false
18
+ type: string
19
+
20
+ # Single-flight: do not run overlapping design review runs.
21
+ concurrency:
22
+ group: design-review-agent
23
+ cancel-in-progress: false
24
+
25
+ jobs:
26
+ run-design-review:
27
+ runs-on: ubuntu-latest
28
+ timeout-minutes: 60
29
+ permissions:
30
+ contents: write
31
+ issues: write
32
+ pull-requests: write
33
+ statuses: write
34
+ actions: read
35
+ steps:
36
+ - name: Checkout repository
37
+ uses: actions/checkout@v4
38
+ with:
39
+ fetch-depth: 0
40
+ persist-credentials: false
41
+
42
+ - name: Setup Node.js
43
+ uses: actions/setup-node@v4
44
+ with:
45
+ node-version: 22
46
+
47
+ - name: Configure Git author identity
48
+ env:
49
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
50
+ run: |
51
+ git config --global user.name "github-actions[bot]"
52
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
53
+ git config --global --add safe.directory "$GITHUB_WORKSPACE"
54
+ gh auth setup-git
55
+
56
+ - name: Cache Antigravity CLI
57
+ id: cache-agy
58
+ uses: actions/cache@v4
59
+ with:
60
+ path: ~/.local/bin/agy
61
+ key: agy-cli-linux-amd64-v1
62
+
63
+ - name: Install Antigravity CLI
64
+ if: steps.cache-agy.outputs.cache-hit != 'true'
65
+ run: |
66
+ curl -fsSL https://antigravity.google/cli/install.sh | bash
67
+
68
+ - name: Add Antigravity CLI to PATH
69
+ run: echo "$HOME/.local/bin" >> $GITHUB_PATH
70
+
71
+ - name: Write Antigravity OAuth Token
72
+ env:
73
+ ANTIGRAVITY_OAUTH_TOKEN: ${{ secrets.ANTIGRAVITY_OAUTH_TOKEN || secrets.GEMINI_API_KEY }}
74
+ run: |
75
+ if [ -z "$ANTIGRAVITY_OAUTH_TOKEN" ]; then
76
+ echo "::error::Neither ANTIGRAVITY_OAUTH_TOKEN nor GEMINI_API_KEY secret is set; cannot authenticate Antigravity CLI." >&2
77
+ exit 1
78
+ fi
79
+ mkdir -p "$HOME/.gemini/antigravity-cli"
80
+ chmod 700 "$HOME/.gemini/antigravity-cli"
81
+ printf '%s' "$ANTIGRAVITY_OAUTH_TOKEN" > "$HOME/.gemini/antigravity-cli/antigravity-oauth-token"
82
+ chmod 600 "$HOME/.gemini/antigravity-cli/antigravity-oauth-token"
83
+
84
+ - name: Fast preflight credential validation (SwarmClaw Pattern #2)
85
+ run: |
86
+ if [ ! -s "$HOME/.gemini/antigravity-cli/antigravity-oauth-token" ]; then
87
+ echo "::error::Preflight credential check failed: Antigravity OAuth token file is missing or empty." >&2
88
+ exit 1
89
+ fi
90
+ echo "✓ Preflight credential validation passed."
91
+
92
+ - name: Discover and compile domain skills (SwarmClaw Pattern #4)
93
+ id: skills
94
+ run: |
95
+ SKILLS_LIST="Read and follow .agents/skills/design-system/SKILL.md, .agents/skills/design-critique/SKILL.md, and .agents/skills/run/SKILL.md."
96
+ echo "skills_prompt=$SKILLS_LIST" >> "$GITHUB_OUTPUT"
97
+
98
+ - name: Initialize Routine Run Issue
99
+ id: run-issue
100
+ env:
101
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
102
+ EVENT_NAME: ${{ github.event_name }}
103
+ RUN_ID: ${{ github.run_id }}
104
+ SERVER_URL: ${{ github.server_url }}
105
+ REPOSITORY: ${{ github.repository }}
106
+ run: |
107
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
108
+ TITLE="[design-review] run ${TIMESTAMP}"
109
+ BODY="### Autonomous Routine Execution in Progress
110
+ - **Routine**: \`design-review\`
111
+ - **Timestamp**: \`${TIMESTAMP}\`
112
+ - **Trigger**: \`${EVENT_NAME}\`
113
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
114
+
115
+ ---
116
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
117
+ ISSUE_URL=$(gh issue create --title "$TITLE" --body "$BODY" --label "routine-log,routine:design-review,status:running,runner:github-actions")
118
+ ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
119
+ echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
120
+ echo "ROUTINE_ISSUE_NUMBER=$ISSUE_NUMBER" >> "$GITHUB_ENV"
121
+
122
+ - name: Run Design Review
123
+ timeout-minutes: 50
124
+ env:
125
+ GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
126
+ GOOGLE_API_KEY: ${{ secrets.GEMINI_API_KEY }}
127
+ ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
128
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
129
+ ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
130
+ VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
131
+ POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
132
+ TARGET_SURFACE: ${{ inputs.target_surface }}
133
+ SKILLS_PROMPT: ${{ steps.skills.outputs.skills_prompt }}
134
+ GITHUB_SERVER_URL: ${{ github.server_url }}
135
+ GITHUB_REPOSITORY: ${{ github.repository }}
136
+ GITHUB_RUN_ID: ${{ github.run_id }}
137
+ run: |
138
+ PROMPT="You are the Design Review routine for this repository. Read and follow the instructions in .github/prompts/design-review.md exactly. ${SKILLS_PROMPT}"
139
+
140
+ agy -p "$PROMPT" \
141
+ --model gemini-3.8-flash-high \
142
+ --output-format text \
143
+ --print-timeout 50m \
144
+ --dangerously-skip-permissions
145
+
146
+ - name: Emit run summary
147
+ if: always()
148
+ run: |
149
+ REPORT_FILE=".jonah-fleet/run-report.md"
150
+ if [ -f "$REPORT_FILE" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
151
+ cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
152
+ fi
153
+
154
+ - name: Emit Fleet Telemetry (Opt-in)
155
+ if: always()
156
+ env:
157
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
158
+ TELEMETRY_ENDPOINT: ${{ secrets.JONAH_FLEET_TELEMETRY_ENDPOINT }}
159
+ GITHUB_REPOSITORY: ${{ github.repository }}
160
+ GITHUB_RUN_ID: ${{ github.run_id }}
161
+ GITHUB_RUN_NUMBER: ${{ github.run_number }}
162
+ run: |
163
+ REPORT_FILE=".jonah-fleet/run-report.md"
164
+ if [ -f "$REPORT_FILE" ]; then
165
+ npx --yes jonah-fleet telemetry --emit --log "$REPORT_FILE" --endpoint "$TELEMETRY_ENDPOINT" || true
166
+ fi
167
+
168
+ - name: Reconcile Routine Run Issue
169
+ if: always()
170
+ env:
171
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
172
+ ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
173
+ JOB_STATUS: ${{ job.status }}
174
+ EVENT_NAME: ${{ github.event_name }}
175
+ RUN_ID: ${{ github.run_id }}
176
+ SERVER_URL: ${{ github.server_url }}
177
+ REPOSITORY: ${{ github.repository }}
178
+ run: |
179
+ if [ -z "$ISSUE_NUMBER" ]; then
180
+ echo "No routine issue to reconcile."
181
+ exit 0
182
+ fi
183
+
184
+ REPORT_FILE=".jonah-fleet/run-report.md"
185
+
186
+ if [ -f "$REPORT_FILE" ]; then
187
+ BODY_CONTENT=$(cat "$REPORT_FILE")
188
+ else
189
+ BODY_CONTENT="### Autonomous Routine Execution Completed (${JOB_STATUS})
190
+ - **Routine**: \`design-review\`
191
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
192
+ - **Trigger**: \`${EVENT_NAME}\`"
193
+ fi
194
+
195
+ FINAL_BODY="${BODY_CONTENT}
196
+
197
+ ---
198
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
199
+
200
+ TEMP_BODY=$(mktemp)
201
+ echo "$FINAL_BODY" > "$TEMP_BODY"
202
+ gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
203
+ rm -f "$TEMP_BODY"
204
+
205
+ if [ "$JOB_STATUS" = "success" ]; then
206
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:success" --remove-label "status:running"
207
+ gh issue close "$ISSUE_NUMBER" --reason completed
208
+ echo "✓ Routine run issue #$ISSUE_NUMBER closed as completed."
209
+ else
210
+ INTERRUPTION_BODY="### ❌ Milestone: Run Interrupted / Failed
211
+ - **Routine**: \`design-review\`
212
+ - **Status**: Workflow job failed or timed out (\`${JOB_STATUS}\`)
213
+ - **Step**: Actions execution halted before normal completion
214
+ - **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
215
+
216
+ ---
217
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
218
+ gh issue comment "$ISSUE_NUMBER" --body "$INTERRUPTION_BODY" || true
219
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:failure,needs-attention" --remove-label "status:running"
220
+ echo "⚠️ Routine run issue #$ISSUE_NUMBER left open for triage (status: $JOB_STATUS)."
221
+ fi