jonah-fleet 1.23.1 → 1.25.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 CHANGED
@@ -5,6 +5,27 @@ All notable changes to `jonah-fleet` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.25.0](https://github.com/juliendurandeu/jonah-fleet/compare/v1.24.0...v1.25.0) (2026-09-23)
9
+
10
+
11
+ ### Features
12
+
13
+ * **guard:** enrich LoopGuard diagnostics with action details and provision MCP in review workflows ([#367](https://github.com/juliendurandeu/jonah-fleet/issues/367)) ([a93d783](https://github.com/juliendurandeu/jonah-fleet/commit/a93d7833fd3caf6b5a4f8e50ccfeaa2d1e146c36))
14
+
15
+ ## [Unreleased]
16
+
17
+ ### Features
18
+
19
+ * **guard:** capture action arguments on LoopGuard circuit breaker trips, enrich failure cards and reports with formatted action details, and surface active tool commands in runner stdout.
20
+ * **workflows:** provision MCP servers for Antigravity CLI in `analytics-review-cron.yml` and `design-review-cron.yml`.
21
+
22
+ ## [1.24.0](https://github.com/juliendurandeu/jonah-fleet/compare/v1.23.1...v1.24.0) (2026-09-23)
23
+
24
+
25
+ ### Features
26
+
27
+ * **workflows:** support triggering autowork on issue assignment to bot/persona ([#339](https://github.com/juliendurandeu/jonah-fleet/issues/339)) ([7a976f3](https://github.com/juliendurandeu/jonah-fleet/commit/7a976f32defa9ebc464df40702986d32db8508bc))
28
+
8
29
  ## [1.23.1](https://github.com/juliendurandeu/jonah-fleet/compare/v1.23.0...v1.23.1) (2026-09-20)
9
30
 
10
31
 
@@ -35,6 +56,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
35
56
 
36
57
  ## [Unreleased]
37
58
 
59
+ ### Features
60
+
61
+ * **workflows:** support triggering autowork on issue assignment to bot persona ([#19](https://github.com/juliendurandeu/jonah-fleet/issues/19))
62
+
38
63
  ### Bug Fixes
39
64
 
40
65
  * **runner:** prevent routine tracking issues from being mistakenly claimed as target issues via `excludeIssueNumber` and `isRoutineRunTitle` guardrails.
package/dist/index.js CHANGED
@@ -115,7 +115,8 @@ var ROUTINE_TO_WORKFLOW_MAP = {
115
115
  "autowork-cron.yml",
116
116
  "trigger-autowork-on-merge.yml",
117
117
  "trigger-autowork-on-bug.yml",
118
- "trigger-autowork-manual.yml"
118
+ "trigger-autowork-manual.yml",
119
+ "trigger-autowork-on-assign.yml"
119
120
  ],
120
121
  "peer-review": ["trigger-review-routine.yml"],
121
122
  optimizer: ["prompt-optimizer-cron.yml"],
@@ -3622,7 +3623,8 @@ var LoopGuard = class {
3622
3623
  message: `Tool circuit breaker tripped: ${this.consecutiveErrorCount} consecutive identical tool errors for '${toolName}' with unchanged arguments.`,
3623
3624
  toolName,
3624
3625
  actionHash: hash,
3625
- count: this.consecutiveErrorCount
3626
+ count: this.consecutiveErrorCount,
3627
+ args
3626
3628
  });
3627
3629
  }
3628
3630
  } else {
@@ -3645,7 +3647,8 @@ var LoopGuard = class {
3645
3647
  message: `Action repetition loop detected: tool '${toolName}' called ${repetitionCount} times with identical parameters within sliding window of ${this.slidingWindowSize}.`,
3646
3648
  toolName,
3647
3649
  actionHash: hash,
3648
- count: repetitionCount
3650
+ count: repetitionCount,
3651
+ args
3649
3652
  });
3650
3653
  }
3651
3654
  }
@@ -3673,7 +3676,8 @@ var LoopGuard = class {
3673
3676
  message: `Alternating ping-pong action loop detected: ${this.pingPongThreshold} consecutive alternating cycles between tools (A-B-A-B-A-B).`,
3674
3677
  toolName,
3675
3678
  actionHash: hash,
3676
- count: this.pingPongThreshold
3679
+ count: this.pingPongThreshold,
3680
+ args
3677
3681
  });
3678
3682
  }
3679
3683
  }
@@ -3716,6 +3720,18 @@ var LoopGuard = class {
3716
3720
  return trip;
3717
3721
  }
3718
3722
  };
3723
+ function formatActionSummary(toolName, args) {
3724
+ if (!args) return toolName;
3725
+ if (typeof args === "string") return `${toolName}: ${args}`;
3726
+ if (args.CommandLine) return `${toolName}: ${args.CommandLine}`;
3727
+ if (args.command) return `${toolName}: ${args.command}`;
3728
+ if (args.TargetFile) return `${toolName}: ${args.TargetFile}`;
3729
+ if (args.path) return `${toolName}: ${args.path}`;
3730
+ if (args.AbsolutePath) return `${toolName}: ${args.AbsolutePath}`;
3731
+ if (args.Query) return `${toolName}: ${args.Query}`;
3732
+ const str = canonicalStringify(args);
3733
+ return str.length > 200 ? `${toolName}: ${str.slice(0, 197)}...` : `${toolName}: ${str}`;
3734
+ }
3719
3735
  function formatLoopGuardFailureCard(options) {
3720
3736
  const serverUrl = options.serverUrl || process.env.GITHUB_SERVER_URL || "https://github.com";
3721
3737
  const repository = options.repository || process.env.GITHUB_REPOSITORY || "";
@@ -3727,16 +3743,19 @@ function formatLoopGuardFailureCard(options) {
3727
3743
  `- **Status**: Loop guard circuit breaker tripped (\`loop_circuit_breaker\`)`,
3728
3744
  `- **Root Cause Category**: \`loop_circuit_breaker\``,
3729
3745
  `- **Trigger**: \`${options.trip.reason}\``,
3730
- `- **Reason**: ${options.trip.message}`,
3731
- `- **Action**: Process terminated to prevent runaway token burn`
3746
+ `- **Reason**: ${options.trip.message}`
3732
3747
  ];
3748
+ if (options.trip.args !== void 0) {
3749
+ lines.push(`- **Triggered Action**: \`${formatActionSummary(options.trip.toolName, options.trip.args)}\``);
3750
+ }
3751
+ lines.push(`- **Action**: Process terminated to prevent runaway token burn`);
3733
3752
  if (logUrl) {
3734
3753
  lines.push(`- **Action Log**: [View Run Logs](${logUrl})`);
3735
3754
  }
3736
3755
  return lines.join("\n");
3737
3756
  }
