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.
Files changed (49) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +25 -2
  3. package/dist/commands/daemon.d.ts.map +1 -1
  4. package/dist/commands/init.d.ts +3 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/labels.d.ts +11 -0
  7. package/dist/commands/labels.d.ts.map +1 -0
  8. package/dist/commands/status.d.ts.map +1 -1
  9. package/dist/commands/sync.d.ts.map +1 -1
  10. package/dist/commands/telemetry.d.ts.map +1 -1
  11. package/dist/index.js +2527 -519
  12. package/dist/lib/daemon-keys.d.ts +103 -0
  13. package/dist/lib/daemon-keys.d.ts.map +1 -0
  14. package/dist/lib/daemon.d.ts +8 -2
  15. package/dist/lib/daemon.d.ts.map +1 -1
  16. package/dist/lib/fleet-query.d.ts.map +1 -1
  17. package/dist/lib/labels.d.ts +68 -0
  18. package/dist/lib/labels.d.ts.map +1 -0
  19. package/dist/lib/manifest.d.ts +6 -0
  20. package/dist/lib/manifest.d.ts.map +1 -1
  21. package/dist/lib/presets.d.ts +52 -1
  22. package/dist/lib/presets.d.ts.map +1 -1
  23. package/dist/lib/runner.d.ts +114 -0
  24. package/dist/lib/runner.d.ts.map +1 -1
  25. package/dist/lib/telemetry.d.ts.map +1 -1
  26. package/dist/lib/terminal-card.d.ts +24 -1
  27. package/dist/lib/terminal-card.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/schema.json +74 -1
  30. package/templates/prompts/ORCHESTRATION.md +84 -41
  31. package/templates/prompts/_prompt-template.md +10 -13
  32. package/templates/prompts/analytics-review.md +4 -2
  33. package/templates/prompts/autowork.md +76 -35
  34. package/templates/prompts/dependency-update-security-check.md +4 -2
  35. package/templates/prompts/design-review.md +125 -0
  36. package/templates/prompts/issues-housekeeping.md +10 -8
  37. package/templates/prompts/optimizer.md +31 -12
  38. package/templates/prompts/peer-review.md +42 -7
  39. package/templates/prompts/product-planning.md +14 -10
  40. package/templates/workflows/autowork-cron.yml +137 -38
  41. package/templates/workflows/dependency-check-cron.yml +127 -2
  42. package/templates/workflows/design-review-cron.yml +221 -0
  43. package/templates/workflows/issues-housekeeping-cron.yml +127 -2
  44. package/templates/workflows/prompt-optimizer-cron.yml +134 -9
  45. package/templates/workflows/sync-fleet.yml +4 -0
  46. package/templates/workflows/trigger-autowork-manual.yml +154 -11
  47. package/templates/workflows/trigger-autowork-on-bug.yml +177 -9
  48. package/templates/workflows/trigger-autowork-on-merge.yml +178 -9
  49. package/templates/workflows/trigger-review-routine.yml +162 -22
