jonah-fleet 1.6.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.
- package/CHANGELOG.md +130 -0
- package/README.md +25 -2
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/labels.d.ts +11 -0
- package/dist/commands/labels.d.ts.map +1 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/telemetry.d.ts.map +1 -1
- package/dist/index.js +2527 -519
- package/dist/lib/daemon-keys.d.ts +103 -0
- package/dist/lib/daemon-keys.d.ts.map +1 -0
- package/dist/lib/daemon.d.ts +8 -2
- package/dist/lib/daemon.d.ts.map +1 -1
- package/dist/lib/fleet-query.d.ts.map +1 -1
- package/dist/lib/labels.d.ts +68 -0
- package/dist/lib/labels.d.ts.map +1 -0
- package/dist/lib/manifest.d.ts +6 -0
- package/dist/lib/manifest.d.ts.map +1 -1
- package/dist/lib/presets.d.ts +52 -1
- package/dist/lib/presets.d.ts.map +1 -1
- package/dist/lib/runner.d.ts +114 -0
- package/dist/lib/runner.d.ts.map +1 -1
- package/dist/lib/telemetry.d.ts.map +1 -1
- package/dist/lib/terminal-card.d.ts +24 -1
- package/dist/lib/terminal-card.d.ts.map +1 -1
- package/package.json +1 -1
- package/schema.json +74 -1
- package/templates/prompts/ORCHESTRATION.md +84 -41
- package/templates/prompts/_prompt-template.md +10 -13
- package/templates/prompts/analytics-review.md +4 -2
- package/templates/prompts/autowork.md +76 -35
- package/templates/prompts/dependency-update-security-check.md +4 -2
- package/templates/prompts/design-review.md +125 -0
- package/templates/prompts/issues-housekeeping.md +10 -8
- package/templates/prompts/optimizer.md +31 -12
- package/templates/prompts/peer-review.md +42 -7
- package/templates/prompts/product-planning.md +14 -10
- package/templates/workflows/autowork-cron.yml +137 -38
- package/templates/workflows/dependency-check-cron.yml +127 -2
- package/templates/workflows/design-review-cron.yml +221 -0
- package/templates/workflows/issues-housekeeping-cron.yml +127 -2
- package/templates/workflows/prompt-optimizer-cron.yml +134 -9
- package/templates/workflows/sync-fleet.yml +4 -0
- package/templates/workflows/trigger-autowork-manual.yml +154 -11
- package/templates/workflows/trigger-autowork-on-bug.yml +177 -9
- package/templates/workflows/trigger-autowork-on-merge.yml +178 -9
- package/templates/workflows/trigger-review-routine.yml +162 -22
|
@@ -29,7 +29,7 @@ concurrency:
|
|
|
29
29
|
jobs:
|
|
30
30
|
run-autowork:
|
|
31
31
|
runs-on: ubuntu-latest
|
|
32
|
-
timeout-minutes:
|
|
32
|
+
timeout-minutes: 70
|
|
33
33
|
permissions:
|
|
34
34
|
contents: write
|
|
35
35
|
issues: write
|
|
@@ -42,7 +42,7 @@ jobs:
|
|
|
42
42
|
with:
|
|
43
43
|
fetch-depth: 0
|
|
44
44
|
token: ${{ secrets.GH_PAT || github.token }}
|
|
45
|
-
|
|
45
|
+
persist-credentials: false
|
|
46
46
|
|
|
47
47
|
- name: Setup Node.js
|
|
48
48
|
uses: actions/setup-node@v4
|
|
@@ -50,10 +50,13 @@ jobs:
|
|
|
50
50
|
node-version: 22
|
|
51
51
|
|
|
52
52
|
- name: Configure Git author identity
|
|
53
|
+
env:
|
|
54
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
53
55
|
run: |
|
|
54
56
|
git config --global user.name "github-actions[bot]"
|
|
55
57
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
56
58
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
59
|
+
gh auth setup-git
|
|
57
60
|
|
|
58
61
|
- name: Cache Antigravity CLI
|
|
59
62
|
id: cache-agy
|
|
@@ -110,6 +113,74 @@ jobs:
|
|
|
110
113
|
fi
|
|
111
114
|
echo "skills_prompt=$SKILLS_PROMPT" >> "$GITHUB_OUTPUT"
|
|
112
115
|
|
|
116
|
+
- name: Resolve routine configuration
|
|
117
|
+
id: routine-config
|
|
118
|
+
run: |
|
|
119
|
+
ROUTINE="autowork"
|
|
120
|
+
DEFAULT_MODEL="gemini-3.8-flash-high"
|
|
121
|
+
DEFAULT_TIMEOUT="60"
|
|
122
|
+
|
|
123
|
+
MODEL="$DEFAULT_MODEL"
|
|
124
|
+
TIMEOUT="$DEFAULT_TIMEOUT"
|
|
125
|
+
|
|
126
|
+
if [ -f "agents-manifest.json" ]; then
|
|
127
|
+
CONFIG_JSON=$(node -e '
|
|
128
|
+
try {
|
|
129
|
+
const fs = require("fs");
|
|
130
|
+
const m = JSON.parse(fs.readFileSync("agents-manifest.json", "utf8"));
|
|
131
|
+
const r = process.argv[1];
|
|
132
|
+
const model = m.models?.[r] || m.models?.default;
|
|
133
|
+
const timeout = m.budgets?.timeoutMinutes?.[r] || m.budgets?.timeoutMinutes?.default;
|
|
134
|
+
console.log(JSON.stringify({ model: model || "", timeout: timeout ? String(timeout) : "" }));
|
|
135
|
+
} catch (e) {
|
|
136
|
+
console.log(JSON.stringify({ model: "", timeout: "" }));
|
|
137
|
+
}
|
|
138
|
+
' "$ROUTINE")
|
|
139
|
+
|
|
140
|
+
RESOLVED_MODEL=$(node -e "try { console.log(JSON.parse(process.argv[1]).model || ''); } catch {}" "$CONFIG_JSON")
|
|
141
|
+
RESOLVED_TIMEOUT=$(node -e "try { console.log(JSON.parse(process.argv[1]).timeout || ''); } catch {}" "$CONFIG_JSON")
|
|
142
|
+
|
|
143
|
+
if [ -n "$RESOLVED_MODEL" ]; then
|
|
144
|
+
MODEL="$RESOLVED_MODEL"
|
|
145
|
+
fi
|
|
146
|
+
if [ -n "$RESOLVED_TIMEOUT" ]; then
|
|
147
|
+
TIMEOUT="$RESOLVED_TIMEOUT"
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
echo "model=$MODEL" >> "$GITHUB_OUTPUT"
|
|
152
|
+
echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
|
|
153
|
+
echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
|
|
154
|
+
|
|
155
|
+
- name: Initialize Routine Run Issue
|
|
156
|
+
id: run-issue
|
|
157
|
+
env:
|
|
158
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
159
|
+
TARGET_ARG: ${{ inputs.issue_number }}
|
|
160
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
161
|
+
RUN_ID: ${{ github.run_id }}
|
|
162
|
+
SERVER_URL: ${{ github.server_url }}
|
|
163
|
+
REPOSITORY: ${{ github.repository }}
|
|
164
|
+
run: |
|
|
165
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
|
|
166
|
+
if [ -n "$TARGET_ARG" ]; then
|
|
167
|
+
TITLE="[autowork] run ${TIMESTAMP} (Issue #${TARGET_ARG})"
|
|
168
|
+
else
|
|
169
|
+
TITLE="[autowork] run ${TIMESTAMP}"
|
|
170
|
+
fi
|
|
171
|
+
BODY="### Autonomous Routine Execution in Progress
|
|
172
|
+
- **Routine**: \`autowork\`
|
|
173
|
+
- **Timestamp**: \`${TIMESTAMP}\`
|
|
174
|
+
- **Trigger**: \`${EVENT_NAME}\`
|
|
175
|
+
- **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
|
|
179
|
+
ISSUE_URL=$(gh issue create --title "$TITLE" --body "$BODY" --label "routine-log,routine:autowork,status:running,runner:github-actions")
|
|
180
|
+
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
|
|
181
|
+
echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
|
|
182
|
+
echo "ROUTINE_ISSUE_NUMBER=$ISSUE_NUMBER" >> "$GITHUB_ENV"
|
|
183
|
+
|
|
113
184
|
- name: Run Autowork
|
|
114
185
|
timeout-minutes: 60
|
|
115
186
|
env:
|
|
@@ -118,9 +189,12 @@ jobs:
|
|
|
118
189
|
ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
119
190
|
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
120
191
|
TARGET_ISSUE: ${{ inputs.issue_number }}
|
|
192
|
+
ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
|
|
121
193
|
MODE: ${{ inputs.mode || 'targeted' }}
|
|
122
194
|
CUSTOM_PROMPT: ${{ inputs.custom_prompt }}
|
|
123
195
|
SKILLS_PROMPT: ${{ steps.skills.outputs.skills_prompt }}
|
|
196
|
+
MODEL: ${{ steps.routine-config.outputs.model || 'gemini-3.8-flash-high' }}
|
|
197
|
+
PRINT_TIMEOUT: ${{ steps.routine-config.outputs.print_timeout || '60m' }}
|
|
124
198
|
GITHUB_SERVER_URL: ${{ github.server_url }}
|
|
125
199
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
126
200
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
@@ -136,17 +210,31 @@ jobs:
|
|
|
136
210
|
fi
|
|
137
211
|
|
|
138
212
|
agy -p "$PROMPT" \
|
|
139
|
-
--model
|
|
213
|
+
--model "$MODEL" \
|
|
140
214
|
--output-format text \
|
|
141
|
-
--print-timeout
|
|
215
|
+
--print-timeout "$PRINT_TIMEOUT" \
|
|
142
216
|
--dangerously-skip-permissions
|
|
143
217
|
|
|
144
218
|
- name: Emit run summary
|
|
145
219
|
if: always()
|
|
146
220
|
run: |
|
|
147
|
-
|
|
148
|
-
if [ -
|
|
149
|
-
cat "$
|
|
221
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
222
|
+
if [ -f "$REPORT_FILE" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
|
|
223
|
+
cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
- name: Emit Fleet Telemetry (Opt-in)
|
|
227
|
+
if: always()
|
|
228
|
+
env:
|
|
229
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
230
|
+
TELEMETRY_ENDPOINT: ${{ secrets.JONAH_FLEET_TELEMETRY_ENDPOINT }}
|
|
231
|
+
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
232
|
+
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
233
|
+
GITHUB_RUN_NUMBER: ${{ github.run_number }}
|
|
234
|
+
run: |
|
|
235
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
236
|
+
if [ -f "$REPORT_FILE" ]; then
|
|
237
|
+
npx --yes jonah-fleet telemetry --emit --log "$REPORT_FILE" --endpoint "$TELEMETRY_ENDPOINT" || true
|
|
150
238
|
fi
|
|
151
239
|
|
|
152
240
|
- name: Verify Atomic Handoff Invariant (PR Existence Guard)
|
|
@@ -154,10 +242,10 @@ jobs:
|
|
|
154
242
|
env:
|
|
155
243
|
GH_TOKEN: ${{ github.token }}
|
|
156
244
|
run: |
|
|
157
|
-
|
|
158
|
-
if [ -
|
|
159
|
-
if grep -q "Result.*SUCCESS" "$
|
|
160
|
-
WORKED_BRANCH=$(grep -E '^\s*-\s*(Pushed branch|Branch):' "$
|
|
245
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
246
|
+
if [ -f "$REPORT_FILE" ]; then
|
|
247
|
+
if grep -q "Result.*SUCCESS" "$REPORT_FILE"; then
|
|
248
|
+
WORKED_BRANCH=$(grep -E '^\s*-\s*(Pushed branch|Branch):' "$REPORT_FILE" | head -n 1 | sed -E 's/.*`([^`]+)`.*/\1/')
|
|
161
249
|
if [ -n "$WORKED_BRANCH" ] && [[ "$WORKED_BRANCH" =~ (feat|fix)/ ]]; then
|
|
162
250
|
echo "Verifying PR existence for branch: $WORKED_BRANCH"
|
|
163
251
|
PR_COUNT=$(gh pr list --head "$WORKED_BRANCH" --state all --json number --jq 'length' 2>/dev/null || echo "0")
|
|
@@ -169,3 +257,58 @@ jobs:
|
|
|
169
257
|
fi
|
|
170
258
|
fi
|
|
171
259
|
fi
|
|
260
|
+
|
|
261
|
+
- name: Reconcile Routine Run Issue
|
|
262
|
+
if: always()
|
|
263
|
+
env:
|
|
264
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
265
|
+
ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
|
|
266
|
+
JOB_STATUS: ${{ job.status }}
|
|
267
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
268
|
+
RUN_ID: ${{ github.run_id }}
|
|
269
|
+
SERVER_URL: ${{ github.server_url }}
|
|
270
|
+
REPOSITORY: ${{ github.repository }}
|
|
271
|
+
run: |
|
|
272
|
+
if [ -z "$ISSUE_NUMBER" ]; then
|
|
273
|
+
echo "No routine issue to reconcile."
|
|
274
|
+
exit 0
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
278
|
+
|
|
279
|
+
if [ -f "$REPORT_FILE" ]; then
|
|
280
|
+
BODY_CONTENT=$(cat "$REPORT_FILE")
|
|
281
|
+
else
|
|
282
|
+
BODY_CONTENT="### Autonomous Routine Execution Completed (${JOB_STATUS})
|
|
283
|
+
- **Routine**: \`autowork\`
|
|
284
|
+
- **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
|
|
285
|
+
- **Trigger**: \`${EVENT_NAME}\`"
|
|
286
|
+
fi
|
|
287
|
+
|
|
288
|
+
FINAL_BODY="${BODY_CONTENT}
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
|
|
292
|
+
|
|
293
|
+
TEMP_BODY=$(mktemp)
|
|
294
|
+
echo "$FINAL_BODY" > "$TEMP_BODY"
|
|
295
|
+
gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
|
|
296
|
+
rm -f "$TEMP_BODY"
|
|
297
|
+
|
|
298
|
+
if [ "$JOB_STATUS" = "success" ]; then
|
|
299
|
+
gh issue edit "$ISSUE_NUMBER" --add-label "status:success" --remove-label "status:running"
|
|
300
|
+
gh issue close "$ISSUE_NUMBER" --reason completed
|
|
301
|
+
echo "✓ Routine run issue #$ISSUE_NUMBER closed as completed."
|
|
302
|
+
else
|
|
303
|
+
INTERRUPTION_BODY="### ❌ Milestone: Run Interrupted / Failed
|
|
304
|
+
- **Routine**: \`autowork\`
|
|
305
|
+
- **Status**: Workflow job failed or timed out (\`${JOB_STATUS}\`)
|
|
306
|
+
- **Step**: Actions execution halted before normal completion
|
|
307
|
+
- **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
|
|
311
|
+
gh issue comment "$ISSUE_NUMBER" --body "$INTERRUPTION_BODY" || true
|
|
312
|
+
gh issue edit "$ISSUE_NUMBER" --add-label "status:failure,needs-attention" --remove-label "status:running"
|
|
313
|
+
echo "⚠️ Routine run issue #$ISSUE_NUMBER left open for triage (status: $JOB_STATUS)."
|
|
314
|
+
fi
|
|
@@ -4,17 +4,16 @@ on:
|
|
|
4
4
|
issues:
|
|
5
5
|
types: [labeled, opened]
|
|
6
6
|
|
|
7
|
-
concurrency:
|
|
8
|
-
group: autowork-bug-${{ github.event.issue.number }}
|
|
9
|
-
cancel-in-progress: true
|
|
10
|
-
|
|
11
7
|
jobs:
|
|
12
8
|
fire-autowork:
|
|
13
9
|
if: >-
|
|
14
10
|
(github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'bug') && (contains(github.event.issue.labels.*.name, 'priority/P1') || contains(github.event.issue.labels.*.name, 'priority/P0'))) ||
|
|
15
11
|
(github.event.action == 'labeled' && contains(github.event.issue.labels.*.name, 'bug') && (contains(github.event.issue.labels.*.name, 'priority/P1') || contains(github.event.issue.labels.*.name, 'priority/P0')))
|
|
12
|
+
concurrency:
|
|
13
|
+
group: autowork-bug-${{ github.event.issue.number }}
|
|
14
|
+
cancel-in-progress: true
|
|
16
15
|
runs-on: ubuntu-latest
|
|
17
|
-
timeout-minutes:
|
|
16
|
+
timeout-minutes: 70
|
|
18
17
|
permissions:
|
|
19
18
|
contents: write
|
|
20
19
|
issues: write
|
|
@@ -27,7 +26,7 @@ jobs:
|
|
|
27
26
|
with:
|
|
28
27
|
fetch-depth: 0
|
|
29
28
|
token: ${{ secrets.GH_PAT || github.token }}
|
|
30
|
-
|
|
29
|
+
persist-credentials: false
|
|
31
30
|
|
|
32
31
|
- name: Setup Node.js
|
|
33
32
|
uses: actions/setup-node@v4
|
|
@@ -35,10 +34,13 @@ jobs:
|
|
|
35
34
|
node-version: 22
|
|
36
35
|
|
|
37
36
|
- name: Configure Git author identity
|
|
37
|
+
env:
|
|
38
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
38
39
|
run: |
|
|
39
40
|
git config --global user.name "github-actions[bot]"
|
|
40
41
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
41
42
|
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
43
|
+
gh auth setup-git
|
|
42
44
|
|
|
43
45
|
- name: Cache Antigravity CLI
|
|
44
46
|
id: cache-agy
|
|
@@ -81,15 +83,83 @@ jobs:
|
|
|
81
83
|
fi
|
|
82
84
|
echo "skills_prompt=$SKILLS_PROMPT" >> "$GITHUB_OUTPUT"
|
|
83
85
|
|
|
86
|
+
- name: Resolve routine configuration
|
|
87
|
+
id: routine-config
|
|
88
|
+
run: |
|
|
89
|
+
ROUTINE="autowork"
|
|
90
|
+
DEFAULT_MODEL="gemini-3.8-flash-high"
|
|
91
|
+
DEFAULT_TIMEOUT="60"
|
|
92
|
+
|
|
93
|
+
MODEL="$DEFAULT_MODEL"
|
|
94
|
+
TIMEOUT="$DEFAULT_TIMEOUT"
|
|
95
|
+
|
|
96
|
+
if [ -f "agents-manifest.json" ]; then
|
|
97
|
+
CONFIG_JSON=$(node -e '
|
|
98
|
+
try {
|
|
99
|
+
const fs = require("fs");
|
|
100
|
+
const m = JSON.parse(fs.readFileSync("agents-manifest.json", "utf8"));
|
|
101
|
+
const r = process.argv[1];
|
|
102
|
+
const model = m.models?.[r] || m.models?.default;
|
|
103
|
+
const timeout = m.budgets?.timeoutMinutes?.[r] || m.budgets?.timeoutMinutes?.default;
|
|
104
|
+
console.log(JSON.stringify({ model: model || "", timeout: timeout ? String(timeout) : "" }));
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.log(JSON.stringify({ model: "", timeout: "" }));
|
|
107
|
+
}
|
|
108
|
+
' "$ROUTINE")
|
|
109
|
+
|
|
110
|
+
RESOLVED_MODEL=$(node -e "try { console.log(JSON.parse(process.argv[1]).model || ''); } catch {}" "$CONFIG_JSON")
|
|
111
|
+
RESOLVED_TIMEOUT=$(node -e "try { console.log(JSON.parse(process.argv[1]).timeout || ''); } catch {}" "$CONFIG_JSON")
|
|
112
|
+
|
|
113
|
+
if [ -n "$RESOLVED_MODEL" ]; then
|
|
114
|
+
MODEL="$RESOLVED_MODEL"
|
|
115
|
+
fi
|
|
116
|
+
if [ -n "$RESOLVED_TIMEOUT" ]; then
|
|
117
|
+
TIMEOUT="$RESOLVED_TIMEOUT"
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
echo "model=$MODEL" >> "$GITHUB_OUTPUT"
|
|
122
|
+
echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
|
|
123
|
+
echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
|
|
124
|
+
|
|
125
|
+
- name: Initialize Routine Run Issue
|
|
126
|
+
id: run-issue
|
|
127
|
+
env:
|
|
128
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
129
|
+
ISSUE_NUM: ${{ github.event.issue.number }}
|
|
130
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
131
|
+
RUN_ID: ${{ github.run_id }}
|
|
132
|
+
SERVER_URL: ${{ github.server_url }}
|
|
133
|
+
REPOSITORY: ${{ github.repository }}
|
|
134
|
+
run: |
|
|
135
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
|
|
136
|
+
TITLE="[autowork] run ${TIMESTAMP} (Issue #${ISSUE_NUM})"
|
|
137
|
+
BODY="### Autonomous Routine Execution in Progress
|
|
138
|
+
- **Routine**: \`autowork\`
|
|
139
|
+
- **Timestamp**: \`${TIMESTAMP}\`
|
|
140
|
+
- **Trigger**: \`${EVENT_NAME}\` (High-priority bug)
|
|
141
|
+
- **Target**: Issue #${ISSUE_NUM}
|
|
142
|
+
- **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
|
|
146
|
+
ISSUE_URL=$(gh issue create --title "$TITLE" --body "$BODY" --label "routine-log,routine:autowork,status:running,runner:github-actions")
|
|
147
|
+
ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
|
|
148
|
+
echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
|
|
149
|
+
echo "ROUTINE_ISSUE_NUMBER=$ISSUE_NUMBER" >> "$GITHUB_ENV"
|
|
150
|
+
|
|
84
151
|
- name: Run Autowork
|
|
85
|
-
timeout-minutes:
|
|
152
|
+
timeout-minutes: 60
|
|
86
153
|
env:
|
|
87
154
|
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
88
155
|
GOOGLE_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
89
156
|
ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
90
157
|
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
91
158
|
TARGET_ISSUE: ${{ github.event.issue.number }}
|
|
159
|
+
ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
|
|
92
160
|
SKILLS_PROMPT: ${{ steps.skills.outputs.skills_prompt }}
|
|
161
|
+
MODEL: ${{ steps.routine-config.outputs.model || 'gemini-3.8-flash-high' }}
|
|
162
|
+
PRINT_TIMEOUT: ${{ steps.routine-config.outputs.print_timeout || '60m' }}
|
|
93
163
|
GITHUB_SERVER_URL: ${{ github.server_url }}
|
|
94
164
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
95
165
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
@@ -97,7 +167,105 @@ jobs:
|
|
|
97
167
|
PROMPT="You are the Autowork routine for this repository. A high-priority bug was filed. Read and follow .github/prompts/autowork.md. ${SKILLS_PROMPT} Your target is issue #${TARGET_ISSUE}. You are in Targeted mode: work issue #${TARGET_ISSUE} directly."
|
|
98
168
|
|
|
99
169
|
agy -p "$PROMPT" \
|
|
100
|
-
--model
|
|
170
|
+
--model "$MODEL" \
|
|
101
171
|
--output-format text \
|
|
102
|
-
--print-timeout
|
|
172
|
+
--print-timeout "$PRINT_TIMEOUT" \
|
|
103
173
|
--dangerously-skip-permissions
|
|
174
|
+
|
|
175
|
+
- name: Emit run summary
|
|
176
|
+
if: always()
|
|
177
|
+
run: |
|
|
178
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
179
|
+
if [ -f "$REPORT_FILE" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
|
|
180
|
+
cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
- name: Emit Fleet Telemetry (Opt-in)
|
|
184
|
+
if: always()
|
|
185
|
+
env:
|
|
186
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
187
|
+
TELEMETRY_ENDPOINT: ${{ secrets.JONAH_FLEET_TELEMETRY_ENDPOINT }}
|
|
188
|
+
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
189
|
+
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
190
|
+
GITHUB_RUN_NUMBER: ${{ github.run_number }}
|
|
191
|
+
run: |
|
|
192
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
193
|
+
if [ -f "$REPORT_FILE" ]; then
|
|
194
|
+
npx --yes jonah-fleet telemetry --emit --log "$REPORT_FILE" --endpoint "$TELEMETRY_ENDPOINT" || true
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
- name: Verify Atomic Handoff Invariant (PR Existence Guard)
|
|
198
|
+
if: always()
|
|
199
|
+
env:
|
|
200
|
+
GH_TOKEN: ${{ github.token }}
|
|
201
|
+
run: |
|
|
202
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
203
|
+
if [ -f "$REPORT_FILE" ]; then
|
|
204
|
+
if grep -q "Result.*SUCCESS" "$REPORT_FILE"; then
|
|
205
|
+
WORKED_BRANCH=$(grep -E '^\s*-\s*(Pushed branch|Branch):' "$REPORT_FILE" | head -n 1 | sed -E 's/.*`([^`]+)`.*/\1/')
|
|
206
|
+
if [ -n "$WORKED_BRANCH" ] && [[ "$WORKED_BRANCH" =~ (feat|fix)/ ]]; then
|
|
207
|
+
echo "Verifying PR existence for branch: $WORKED_BRANCH"
|
|
208
|
+
PR_COUNT=$(gh pr list --head "$WORKED_BRANCH" --state all --json number --jq 'length' 2>/dev/null || echo "0")
|
|
209
|
+
if [ "$PR_COUNT" -eq 0 ]; then
|
|
210
|
+
echo "::error::Atomic Handoff Invariant Violated: Branch '$WORKED_BRANCH' was implemented and pushed, but no pull request exists on GitHub!" >&2
|
|
211
|
+
exit 1
|
|
212
|
+
fi
|
|
213
|
+
echo "✓ Verified pull request exists on GitHub for branch: $WORKED_BRANCH"
|
|
214
|
+
fi
|
|
215
|
+
fi
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
- name: Reconcile Routine Run Issue
|
|
219
|
+
if: always()
|
|
220
|
+
env:
|
|
221
|
+
GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
|
|
222
|
+
ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
|
|
223
|
+
JOB_STATUS: ${{ job.status }}
|
|
224
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
225
|
+
RUN_ID: ${{ github.run_id }}
|
|
226
|
+
SERVER_URL: ${{ github.server_url }}
|
|
227
|
+
REPOSITORY: ${{ github.repository }}
|
|
228
|
+
run: |
|
|
229
|
+
if [ -z "$ISSUE_NUMBER" ]; then
|
|
230
|
+
echo "No routine issue to reconcile."
|
|
231
|
+
exit 0
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
REPORT_FILE=".jonah-fleet/run-report.md"
|
|
235
|
+
|
|
236
|
+
if [ -f "$REPORT_FILE" ]; then
|
|
237
|
+
BODY_CONTENT=$(cat "$REPORT_FILE")
|
|
238
|
+
else
|
|
239
|
+
BODY_CONTENT="### Autonomous Routine Execution Completed (${JOB_STATUS})
|
|
240
|
+
- **Routine**: \`autowork\`
|
|
241
|
+
- **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
|
|
242
|
+
- **Trigger**: \`${EVENT_NAME}\`"
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
FINAL_BODY="${BODY_CONTENT}
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
|
|
249
|
+
|
|
250
|
+
TEMP_BODY=$(mktemp)
|
|
251
|
+
echo "$FINAL_BODY" > "$TEMP_BODY"
|
|
252
|
+
gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
|
|
253
|
+
rm -f "$TEMP_BODY"
|
|
254
|
+
|
|
255
|
+
if [ "$JOB_STATUS" = "success" ]; then
|
|
256
|
+
gh issue edit "$ISSUE_NUMBER" --add-label "status:success" --remove-label "status:running"
|
|
257
|
+
gh issue close "$ISSUE_NUMBER" --reason completed
|
|
258
|
+
echo "✓ Routine run issue #$ISSUE_NUMBER closed as completed."
|
|
259
|
+
else
|
|
260
|
+
INTERRUPTION_BODY="### ❌ Milestone: Run Interrupted / Failed
|
|
261
|
+
- **Routine**: \`autowork\`
|
|
262
|
+
- **Status**: Workflow job failed or timed out (\`${JOB_STATUS}\`)
|
|
263
|
+
- **Step**: Actions execution halted before normal completion
|
|
264
|
+
- **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
|
|
268
|
+
gh issue comment "$ISSUE_NUMBER" --body "$INTERRUPTION_BODY" || true
|
|
269
|
+
gh issue edit "$ISSUE_NUMBER" --add-label "status:failure,needs-attention" --remove-label "status:running"
|
|
270
|
+
echo "⚠️ Routine run issue #$ISSUE_NUMBER left open for triage (status: $JOB_STATUS)."
|
|
271
|
+
fi
|