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 +25 -0
- package/dist/index.js +35 -9
- package/dist/lib/loop-guard.d.ts +5 -0
- package/dist/lib/loop-guard.d.ts.map +1 -1
- package/dist/lib/presets.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/docs/AGENTS.template.md +6 -0
- package/templates/prompts/ORCHESTRATION.md +2 -1
- package/templates/prompts/autowork.md +5 -4
- package/templates/scripts/run-with-loop-guard.js +44 -6
- package/templates/workflows/analytics-review-cron.yml +15 -0
- package/templates/workflows/design-review-cron.yml +10 -1
- package/templates/workflows/trigger-autowork-on-assign.yml +327 -0
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
|
-
|
|
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
|
-
|
|
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
|
};
|
package/dist/lib/loop-guard.d.ts
CHANGED
|
@@ -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;
|
|
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
|
@@ -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
|
-
|
|
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
|
-
|
|
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] ${
|
|
406
|
+
console.log(`\n[tool:start] ${summary}`);
|
|
369
407
|
} else if (su.state === 'DONE') {
|
|
370
|
-
console.log(`[tool:done] ${
|
|
408
|
+
console.log(`[tool:done] ${summary}`);
|
|
371
409
|
} else if (su.state === 'ERROR') {
|
|
372
|
-
console.log(`[tool:error] ${
|
|
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
|