@@ -8,7 +8,7 @@ Review a pull request (in Targeted mode for a specific `$PR_NUMBER`, or in Scan
8
8
 
9
9
  Before reading further, before any tool call, and before deciding the mode, check the environment variable `$PR_NUMBER`.
10
10
 
11
- - **$PR_NUMBER is set → Targeted mode.** The value of `$PR_NUMBER` is your target PR. You may also check `$PR_URL`. Skip all selection logic.
11
+ - **$PR_NUMBER is set → Targeted mode.** The value of `$PR_NUMBER`is your target PR. You may also check`$PR_URL`. Skip all selection logic.
12
12
  - **$PR_NUMBER is not set → Scan mode.** Only then select a PR by priority.
13
13
 
14
14
  **Targeted mode is sticky: it can never fall back to Scan mode.** Once the invocation contains a PR reference, you must review exactly that PR. If you cannot act on it (closed/merged/missing), STOP and log FAILURE.
@@ -19,7 +19,7 @@ The run is SUCCESS only if ALL of these are true:
19
19
 
20
20
  - [ ] Identified the target PR: if one was named in the invocation, reviewed exactly that PR; otherwise listed open PRs and selected one by priority
21
21
  - [ ] Ran the code-review pass (`/code-review` and security pass), and posted findings as inline review comments
22
- - [ ] Took exactly one final action: squash-merged (if PR is good, CI green and present; executed Autonomous Issue Synthesis if unlinked) OR posted findings and **converted the PR back to draft** (`gh pr ready <N> --undo`) for author/autowork in-session fixes OR, if round cap reached at round 5 with blocking findings, converted to draft and escalated to human
22
+ - [ ] Took exactly one final action: squash-merged (if PR is good, CI green and present; executed Autonomous Issue Synthesis if unlinked; closed tracking issue explicitly if referenced) OR posted findings and **converted the PR back to draft** (`gh pr ready <N> --undo`) for author/autowork in-session fixes OR, if round cap reached at round 5 with blocking findings, converted to draft and escalated to human
23
23
  - [ ] If merging: captured deferred non-blocking findings per materiality bar (filed follow-up issues for material ones, batched or dropped immaterial ones)
24
24
  - [ ] If in Scan mode and no eligible PRs exist, logged SUCCESS with "No PRs to review"
25
25
 
@@ -37,8 +37,9 @@ If any criterion cannot be met, stop immediately and log FAILURE with the reason
37
37
  ## Final action: merge or bounce to draft
38
38
 
39
39
  Every review ends in exactly one of two states:
40
+
40
41
  - **Merge** — only if PR is good, CI is green and verified on the head commit. If the PR does not reference a tracked issue (`Closes #N`), execute Autonomous Issue Synthesis prior to merge.
41
- - Sequence: (1) if unlinked, synthesize tracking issue (`gh issue create`) and link to PR (`gh pr edit`), (2) squash-merge, (3) submit held review comments, (4) file follow-up issues for deferred material findings.
42
+ - Sequence: (1) if unlinked, synthesize tracking issue (`gh issue create`) and link to PR (`gh pr edit`), (2) squash-merge (`gh pr merge <N> --squash --delete-branch`), (3) explicitly close tracking issue if referenced (`gh issue close <ISSUE_NUMBER>`), (4) submit held review comments, (5) file follow-up issues for deferred material findings.
42
43
  - Immaterial findings (style/preference) default to dying in the review thread or getting batched.
43
44
  - Mechanical doc fixes (missing changelog line, doc typo in diff) can be committed directly to `main` after squash-merge.
44
45
  - **Bounce to draft** — if any **blocking** finding remains (correctness bug, security flaw, failing/missing CI, broken contract):
@@ -63,12 +64,13 @@ Every review ends in exactly one of two states:
63
64
  ### Step 0: Determine the target PR (do this FIRST)
64
65
 
65
66
  Check if `$PR_NUMBER` is set:
67
+
66
68
  - **$PR_NUMBER is set → Targeted mode.** Review that exact PR. Skip selection steps 1–2.
67
69
  - **$PR_NUMBER is not set → Scan mode.** Proceed to steps 1–2.
68
70
 
69
71
  ### Steps 1–2: Select a PR (Scan mode only)
70
72
 
71
- 1. List all open PRs, excluding drafts, pure log PRs (`.github/prompts/logs/**`), and automated release PRs (`release-please--*` / `chore(main): release*`).
73
+ 1. List all open PRs, excluding drafts and automated release PRs (`release-please--*` / `chore(main): release*`).
72
74
  2. **Dual Execution Priority Routing**:
73
75
  - If running in **Cloud Actions** (`$GITHUB_ACTIONS` / `$CI`): Scan mode prioritizes PRs labeled `priority/P0` or `priority/P1` (or untagged PRs). Lower-priority PRs (`priority/P2`, `priority/P3`) are eligible for cloud review ONLY if they have remained ready and unreviewed for more than 48 hours (`created_at` older than 48h, acting as a cloud catchup sweep).
74
76
  - If running in **Local Agent** (`$LOCAL_AGENT`): Scan mode reviews any ready PR across all priorities (P0 → P1 → P2 → P3) with no age gating.
@@ -78,8 +80,21 @@ Check if `$PR_NUMBER` is set:
78
80
 
79
81
  ### Step 3: Round tracking & Starting Review marker
80
82
 
81
- - Post a "Starting review (round N)" comment on the target PR to claim the review window.
83
+ - Post a "Starting review (round N)" comment on the target PR to claim the review window:
84
+ - If `$ROUTINE_ISSUE_NUMBER` is set in the environment or routine prompt, include a link to the tracking log issue:
85
+ `Starting review (round N) · [Run Log #$ROUTINE_ISSUE_NUMBER](${GITHUB_SERVER_URL:-https://github.com}/${GITHUB_REPOSITORY}/issues/${ROUTINE_ISSUE_NUMBER})`
86
+ (or `Starting review (round N) · Run log: #$ROUTINE_ISSUE_NUMBER`).
87
+ - If `$ROUTINE_ISSUE_NUMBER` is not set, post `Starting review (round N)`.
82
88
  - Check round count `N`. If `N >= 5` and blocking findings persist, prepare to escalate.
89
+ - **Milestone 1 (Intake & Review Scope)**: If `$ROUTINE_ISSUE_NUMBER` is set, emit milestone card to the routine issue thread:
90
+ ```bash
91
+ gh issue comment "$ROUTINE_ISSUE_NUMBER" --body "### 🧭 Milestone: Intake & Review Scope
92
+ - **Phase**: \`Phase 1 · Review Target & Scope\`
93
+ - **Status**: ⏳ In Progress
94
+ - **Target / Context**: \`PR #<PR_NUMBER> (Round N)\`
95
+ - **Key Decision / Finding**: Claimed review window; starting multi-angle evaluation passes.
96
+ - **Next**: Multi-Angle Code Review Pass" || true
97
+ ```
83
98
 
84
99
  ### Step 4: Multi-Angle Code Review Pass
85
100
 
@@ -98,12 +113,14 @@ Check if `$PR_NUMBER` is set:
98
113
  ### Step 5: Classify Findings & Make Decision
99
114
 
100
115
  Classify each finding:
116
+
101
117
  - **Blocking**: Broken logic, security hole, data loss, regression, broken tests, missing deliverable from the issue/PR specification.
102
118
  - **Non-blocking**: Minor refactor, style preference, performance micro-optimization, missing `Closes #N` on contributor PRs with self-contained descriptions.
103
119
 
104
120
  ### Step 5.5: Autonomous Issue Synthesis (for unlinked PRs)
105
121
 
106
122
  If the PR is clean and approved for merge, but lacks a `Closes #N` tracking link:
123
+
107
124
  1. Synthesize a retroactive tracking issue on GitHub:
108
125
  ```bash
109
126
  gh issue create --title "<PR Title>" --body "Tracked retroactively from external pull request #<PR_NUMBER>.\n\n## Deliverables & Context\n<PR Description>\n\n_Synthesized autonomously by Jonah Fleet Peer Review_"
@@ -120,17 +137,35 @@ If the PR is clean and approved for merge, but lacks a `Closes #N` tracking link
120
137
  - If `N < 5`: Post inline comments, submit review as `COMMENT`, and convert PR to draft (`gh pr ready <N> --undo`).
121
138
  - If `N >= 5`: Convert PR to draft, post summary comment escalating to repo maintainer, and apply `needs-human` label.
122
139
  - **If Clean (or only Non-blocking findings)**:
140
+ - If the PR branch has minor mechanical merge conflicts against `origin/main` (e.g. adjacent `CHANGELOG.md` entries from concurrent merges) while code and tests are sound, resolve the conflict mechanically via `/resolving-merge-conflicts` before squash-merging rather than bouncing the PR back to draft.
123
141
  - If PR lacks `Closes #N`, execute Autonomous Issue Synthesis (Step 5.5).
142
+ - Extract the tracking issue number `$ISSUE_NUMBER` from the PR description or title (e.g. `Closes #<N>`, `Fixes #<N>`, `Resolves #<N>`).
124
143
  - Squash-merge the PR: `gh pr merge <N> --squash --delete-branch`.
144
+ - **Explicit Tracking Issue Closure Guardrail**: If a tracking issue was referenced (`$ISSUE_NUMBER`), explicitly close it immediately after merge rather than relying solely on GitHub's native keyword parser (which often fails to trigger on bot-merged squash commits or draft PRs):
145
+ ```bash
146
+ gh issue close "$ISSUE_NUMBER" --comment "Closed via PR #<N> (merged into main)."
147
+ ```
125
148
  - Submit held review comments.
149
+ - In any review summary, decision comment, or escalation comment posted to the PR, include the run log reference if `$ROUTINE_ISSUE_NUMBER` is set (e.g. `- **Run Log**: [#$ROUTINE_ISSUE_NUMBER](${GITHUB_SERVER_URL:-https://github.com}/${GITHUB_REPOSITORY}/issues/${ROUTINE_ISSUE_NUMBER})`).
126
150
  - File follow-up issues for material non-blocking findings.
127
151
  - If mechanical doc fixes are needed, commit directly to `main`.
128
152
 
129
153
  ## Logging
130
154
 
131
- After completing (SUCCESS or FAILURE), write a log file to `.github/prompts/logs/peer-review/{timestamp}.md` following the schema in `.github/prompts/logs/_template.md`. Include:
155
+ After completing (SUCCESS or FAILURE), record run execution details to `.jonah-fleet/run-report.md`. Include:
156
+
132
157
  - Prompt SHA
133
158
  - Target PR number and decision (MERGE / BOUNCE / ESCALATE)
134
159
  - Execution trace and findings summary
135
160
 
136
- **Important**: Commit the log file directly to `main` and push. Follow the Log delivery fallback in `ORCHESTRATION.md` if direct push fails.
161
+ **Issue Logging Protocol**:
162
+ - **Milestone 4 (Run Completed)**: If `$ROUTINE_ISSUE_NUMBER` is set, emit compact milestone card to close out the comment stream:
163
+ ```bash
164
+ gh issue comment "$ROUTINE_ISSUE_NUMBER" --body "### 🏁 Milestone: Run Completed
165
+ - **Phase**: \`Phase 4 · Reconciliation\`
166
+ - **Status**: ✅ SUCCESS
167
+ - **Target / Context**: \`PR #<PR_NUMBER>\`
168
+ - **Key Decision / Finding**: Review completed with decision \`<MERGE | BOUNCE | ESCALATE>\`.
169
+ - **Next**: Routine finished; issue closed by harness" || true
170
+ ```
171
+ - Follow the Routine Issue Logging & Telemetry Protocol in `ORCHESTRATION.md`. Never commit run logs to git branches.
@@ -11,8 +11,8 @@ This routine runs behind a **human approval gate**: it **never files autowork-re
11
11
  This routine runs in two modes: **Propose** (scheduled cron sweep / unapproved fire) and **Promote** (operator-approved fire).
12
12
 
13
13
  In **Propose mode**, SUCCESS requires:
14
- - [ ] Read current roadmap, domain documentation, closed measurement trackers, and recent feedback/analytics findings
15
- - [ ] Performed Feature Pruning & Deprecation Audit: evaluated shipped features and measurement outcomes for low-ROI (<2% user adoption or >50% failure rate) features, drafting deprecation, removal, or simplification proposals
14
+ - [ ] Read current roadmap, domain documentation, closed measurement trackers, recent feedback/analytics findings, and the latest open `🎨 Design Review` issue / recent design-review routine run issues
15
+ - [ ] Performed Feature Pruning & Deprecation Audit: evaluated shipped features, measurement outcomes (<2% user adoption or >50% failure rate), and Design Review pruning/clutter directives, drafting deprecation, removal, or simplification proposals
16
16
  - [ ] Created or updated exactly one dated staging issue (`🗺️ Product Plan — {date}`) containing:
17
17
  - Up to 3 well-scoped proposals (Summary/Tasks/Why/Complexity), covering additions, pivots, or deprecations
18
18
  - Backlog re-ranking recommendations
@@ -51,10 +51,10 @@ If any criterion cannot be met, stop immediately and log FAILURE with the reason
51
51
 
52
52
  ### Steps 1–3: Propose Mode (Staging Proposals)
53
53
 
54
- 1. Read `ROADMAP.md`, `AGENTS.md`, closed measurement trackers with `RECOMMENDATION: [PIVOT | DEPRECATE | ITERATE]`, and open issues.
54
+ 1. Read `ROADMAP.md`, `AGENTS.md`, closed measurement trackers with `RECOMMENDATION: [PIVOT | DEPRECATE | ITERATE]`, the latest open `🎨 Design Review` issue (and recent run issues with `gh issue list --label "routine:design-review"`), and open issues.
55
55
  2. **Feature Pruning & Deprecation Audit**:
56
- - Audit shipped features and closed measurement tracker verdicts.
57
- - For any feature with <2% user adoption, sub-threshold CTR, or >50% failure rate, draft explicit deprecation, removal, or pivot proposals to keep the codebase lean and eliminate maintenance waste.
56
+ - Audit shipped features, closed measurement tracker verdicts, and `🎨 Design Review` clutter/pruning findings.
57
+ - For any feature with <2% user adoption, sub-threshold CTR, >50% failure rate, or persistent UI clutter flagged by Design Review, draft explicit deprecation, removal, or pivot proposals to keep the codebase lean and eliminate maintenance waste.
58
58
  3. Draft up to 3 high-impact proposals (including additions, pivots, or deprecations) based on roadmap priorities, measurement outcomes, and user feedback.
59
59
  4. For proposals sized `size/M` or above, draft a formal specification using `/to-spec`.
60
60
  5. Stage all proposals in a dedicated staging issue: `🗺️ Product Plan — {YYYY-MM-DD}` assigned to the repo maintainer.
@@ -70,9 +70,13 @@ If any criterion cannot be met, stop immediately and log FAILURE with the reason
70
70
 
71
71
  ## Logging
72
72
 
73
- After completing (SUCCESS or FAILURE), write a log file to `.github/prompts/logs/product-planning/{timestamp}.md` following the schema in `.github/prompts/logs/_template.md`. Include:
74
- - Prompt SHA
75
- - Mode (Propose or Promote)
76
- - Staged or promoted proposals tally
73
+ Follow the Routine Issue Logging Protocol in `ORCHESTRATION.md`:
74
+ 1. Write the final run report to `.jonah-fleet/run-report.md`.
75
+ 2. Include the Run Summary table with:
76
+ - Routine: `product-planning`
77
+ - Mode: `Propose` or `Promote`
78
+ - Result: `SUCCESS` or `FAILURE`
79
+ - Prompt SHA: (run `git rev-parse --short HEAD:.github/prompts/product-planning.md` or template)
80
+ - Staged or promoted proposals tally
81
+ 3. The surrounding execution harness will reconcile the corresponding GitHub issue.
77
82
 
78
- **Important**: Commit the log file directly to `main` and push. Follow the Log delivery fallback in `ORCHESTRATION.md` if direct push fails.
@@ -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
@@ -105,6 +108,74 @@ jobs:
105
108
  fi
106
109
  echo "skills_prompt=$SKILLS_PROMPT" >> "$GITHUB_OUTPUT"
107
110
 
111
+ - name: Resolve routine configuration
112
+ id: routine-config
113
+ run: |
114
+ ROUTINE="autowork"
115
+ DEFAULT_MODEL="gemini-3.8-flash-high"
116
+ DEFAULT_TIMEOUT="60"
117
+
118
+ MODEL="$DEFAULT_MODEL"
119
+ TIMEOUT="$DEFAULT_TIMEOUT"
120
+
121
+ if [ -f "agents-manifest.json" ]; then
122
+ CONFIG_JSON=$(node -e '
123
+ try {
124
+ const fs = require("fs");
125
+ const m = JSON.parse(fs.readFileSync("agents-manifest.json", "utf8"));
126
+ const r = process.argv[1];
127
+ const model = m.models?.[r] || m.models?.default;
128
+ const timeout = m.budgets?.timeoutMinutes?.[r] || m.budgets?.timeoutMinutes?.default;
129
+ console.log(JSON.stringify({ model: model || "", timeout: timeout ? String(timeout) : "" }));
130
+ } catch (e) {
131
+ console.log(JSON.stringify({ model: "", timeout: "" }));
132
+ }
133
+ ' "$ROUTINE")
134
+
135
+ RESOLVED_MODEL=$(node -e "try { console.log(JSON.parse(process.argv[1]).model || ''); } catch {}" "$CONFIG_JSON")
136
+ RESOLVED_TIMEOUT=$(node -e "try { console.log(JSON.parse(process.argv[1]).timeout || ''); } catch {}" "$CONFIG_JSON")
137
+
138
+ if [ -n "$RESOLVED_MODEL" ]; then
139
+ MODEL="$RESOLVED_MODEL"
140
+ fi
141
+ if [ -n "$RESOLVED_TIMEOUT" ]; then
142
+ TIMEOUT="$RESOLVED_TIMEOUT"
143
+ fi
144
+ fi
145
+
146
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
147
+ echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
148
+ echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
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
+
108
179
  - name: Run Autowork
109
180
  timeout-minutes: 60
110
181
  env:
@@ -113,7 +184,10 @@ jobs:
113
184
  ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
114
185
  GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
115
186
  TARGET_ISSUE: ${{ inputs.target_issue || inputs.issue_number }}
187
+ ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
116
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' }}
117
191
  GITHUB_SERVER_URL: ${{ github.server_url }}
118
192
  GITHUB_REPOSITORY: ${{ github.repository }}
119
193
  GITHUB_RUN_ID: ${{ github.run_id }}
@@ -125,17 +199,17 @@ jobs:
125
199
  fi
126
200
 
127
201
  agy -p "$PROMPT" \
128
- --model gemini-3.7-flash-high \
202
+ --model "$MODEL" \
129
203
  --output-format text \
130
- --print-timeout 60m \
204
+ --print-timeout "$PRINT_TIMEOUT" \
131
205
  --dangerously-skip-permissions
132
206
 
133
207
  - name: Emit run summary
134
208
  if: always()
135
209
  run: |
136
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
137
- if [ -n "$LATEST_LOG" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
138
- 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"
139
213
  fi
140
214
 
141
215
  - name: Emit Fleet Telemetry (Opt-in)
@@ -147,9 +221,9 @@ jobs:
147
221
  GITHUB_RUN_ID: ${{ github.run_id }}
148
222
  GITHUB_RUN_NUMBER: ${{ github.run_number }}
149
223
  run: |
150
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
151
- if [ -n "$LATEST_LOG" ] && [ -f "$LATEST_LOG" ]; then
152
- 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
153
227
  fi
154
228
 
155
229
  - name: Verify Atomic Handoff Invariant (PR Existence Guard)
@@ -157,10 +231,10 @@ jobs:
157
231
  env:
158
232
  GH_TOKEN: ${{ github.token }}
159
233
  run: |
160
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
161
- if [ -n "$LATEST_LOG" ]; then
162
- if grep -q "Result.*SUCCESS" "$LATEST_LOG"; then
163
- 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/')
164
238
  if [ -n "$WORKED_BRANCH" ] && [[ "$WORKED_BRANCH" =~ (feat|fix)/ ]]; then
165
239
  echo "Verifying PR existence for branch: $WORKED_BRANCH"
166
240
  PR_COUNT=$(gh pr list --head "$WORKED_BRANCH" --state all --json number --jq 'length' 2>/dev/null || echo "0")
@@ -173,33 +247,58 @@ jobs:
173
247
  fi
174
248
  fi
175
249
 
176
- - name: Commit and push run log directly to main
250
+ - name: Reconcile Routine Run Issue
177
251
  if: always()
178
252
  env:
179
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 }}
180
260
  run: |
181
- LATEST_LOG=$(ls -t .github/prompts/logs/autowork/*.md 2>/dev/null | head -n 1)
182
- if [ -n "$LATEST_LOG" ] && [ -f "$LATEST_LOG" ]; then
183
- TMP_LOG_FILE=$(mktemp)
184
- cp "$LATEST_LOG" "$TMP_LOG_FILE"
185
- LOG_REL_PATH="$LATEST_LOG"
186
- LOG_NAME=$(basename "$LATEST_LOG" .md)
187
-
188
- git fetch origin main:main || git fetch origin main || true
189
- git checkout main || git checkout -B main origin/main || true
190
-
191
- mkdir -p "$(dirname "$LOG_REL_PATH")"
192
- cp "$TMP_LOG_FILE" "$LOG_REL_PATH"
193
- rm -f "$TMP_LOG_FILE"
194
-
195
- git add "$LOG_REL_PATH"
196
- if ! git diff --cached --quiet; then
197
- git commit -m "docs(log): record autowork run ${LOG_NAME} [skip ci]" || true
198
- if [ -n "$GH_TOKEN" ]; then
199
- git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" main || git push origin main || true
200
- else
201
- git push origin main || true
202
- fi
203
- 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)."
204
303
  fi
205
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
@@ -65,6 +69,69 @@ jobs:
65
69
  printf '%s' "$ANTIGRAVITY_OAUTH_TOKEN" > "$HOME/.gemini/antigravity-cli/antigravity-oauth-token"
66
70
  chmod 600 "$HOME/.gemini/antigravity-cli/antigravity-oauth-token"
67
71
 
72
+ - name: Resolve routine configuration
73
+ id: routine-config
74
+ run: |
75
+ ROUTINE="dependency-update-security-check"
76
+ DEFAULT_MODEL="gemini-3.8-flash-medium"
77
+ DEFAULT_TIMEOUT="25"
78
+
79
+ MODEL="$DEFAULT_MODEL"
80
+ TIMEOUT="$DEFAULT_TIMEOUT"
81
+
82
+ if [ -f "agents-manifest.json" ]; then
83
+ CONFIG_JSON=$(node -e '
84
+ try {
85
+ const fs = require("fs");
86
+ const m = JSON.parse(fs.readFileSync("agents-manifest.json", "utf8"));
87
+ const r = process.argv[1];
88
+ const model = m.models?.[r] || m.models?.default;
89
+ const timeout = m.budgets?.timeoutMinutes?.[r] || m.budgets?.timeoutMinutes?.default;
90
+ console.log(JSON.stringify({ model: model || "", timeout: timeout ? String(timeout) : "" }));
91
+ } catch (e) {
92
+ console.log(JSON.stringify({ model: "", timeout: "" }));
93
+ }
94
+ ' "$ROUTINE")
95
+
96
+ RESOLVED_MODEL=$(node -e "try { console.log(JSON.parse(process.argv[1]).model || ''); } catch {}" "$CONFIG_JSON")
97
+ RESOLVED_TIMEOUT=$(node -e "try { console.log(JSON.parse(process.argv[1]).timeout || ''); } catch {}" "$CONFIG_JSON")
98
+
99
+ if [ -n "$RESOLVED_MODEL" ]; then
100
+ MODEL="$RESOLVED_MODEL"
101
+ fi
102
+ if [ -n "$RESOLVED_TIMEOUT" ]; then
103
+ TIMEOUT="$RESOLVED_TIMEOUT"
104
+ fi
105
+ fi
106
+
107
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
108
+ echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
109
+ echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
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
+
68
135
  - name: Run Dependency Update Check
69
136
  timeout-minutes: 25
70
137
  env:
@@ -72,6 +139,9 @@ jobs:
72
139
  GOOGLE_API_KEY: ${{ secrets.GEMINI_API_KEY }}
73
140
  ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
74
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' }}
75
145
  GITHUB_SERVER_URL: ${{ github.server_url }}
76
146
  GITHUB_REPOSITORY: ${{ github.repository }}
77
147
  GITHUB_RUN_ID: ${{ github.run_id }}
@@ -79,7 +149,62 @@ jobs:
79
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."
80
150
 
81
151
  agy -p "$PROMPT" \
82
- --model gemini-3.7-flash-high \
152
+ --model "$MODEL" \
83
153
  --output-format text \
84
- --print-timeout 25m \
154
+ --print-timeout "$PRINT_TIMEOUT" \
85
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