3738
3757
  function formatLoopGuardReport(options) {
3739
- return [
3758
+ const reportLines = [
3740
3759
  `# Run Report`,
3741
3760
  ``,
3742
3761
  `## Result`,
@@ -3757,10 +3776,16 @@ function formatLoopGuardReport(options) {
3757
3776
  `The autonomous execution was halted by the deterministic loop-guard wrapper.`,
3758
3777
  `- **Category**: \`loop_circuit_breaker\``,
3759
3778
  `- **Trigger**: \`${options.trip.reason}\``,
3760
- `- **Tool**: \`${options.trip.toolName}\``,
3779
+ `- **Tool**: \`${options.trip.toolName}\``
3780
+ ];
3781
+ if (options.trip.args !== void 0) {
3782
+ reportLines.push(`- **Parameters**: \`${formatActionSummary(options.trip.toolName, options.trip.args)}\``);
3783
+ }
3784
+ reportLines.push(
3761
3785
  `- **Action Hash**: \`${options.trip.actionHash}\``,
3762
3786
  `- **Message**: ${options.trip.message}`
3763
- ].join("\n");
3787
+ );
3788
+ return reportLines.join("\n");
3764
3789
  }
3765
3790
 
3766
3791
  // src/lib/runner.ts
@@ -6296,6 +6321,7 @@ export {
6296
6321
  LoopGuard,
6297
6322
  canonicalStringify,
6298
6323
  computeActionHash,
6324
+ formatActionSummary,
6299
6325
  formatLoopGuardFailureCard,
6300
6326
  formatLoopGuardReport
6301
6327
  };
@@ -5,6 +5,7 @@ export interface LoopGuardTrip {
5
5
  toolName: string;
6
6
  actionHash: string;
7
7
  count: number;
8
+ args?: any;
8
9
  }
9
10
  export interface ActionRecord {
10
11
  toolName: string;
@@ -57,6 +58,10 @@ export declare class LoopGuard {
57
58
  feedLine(line: string): LoopGuardTrip | null;
58
59
  private triggerTrip;
59
60
  }
61
+ /**
62
+ * Formats a concise, human-readable summary of a tool action and its parameters.
63
+ */
64
+ export declare function formatActionSummary(toolName: string, args: any): string;
60
65
  export interface LoopGuardFailureCardOptions {
61
66
  routine: string;
62
67
  trip: LoopGuardTrip;
@@ -1 +1 @@
1
- {"version":3,"file":"loop-guard.d.ts","sourceRoot":"","sources":["../../src/lib/loop-guard.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,WAAW,GAAG,oBAAoB,CAAC;AAEpF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CACxC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAarD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM,CAGrE;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,MAAM,CAAC,CAAgC;IAE/C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,qBAAqB,CAAa;IAC1C,OAAO,CAAC,aAAa,CAA8B;IAEnD,YAAY,OAAO,GAAE,gBAAqB,EAMzC;IAEM,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI,CAE9D;IAEM,SAAS,IAAI,OAAO,CAE1B;IAEM,OAAO,IAAI,aAAa,GAAG,IAAI,CAErC;IAEM,UAAU,IAAI,YAAY,EAAE,CAElC;IAEM,KAAK,IAAI,IAAI,CAKnB;IAED;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,OAAe,GAAG,aAAa,GAAG,IAAI,CAuH/F;IAED;;OAEG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAwBlD;IAED,OAAO,CAAC,WAAW;CAWpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,CAqBvF;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CA0B7E"}
1
+ {"version":3,"file":"loop-guard.d.ts","sourceRoot":"","sources":["../../src/lib/loop-guard.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,WAAW,GAAG,oBAAoB,CAAC;AAEpF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CACxC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAarD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM,CAGrE;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,MAAM,CAAC,CAAgC;IAE/C,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,qBAAqB,CAAa;IAC1C,OAAO,CAAC,aAAa,CAA8B;IAEnD,YAAY,OAAO,GAAE,gBAAqB,EAMzC;IAEM,SAAS,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI,CAE9D;IAEM,SAAS,IAAI,OAAO,CAE1B;IAEM,OAAO,IAAI,aAAa,GAAG,IAAI,CAErC;IAEM,UAAU,IAAI,YAAY,EAAE,CAElC;IAEM,KAAK,IAAI,IAAI,CAKnB;IAED;;OAEG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAE,OAAe,GAAG,aAAa,GAAG,IAAI,CA0H/F;IAED;;OAEG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAwBlD;IAED,OAAO,CAAC,WAAW;CAWpB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM,CAWvE;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,MAAM,CA0BvF;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAmC7E"}
@@ -1 +1 @@
1
- {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/lib/presets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/lib/presets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kCAAkC,CAAC,EAAE,MAAM,CAAC;IAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,kCAAkC,CAAC,EAAE,MAAM,CAAC;QAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KACnC,CAAC;IACF,cAAc,CAAC,EAAE;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,kCAAkC,CAAC,EAAE,MAAM,CAAC;QAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE;QACR,QAAQ,EAAE,OAAO,CAAC;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,SAAS,EAAE,OAAO,CAAC;QACnB,qBAAqB,EAAE,OAAO,CAAC;QAC/B,kCAAkC,EAAE,OAAO,CAAC;QAC5C,kBAAkB,EAAE,OAAO,CAAC;QAC5B,kBAAkB,EAAE,OAAO,CAAC;QAC5B,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,kCAAkC,CAAC,EAAE,MAAM,CAAC;QAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KACnC,CAAC;IACF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAC;KAC9B,CAAC;IACF,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASzD,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAS3D,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASjE,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,aAKnC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,cAsBpC,CAAC;AAGF,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,6BAA6B,EAAE,mBAI3C,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE;IAAE,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAoE3H,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAerF,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,aAAa,CAAC,UAAU,CAAC,GAAG,YAAY,CAalG,CAAC;AAEF,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,UAAU,kFAAkF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jonah-fleet",
3
- "version": "1.23.1",
3
+ "version": "1.25.0",
4
4
  "description": "Standalone autonomous agent fleet with Symphony orchestration, claim protocols, and continuous improvement loops",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -69,6 +69,12 @@ tests/ # Test suites
69
69
 
70
70
  ## Autonomous Agent Dispatch (Targeted Autowork)
71
71
 
72
+ ### 1-Click Assignment Trigger
73
+
74
+ Assigning any issue in GitHub's native sidebar Assignees dropdown to the designated fleet bot account (configured via `vars.AGENT_BOT_LOGIN` or machine user) automatically triggers Autowork in Targeted mode via `trigger-autowork-on-assign.yml`.
75
+
76
+ ### Manual Dispatch & Badge Link
77
+
72
78
  To trigger the Autowork routine manually on any specific issue, use the GitHub Actions `workflow_dispatch` trigger or embed this badge link in issue templates/descriptions:
73
79
 
74
80
  ```markdown
@@ -21,6 +21,7 @@ Dispatch is both **scheduled** and **event-driven**. All routines run as ephemer
21
21
  - `trigger-review-routine.yml` fires Peer Review automatically when a PR is marked ready for review, updated, or review is requested (`ready_for_review`, `opened`, `reopened`, `synchronize`, `review_requested`). It can also be manually (re)triggered via `workflow_dispatch` (with optional `pr_number` for Targeted mode or blank for Scan mode) or by commenting `/review`, `/peer-review`, `/retrigger`, or `/re-review` on any open pull request.
22
22
  - `trigger-autowork-on-merge.yml` fires Autowork in **Targeted mode** when a PR merges to `main` and unblocks the next unit of chained work.
23
23
  - `trigger-autowork-on-bug.yml` fires Autowork when an issue becomes a high-priority bug.
24
+ - `trigger-autowork-on-assign.yml` fires Autowork in **Targeted mode** when an issue is assigned to a designated bot account or persona (`vars.AGENT_BOT_LOGIN`).
24
25
  - `trigger-autowork-manual.yml` fires Autowork manually via `workflow_dispatch` or badge link click on a specific issue in **Targeted mode**.
25
26
 
26
27
  Autowork triggers pass the target issue via environment variables (`TARGET_ISSUE`, `ISSUE_NUMBER`, `ISSUE_URL`), putting autowork.md into **Targeted mode** (working the named issue ahead of Phase 1 convergence). Single-flight per issue is strictly enforced across scheduled, event-driven, and manually triggered runs.
@@ -271,7 +272,7 @@ How closed-loop feedback from product telemetry and measurement trackers drives
271
272
  How agent routines are partitioned between cloud GitHub Actions (24/7 cloud runners for fast time-to-resolution) and local machine agents (`jonah-fleet run` / `jonah-fleet daemon` for zero cloud quota consumption):
272
273
 
273
274
  1. **Priority Routing Rules**:
274
- - **`priority/P0` & `priority/P1` & Bugs**: Processed immediately by cloud GitHub Actions upon event trigger (`issues`, `pull_request`, `schedule`).
275
+ - **`priority/P0` & `priority/P1` & Bugs & Persona Assignment**: Processed immediately by cloud GitHub Actions upon event trigger (`issues`, `pull_request`, `schedule`).
275
276
  - **`priority/P2` & `priority/P3` (Lower Priority)**: Handled primarily by local machine agents in isolated Git worktrees. Cloud Actions skips immediate event triggers on P2/P3 items to conserve Actions quota.
276
277
  - **Cloud Catchup Sweep (48h Fallback)**: If a P2/P3 issue or PR remains unclaimed/unreviewed for $>48\text{ hours}$ (e.g. because local machines were offline), the scheduled cloud Actions scan sweep automatically picks it up to prevent work starvation.
277
278
  2. **PR Priority Mirroring**: When Autowork opens a PR, it automatically mirrors the parent issue's priority labels (`priority/P0`..`P3`) onto the pull request so downstream review workflows can filter triggers without extra API overhead.
@@ -70,17 +70,17 @@ If any criterion cannot be met, stop immediately and log FAILURE with the reason
70
70
 
71
71
  This routine runs in two modes, decided here before any other work:
72
72
 
73
- - **Targeted mode** — an environment variable `$ISSUE_NUMBER` (or explicit issue payload) names a target issue. Work _that_ issue as the run's objective, **ahead of** Phase 1 convergence and the normal priority scan.
73
+ - **Targeted mode** — an environment variable `$TARGET_ISSUE` or `$ISSUE_NUMBER` (or explicit issue payload / persona assignment trigger) names a target issue. Work _that_ issue as the run's objective, **ahead of** Phase 1 convergence and the normal priority scan.
74
74
  - **Scan mode** — no issue is named (a scheduled cron run). Run Phase 1, then select an issue by priority in Phase 2.
75
75
 
76
- Check if `$ISSUE_NUMBER` environment variable is set (or scan invocation text for `#<number>` / `/issues/<number>`):
76
+ Check if `$TARGET_ISSUE` or `$ISSUE_NUMBER` environment variable is set (or scan invocation text for `#<number>` / `/issues/<number>`):
77
77
 
78
78
  - **Found one → Targeted mode.** Record it as this run's target issue and proceed to Step 0.5.
79
79
  - **None found → Scan mode.** Proceed as a scheduled run: Phase 1, then normal priority selection in Phase 2.
80
80
 
81
81
  ### Step 0.5: Targeted mode — work the target issue first (only when Step 0 found one)
82
82
 
83
- a. **Read the target issue and check eligibility.** Eligible = open, unassigned or reclaimable stale claim, no open PR (`Closes #N`), no unclosed inward blocking dependencies (`Blocked by #N` or `Depends on #N` where `#N` is open), and not carrying `needs-human` or `needs-design`.
83
+ a. **Read the target issue and check eligibility.** Eligible = open, unassigned or assigned to designated bot persona (`vars.AGENT_BOT_LOGIN`) or reclaimable stale claim, no open PR (`Closes #N`), no unclosed inward blocking dependencies (`Blocked by #N` or `Depends on #N` where `#N` is open), and not carrying `needs-human` or `needs-design`.
84
84
 
85
85
  - **Ineligible** → fall back to Phase 1 and run the normal Scan flow.
86
86
  b. **Eligible → claim, then implement.** Call `get_me` once to learn your own login (step 7), reclaim stale claim if applicable (step 10a), run Claim protocol (step 11), evaluate and implement per steps 12–13, open draft PR, and run in-session review wait (step 15).
@@ -167,6 +167,7 @@ _Generated by [Antigravity](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/ru
167
167
 
168
168
  6. Count open PRs authored by automated sessions representing live reviewable work (excluding log-only PRs). If 3 or more non-log PRs are open, STOP — run is SUCCESS with "Too many open PRs, converging first".
169
169
  7. Call `get_me` once to learn your own GitHub account (`login`).
170
+ - **Persona & Bot Login Matching**: In environments with designated machine user accounts or persona assignment triggers (`vars.AGENT_BOT_LOGIN`), ensure `get_me` identity matching respects both your authenticated account and the configured bot persona. An issue or PR assigned to the bot persona is treated as self-assigned for claim and ownership checks.
170
171
  8. List open issues sorted by priority labels (P1 > P2 > P3). Within the same priority tier, order by type (`bug`/`security` before others), then oldest first.
171
172
  - **Selective Server-Side Querying**: To prevent tool buffer truncation and avoid ingesting un-actionable issues, query GitHub with server-side exclusion filters rather than dumping all issues. E.g.:
172
173
  `gh issue list --state open --search "no:assignee -label:measurement -label:needs-human -label:needs-design -label:wontfix -label:needs-info" --limit 30`
@@ -190,7 +191,7 @@ _Generated by [Antigravity](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/ru
190
191
  10. If the candidate should be closed already (work done, merged PR found in git history or via `gh pr list --state merged --search "<ISSUE_NUMBER>"`), close it immediately (`gh issue close <ISSUE_NUMBER> --comment "Closed: work already merged in PR #<PR_NUMBER>.\n\n_Generated by [Antigravity](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID:-})_"`), close any lingering past failed routine run issues (`PAST_FAILURES=$(gh issue list --label routine-log --search "Issue #<ISSUE_NUMBER>" --state open --json number --jq '.[].number' || true); for p in $PAST_FAILURES; do if [ -n "$p" ] && [ "$p" != "$ROUTINE_ISSUE_NUMBER" ]; then gh issue comment "$p" --body "Resolved: work already merged in PR #<PR_NUMBER>.\n\n_Generated by [Antigravity](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID:-})_" || true; gh issue close "$p" --reason completed || true; fi; done`), and return to step 8.
191
192
  10a. **Stale-claim reclamation:** If candidate is a stale claim per `ORCHESTRATION.md`, re-read immediately before writing, unassign the dead owner, post reclamation comment, and proceed to claim.
192
193
  11. **Claim protocol:**
193
- a. Re-read candidate issue immediately before claiming (`issue_read`). If assigned, abort and pick next candidate.
194
+ a. Re-read candidate issue immediately before claiming (`issue_read`). If assigned to a user other than yourself or the configured bot persona (`vars.AGENT_BOT_LOGIN`), abort and pick next candidate.
194
195
  b. Claim atomically: assign yourself (`login` from step 7) AND post claim comment:
195
196
  - In **Cloud Actions**: `🔒 Claimed by autowork run {run_url} {timestamp}`
196
197
  - In **Local Agent**: `🔒 Claimed by local autowork session (host: {hostname}) {timestamp}`
@@ -98,6 +98,7 @@ export class LoopGuard {
98
98
  toolName,
99
99
  actionHash: hash,
100
100
  count: this.consecutiveErrorCount,
101
+ args,
101
102
  });
102
103
  }
103
104
  } else {
@@ -126,6 +127,7 @@ export class LoopGuard {
126
127
  toolName,
127
128
  actionHash: hash,
128
129
  count: repetitionCount,
130
+ args,
129
131
  });
130
132
  }
131
133
  }
@@ -167,6 +169,7 @@ export class LoopGuard {
167
169
  toolName,
168
170
  actionHash: hash,
169
171
  count: this.pingPongThreshold,
172
+ args,
170
173
  });
171
174
  }
172
175
  }
@@ -209,6 +212,22 @@ export class LoopGuard {
209
212
  }
210
213
  }
211
214
 
215
+ /**
216
+ * Formats a concise, human-readable summary of a tool action and its parameters.
217
+ */
218
+ export function formatActionSummary(toolName, args) {
219
+ if (!args) return toolName;
220
+ if (typeof args === 'string') return `${toolName}: ${args}`;
221
+ if (args.CommandLine) return `${toolName}: ${args.CommandLine}`;
222
+ if (args.command) return `${toolName}: ${args.command}`;
223
+ if (args.TargetFile) return `${toolName}: ${args.TargetFile}`;
224
+ if (args.path) return `${toolName}: ${args.path}`;
225
+ if (args.AbsolutePath) return `${toolName}: ${args.AbsolutePath}`;
226
+ if (args.Query) return `${toolName}: ${args.Query}`;
227
+ const str = canonicalStringify(args);
228
+ return str.length > 200 ? `${toolName}: ${str.slice(0, 197)}...` : `${toolName}: ${str}`;
229
+ }
230
+
212
231
  export function formatLoopGuardFailureCard(options) {
213
232
  const serverUrl = options.serverUrl || process.env.GITHUB_SERVER_URL || 'https://github.com';
214
233
  const repository = options.repository || process.env.GITHUB_REPOSITORY || '';
@@ -222,9 +241,14 @@ export function formatLoopGuardFailureCard(options) {
222
241
  `- **Root Cause Category**: \`loop_circuit_breaker\``,
223
242
  `- **Trigger**: \`${options.trip.reason}\``,
224
243
  `- **Reason**: ${options.trip.message}`,
225
- `- **Action**: Process terminated to prevent runaway token burn`,
226
244
  ];
227
245
 
246
+ if (options.trip.args !== undefined) {
247
+ lines.push(`- **Triggered Action**: \`${formatActionSummary(options.trip.toolName, options.trip.args)}\``);
248
+ }
249
+
250
+ lines.push(`- **Action**: Process terminated to prevent runaway token burn`);
251
+
228
252
  if (logUrl) {
229
253
  lines.push(`- **Action Log**: [View Run Logs](${logUrl})`);
230
254
  }
@@ -233,7 +257,7 @@ export function formatLoopGuardFailureCard(options) {
233
257
  }
234
258
 
235
259
  export function formatLoopGuardReport(options) {
236
- return [
260
+ const reportLines = [
237
261
  `# Run Report`,
238
262
  ``,
239
263
  `## Result`,
@@ -255,9 +279,18 @@ export function formatLoopGuardReport(options) {
255
279
  `- **Category**: \`loop_circuit_breaker\``,
256
280
  `- **Trigger**: \`${options.trip.reason}\``,
257
281
  `- **Tool**: \`${options.trip.toolName}\``,
282
+ ];
283
+
284
+ if (options.trip.args !== undefined) {
285
+ reportLines.push(`- **Parameters**: \`${formatActionSummary(options.trip.toolName, options.trip.args)}\``);
286
+ }
287
+
288
+ reportLines.push(
258
289
  `- **Action Hash**: \`${options.trip.actionHash}\``,
259
290
  `- **Message**: ${options.trip.message}`,
260
- ].join('\n');
291
+ );
292
+
293
+ return reportLines.join('\n');
261
294
  }
262
295
 
263
296
  class LineParser {
@@ -332,6 +365,9 @@ async function main() {
332
365
  onTrip: (trip) => {
333
366
  tripped = trip;
334
367
  console.error(`\n🚨 ::error::[LoopGuard] ${trip.message}`);
368
+ if (trip.args) {
369
+ console.error(`🚨 Action Details: ${formatActionSummary(trip.toolName, trip.args)}`);
370
+ }
335
371
 
336
372
  if (childProcess && !childProcess.killed) {
337
373
  console.error(`🛑 Terminating runner process with SIGTERM...`);
@@ -364,12 +400,14 @@ async function main() {
364
400
  }
365
401
  } else if (su.step_type === 'tool') {
366
402
  const name = su.tool_name || su.tool_info?.name || 'tool';
403
+ const params = su.tool_info?.parameters;
404
+ const summary = formatActionSummary(name, params);
367
405
  if (su.state === 'ACTIVE') {
368
- console.log(`\n[tool:start] ${name}`);
406
+ console.log(`\n[tool:start] ${summary}`);
369
407
  } else if (su.state === 'DONE') {
370
- console.log(`[tool:done] ${name}`);
408
+ console.log(`[tool:done] ${summary}`);
371
409
  } else if (su.state === 'ERROR') {
372
- console.log(`[tool:error] ${name}`);
410
+ console.log(`[tool:error] ${summary}`);
373
411
  }
374
412
  }
375
413
  } else if (parsed.event === 'result' && parsed.result?.response) {
@@ -82,6 +82,21 @@ jobs:
82
82
  fi
83
83
  echo "✓ Preflight credential validation passed."
84
84
 
85
+ - name: Configure MCP servers for Antigravity CLI
86
+ env:
87
+ POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
88
+ VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
89
+ run: |
90
+ if [ -n "$POSTHOG_API_KEY" ]; then
91
+ echo "Configuring PostHog MCP server..."
92
+ agy mcp add --header "Authorization: Bearer $POSTHOG_API_KEY" posthog https://mcp.posthog.com/mcp || true
93
+ fi
94
+ if [ -n "$VERCEL_TOKEN" ]; then
95
+ echo "Configuring Vercel MCP server..."
96
+ agy mcp add --header "Authorization: Bearer $VERCEL_TOKEN" vercel https://mcp.vercel.com || true
97
+ fi
98
+ agy mcp list || true
99
+
85
100
  - name: Discover and compile domain skills (SwarmClaw Pattern #4)
86
101
  id: skills
87
102
  run: |
@@ -89,6 +89,16 @@ jobs:
89
89
  fi
90
90
  echo "✓ Preflight credential validation passed."
91
91
 
92
+ - name: Configure MCP servers for Antigravity CLI
93
+ env:
94
+ VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
95
+ run: |
96
+ if [ -n "$VERCEL_TOKEN" ]; then
97
+ echo "Configuring Vercel MCP server..."
98
+ agy mcp add --header "Authorization: Bearer $VERCEL_TOKEN" vercel https://mcp.vercel.com || true
99
+ fi
100
+ agy mcp list || true
101
+
92
102
  - name: Discover and compile domain skills (SwarmClaw Pattern #4)
93
103
  id: skills
94
104
  run: |
@@ -129,7 +139,6 @@ jobs:
129
139
  ROUTINE: design-review
130
140
  ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
131
141
  VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
132
- POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
133
142
  TARGET_SURFACE: ${{ inputs.target_surface }}
134
143
  SKILLS_PROMPT: ${{ steps.skills.outputs.skills_prompt }}
135
144
  GITHUB_SERVER_URL: ${{ github.server_url }}
@@ -0,0 +1,327 @@
1
+ name: Trigger Autowork on Assignment
2
+
3
+ on:
4
+ issues:
5
+ types: [assigned]
6
+
7
+ jobs:
8
+ fire-autowork:
9
+ if: github.event.assignee.login == vars.AGENT_BOT_LOGIN || github.event.assignee.login == 'jonah-fleet-bot'
10
+ concurrency:
11
+ group: autowork-assign-${{ github.event.issue.number }}
12
+ cancel-in-progress: true
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 70
15
+ permissions:
16
+ contents: write
17
+ issues: write
18
+ pull-requests: write
19
+ statuses: write
20
+ actions: read
21
+ steps:
22
+ - name: Checkout repository
23
+ uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+ token: ${{ secrets.GH_PAT || github.token }}
27
+ persist-credentials: false
28
+
29
+ - name: Setup Node.js
30
+ uses: actions/setup-node@v4
31
+ with:
32
+ node-version: 22
33
+
34
+ - name: Configure Git author identity
35
+ env:
36
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
37
+ run: |
38
+ git config --global user.name "github-actions[bot]"
39
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
40
+ git config --global --add safe.directory "$GITHUB_WORKSPACE"
41
+ gh auth setup-git
42
+
43
+ - name: Cache Antigravity CLI
44
+ id: cache-agy
45
+ uses: actions/cache@v4
46
+ with:
47
+ path: ~/.local/bin/agy
48
+ key: agy-cli-linux-amd64-v1
49
+
50
+ - name: Install Antigravity CLI
51
+ if: steps.cache-agy.outputs.cache-hit != 'true'
52
+ run: |
53
+ curl -fsSL https://antigravity.google/cli/install.sh | bash
54
+
55
+ - name: Add Antigravity CLI to PATH
56
+ run: echo "$HOME/.local/bin" >> $GITHUB_PATH
57
+
58
+ - name: Write Antigravity OAuth Token
59
+ env:
60
+ ANTIGRAVITY_OAUTH_TOKEN: ${{ secrets.ANTIGRAVITY_OAUTH_TOKEN || secrets.GEMINI_API_KEY }}
61
+ run: |
62
+ if [ -z "$ANTIGRAVITY_OAUTH_TOKEN" ]; then
63
+ echo "::error::Neither ANTIGRAVITY_OAUTH_TOKEN nor GEMINI_API_KEY secret is set; cannot authenticate Antigravity CLI." >&2
64
+ exit 1
65
+ fi
66
+ mkdir -p "$HOME/.gemini/antigravity-cli"
67
+ chmod 700 "$HOME/.gemini/antigravity-cli"
68
+ printf '%s' "$ANTIGRAVITY_OAUTH_TOKEN" > "$HOME/.gemini/antigravity-cli/antigravity-oauth-token"
69
+ chmod 600 "$HOME/.gemini/antigravity-cli/antigravity-oauth-token"
70
+
71
+ - name: Discover domain skills
72
+ id: skills
73
+ run: |
74
+ SKILLS_PROMPT=""
75
+ if [ -d ".agents/skills" ]; then
76
+ for skill_path in .agents/skills/*/SKILL.md; do
77
+ if [ -f "$skill_path" ]; then
78
+ SKILLS_PROMPT="${SKILLS_PROMPT}Read and follow ${skill_path}. "
79
+ fi
80
+ done
81
+ fi
82
+ echo "skills_prompt=$SKILLS_PROMPT" >> "$GITHUB_OUTPUT"
83
+
84
+ - name: Resolve routine configuration
85
+ id: routine-config
86
+ run: |
87
+ ROUTINE="autowork"
88
+ DEFAULT_MODEL="gemini-3.8-flash-high"
89
+ DEFAULT_TIMEOUT="60"
90
+
91
+ MODEL="$DEFAULT_MODEL"
92
+ TIMEOUT="$DEFAULT_TIMEOUT"
93
+
94
+ if [ -f "agents-manifest.json" ]; then
95
+ CONFIG_JSON=$(node -e '
96
+ try {
97
+ const fs = require("fs");
98
+ const m = JSON.parse(fs.readFileSync("agents-manifest.json", "utf8"));
99
+ const r = process.argv[1];
100
+ const model = m.models?.[r] || m.models?.default;
101
+ const timeout = m.budgets?.timeoutMinutes?.[r] || m.budgets?.timeoutMinutes?.default;
102
+ console.log(JSON.stringify({ model: model || "", timeout: timeout ? String(timeout) : "" }));
103
+ } catch (e) {
104
+ console.log(JSON.stringify({ model: "", timeout: "" }));
105
+ }
106
+ ' "$ROUTINE")
107
+
108
+ RESOLVED_MODEL=$(node -e "try { console.log(JSON.parse(process.argv[1]).model || ''); } catch {}" "$CONFIG_JSON")
109
+ RESOLVED_TIMEOUT=$(node -e "try { console.log(JSON.parse(process.argv[1]).timeout || ''); } catch {}" "$CONFIG_JSON")
110
+
111
+ if [ -n "$RESOLVED_MODEL" ]; then
112
+ MODEL="$RESOLVED_MODEL"
113
+ fi
114
+ if [ -n "$RESOLVED_TIMEOUT" ]; then
115
+ TIMEOUT="$RESOLVED_TIMEOUT"
116
+ fi
117
+ fi
118
+
119
+ echo "model=$MODEL" >> "$GITHUB_OUTPUT"
120
+ echo "print_timeout=${TIMEOUT}m" >> "$GITHUB_OUTPUT"
121
+ echo "Resolved routine configuration: model=$MODEL, timeout=${TIMEOUT}m"
122
+
123
+ - name: Initialize Routine Run Issue
124
+ id: run-issue
125
+ env:
126
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
127
+ ISSUE_NUM: ${{ github.event.issue.number }}
128
+ EVENT_NAME: ${{ github.event_name }}
129
+ RUN_ID: ${{ github.run_id }}
130
+ SERVER_URL: ${{ github.server_url }}
131
+ REPOSITORY: ${{ github.repository }}
132
+ run: |
133
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
134
+ TITLE="[autowork] run ${TIMESTAMP} (Issue #${ISSUE_NUM})"
135
+ BODY="### Autonomous Routine Execution in Progress
136
+ - **Routine**: \`autowork\`
137
+ - **Timestamp**: \`${TIMESTAMP}\`
138
+ - **Trigger**: \`${EVENT_NAME}\` (Issue assignment to @${{ github.event.assignee.login }})
139
+ - **Target**: Issue #${ISSUE_NUM}
140
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
141
+
142
+ ---
143
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
144
+ ISSUE_URL=$(gh issue create --title "$TITLE" --body "$BODY" --label "routine-log,routine:autowork,status:running,runner:github-actions")
145
+ ISSUE_NUMBER=$(echo "$ISSUE_URL" | grep -oE '[0-9]+$')
146
+ echo "issue_number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT"
147
+ echo "ROUTINE_ISSUE_NUMBER=$ISSUE_NUMBER" >> "$GITHUB_ENV"
148
+
149
+ - name: Run Autowork
150
+ timeout-minutes: 60
151
+ env:
152
+ GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
153
+ GOOGLE_API_KEY: ${{ secrets.GEMINI_API_KEY }}
154
+ ANTIGRAVITY_API_KEY: ${{ secrets.GEMINI_API_KEY }}
155
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
156
+ ROUTINE: autowork
157
+ TARGET_ISSUE: ${{ github.event.issue.number }}
158
+ ROUTINE_ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
159
+ SKILLS_PROMPT: ${{ steps.skills.outputs.skills_prompt }}
160
+ MODEL: ${{ steps.routine-config.outputs.model || 'gemini-3.8-flash-high' }}
161
+ PRINT_TIMEOUT: ${{ steps.routine-config.outputs.print_timeout || '60m' }}
162
+ GITHUB_SERVER_URL: ${{ github.server_url }}
163
+ GITHUB_REPOSITORY: ${{ github.repository }}
164
+ GITHUB_RUN_ID: ${{ github.run_id }}
165
+ run: |
166
+ PROMPT="You are the Autowork routine for this repository. An issue was assigned to this agent persona. 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."
167
+
168
+ set +e
169
+ node .github/scripts/run-with-loop-guard.js \
170
+ -p "$PROMPT" \
171
+ --model "$MODEL" \
172
+ --output-format text \
173
+ --print-timeout "$PRINT_TIMEOUT" \
174
+ --dangerously-skip-permissions 2>&1 | tee /tmp/agy.log
175
+ AGY_EXIT_CODE="${PIPESTATUS[0]}"
176
+ set -e
177
+
178
+ if [ "$AGY_EXIT_CODE" -ne 0 ]; then
179
+ if grep -qiE "Individual quota reached|quota reached" /tmp/agy.log; then
180
+ RESET_INFO=$(grep -oE "Resets in [^.]+" /tmp/agy.log | head -n 1 || echo "Resets in future window")
181
+ echo "QUOTA_PAUSED=true" >> "$GITHUB_ENV"
182
+ echo "QUOTA_RESET_INFO=$RESET_INFO" >> "$GITHUB_ENV"
183
+ echo "⚠️ LLM quota limit reached ($RESET_INFO). Pausing routine gracefully until next sweep."
184
+ exit 0
185
+ fi
186
+ exit "$AGY_EXIT_CODE"
187
+ fi
188
+
189
+ - name: Emit run summary
190
+ if: always()
191
+ run: |
192
+ if [ "$QUOTA_PAUSED" = "true" ]; then
193
+ echo "### ⏸️ Milestone: Routine Execution Quota-Paused" >> "$GITHUB_STEP_SUMMARY"
194
+ echo "- **Status**: LLM quota reached (\`${QUOTA_RESET_INFO}\`)" >> "$GITHUB_STEP_SUMMARY"
195
+ echo "- **Next Action**: Routine execution paused cleanly. Work will resume automatically on the next scheduled sweep after the quota window resets." >> "$GITHUB_STEP_SUMMARY"
196
+ else
197
+ REPORT_FILE=".jonah-fleet/run-report.md"
198
+ if [ -f "$REPORT_FILE" ] && [ -n "$GITHUB_STEP_SUMMARY" ]; then
199
+ cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
200
+ fi
201
+ fi
202
+
203
+ - name: Emit Fleet Telemetry (Opt-in)
204
+ if: always()
205
+ env:
206
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
207
+ TELEMETRY_ENDPOINT: ${{ secrets.JONAH_FLEET_TELEMETRY_ENDPOINT }}
208
+ GITHUB_REPOSITORY: ${{ github.repository }}
209
+ GITHUB_RUN_ID: ${{ github.run_id }}
210
+ GITHUB_RUN_NUMBER: ${{ github.run_number }}
211
+ run: |
212
+ REPORT_FILE=".jonah-fleet/run-report.md"
213
+ if [ -f "$REPORT_FILE" ]; then
214
+ npx --yes jonah-fleet telemetry --emit --log "$REPORT_FILE" --endpoint "$TELEMETRY_ENDPOINT" || true
215
+ fi
216
+
217
+ - name: Verify Atomic Handoff Invariant (PR Existence Guard)
218
+ if: always()
219
+ env:
220
+ GH_TOKEN: ${{ github.token }}
221
+ run: |
222
+ REPORT_FILE=".jonah-fleet/run-report.md"
223
+ if [ -f "$REPORT_FILE" ]; then
224
+ if grep -q "Result.*SUCCESS" "$REPORT_FILE"; then
225
+ WORKED_BRANCH=$(grep -E '^\s*-\s*(Pushed branch|Branch):' "$REPORT_FILE" | head -n 1 | sed -E 's/.*`([^`]+)`.*/\1/')
226
+ if [ -n "$WORKED_BRANCH" ] && [[ "$WORKED_BRANCH" =~ (feat|fix)/ ]]; then
227
+ echo "Verifying PR existence for branch: $WORKED_BRANCH"
228
+ PR_COUNT=$(gh pr list --head "$WORKED_BRANCH" --state all --json number --jq 'length' 2>/dev/null || echo "0")
229
+ if [ "$PR_COUNT" -eq 0 ]; then
230
+ echo "::error::Atomic Handoff Invariant Violated: Branch '$WORKED_BRANCH' was implemented and pushed, but no pull request exists on GitHub!" >&2
231
+ exit 1
232
+ fi
233
+ echo "✓ Verified pull request exists on GitHub for branch: $WORKED_BRANCH"
234
+ fi
235
+ fi
236
+ fi
237
+
238
+ - name: Reconcile Routine Run Issue
239
+ if: always()
240
+ env:
241
+ GH_TOKEN: ${{ secrets.GH_PAT || github.token }}
242
+ ISSUE_NUMBER: ${{ steps.run-issue.outputs.issue_number }}
243
+ JOB_STATUS: ${{ job.status }}
244
+ EVENT_NAME: ${{ github.event_name }}
245
+ RUN_ID: ${{ github.run_id }}
246
+ SERVER_URL: ${{ github.server_url }}
247
+ REPOSITORY: ${{ github.repository }}
248
+ QUOTA_PAUSED: ${{ env.QUOTA_PAUSED }}
249
+ QUOTA_RESET_INFO: ${{ env.QUOTA_RESET_INFO }}
250
+ run: |
251
+ if [ -z "$ISSUE_NUMBER" ]; then
252
+ echo "No routine issue to reconcile."
253
+ exit 0
254
+ fi
255
+
256
+ if [ "$QUOTA_PAUSED" = "true" ]; then
257
+ RESET_STR="${QUOTA_RESET_INFO:-Resets in upcoming window}"
258
+ PAUSE_BODY="### ⏸️ Autonomous Routine Execution Quota-Paused
259
+ - **Routine**: \`autowork\`
260
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
261
+ - **Trigger**: \`${EVENT_NAME}\`
262
+ - **Status**: LLM quota reached (\`${RESET_STR}\`)
263
+ - **Next Action**: Routine execution paused cleanly. Work will resume automatically on the next scheduled sweep after the quota window resets.
264
+
265
+ ---
266
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
267
+
268
+ TEMP_BODY=$(mktemp)
269
+ echo "$PAUSE_BODY" > "$TEMP_BODY"
270
+ gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
271
+ rm -f "$TEMP_BODY"
272
+
273
+ PAUSE_COMMENT=$(printf '%s\n' \
274
+ "### ⏸️ Milestone: Routine Execution Quota-Paused" \
275
+ "- **Routine**: \`autowork\`" \
276
+ "- **Status**: LLM quota reached (\`${RESET_STR}\`)" \
277
+ "- **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})" \
278
+ "- **Next Action**: Execution paused cleanly. The routine will resume automatically on the next scheduled sweep." \
279
+ "" \
280
+ "---" \
281
+ "_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_")
282
+ gh issue comment "$ISSUE_NUMBER" --body "$PAUSE_COMMENT" || true
283
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:quota-paused" --remove-label "status:running"
284
+ gh issue close "$ISSUE_NUMBER" --reason completed
285
+ echo "⏸️ Routine run issue #$ISSUE_NUMBER closed with status:quota-paused."
286
+ exit 0
287
+ fi
288
+
289
+ REPORT_FILE=".jonah-fleet/run-report.md"
290
+
291
+ if [ -f "$REPORT_FILE" ]; then
292
+ BODY_CONTENT=$(cat "$REPORT_FILE")
293
+ else
294
+ BODY_CONTENT="### Autonomous Routine Execution Completed (${JOB_STATUS})
295
+ - **Routine**: \`autowork\`
296
+ - **Run ID**: [\`${RUN_ID}\`](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})
297
+ - **Trigger**: \`${EVENT_NAME}\`"
298
+ fi
299
+
300
+ FINAL_BODY="${BODY_CONTENT}
301
+
302
+ ---
303
+ _Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_"
304
+
305
+ TEMP_BODY=$(mktemp)
306
+ echo "$FINAL_BODY" > "$TEMP_BODY"
307
+ gh issue edit "$ISSUE_NUMBER" --body-file "$TEMP_BODY"
308
+ rm -f "$TEMP_BODY"
309
+
310
+ if [ "$JOB_STATUS" = "success" ]; then
311
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:success" --remove-label "status:running"
312
+ gh issue close "$ISSUE_NUMBER" --reason completed
313
+ echo "✓ Routine run issue #$ISSUE_NUMBER closed as completed."
314
+ else
315
+ INTERRUPTION_BODY=$(printf '%s\n' \
316
+ "### ❌ Milestone: Run Interrupted / Failed" \
317
+ "- **Routine**: \`autowork\`" \
318
+ "- **Status**: Workflow job failed or timed out (\`${JOB_STATUS}\`)" \
319
+ "- **Step**: Actions execution halted before normal completion" \
320
+ "- **Action Log**: [View GitHub Actions Run](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})" \
321
+ "" \
322
+ "---" \
323
+ "_Generated by [Antigravity](${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID})_")
324
+ gh issue comment "$ISSUE_NUMBER" --body "$INTERRUPTION_BODY" || true
325
+ gh issue edit "$ISSUE_NUMBER" --add-label "status:failure,needs-attention" --remove-label "status:running"
326
+ echo "⚠️ Routine run issue #$ISSUE_NUMBER left open for triage (status: $JOB_STATUS)."
327
+ fi