jonah-fleet 1.31.2 → 1.31.3
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,13 @@ 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.31.3](https://github.com/Jonah-Projects/jonah-fleet/compare/v1.31.2...v1.31.3) (2026-10-02)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **loop-guard,prompts:** exempt read-only status polling from loop guard and streamline local autowork handoff ([#580](https://github.com/Jonah-Projects/jonah-fleet/issues/580)) ([ff38bdb](https://github.com/Jonah-Projects/jonah-fleet/commit/ff38bdb6bc3ffccde890df958a2feda0db1effd6))
|
|
14
|
+
|
|
8
15
|
## [1.31.2](https://github.com/Jonah-Projects/jonah-fleet/compare/v1.31.1...v1.31.2) (2026-10-02)
|
|
9
16
|
|
|
10
17
|
|
|
@@ -18,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
25
|
|
|
19
26
|
* **runner:** introduce `detectTransientServiceError` and add startup retry loop (up to 2 retries with backoff) when `agy` encounters transient 503 UNAVAILABLE or handshake EOF during initialization
|
|
20
27
|
* **daemon:** exempt transient service errors (503 UNAVAILABLE) from PR failure cooldowns to avoid penalizing PR review schedules on momentary upstream cloud blips
|
|
28
|
+
* **loop-guard:** exempt read-only CLI status polling commands (`gh run view`, `gh run watch`, `gh pr view`, `gh pr checks`, `git status`) from repetition and ping-pong loop circuit breakers
|
|
29
|
+
* **prompts:** clarify fast autonomous handoff in autowork Step 15 for local daemon runs so completed PRs hand off cleanly to peer-review without 12-minute polling wait
|
|
21
30
|
|
|
22
31
|
## [1.31.1](https://github.com/Jonah-Projects/jonah-fleet/compare/v1.31.0...v1.31.1) (2026-10-01)
|
|
23
32
|
|
package/dist/index.js
CHANGED
|
@@ -3992,6 +3992,20 @@ function computeActionHash(toolName, args) {
|
|
|
3992
3992
|
const canonicalArgs = canonicalStringify(args);
|
|
3993
3993
|
return crypto.createHash("sha256").update(`${toolName}:${canonicalArgs}`).digest("hex");
|
|
3994
3994
|
}
|
|
3995
|
+
function isStatusPollingAction(toolName, args) {
|
|
3996
|
+
if (toolName === "manage_task" && (args?.Action === "status" || args?.action === "status" || args?.Action === "list" || args?.action === "list")) {
|
|
3997
|
+
return true;
|
|
3998
|
+
}
|
|
3999
|
+
if (toolName === "manage_subagents" && (args?.Action === "list" || args?.action === "list")) {
|
|
4000
|
+
return true;
|
|
4001
|
+
}
|
|
4002
|
+
if (toolName === "run_command" && typeof (args?.CommandLine || args?.command) === "string" && /^\s*(?:gh\s+(?:run\s+(?:view|watch|list)|pr\s+(?:view|checks|status|list))|git\s+(?:status|log))\b/i.test(
|
|
4003
|
+
args?.CommandLine || args?.command || ""
|
|
4004
|
+
)) {
|
|
4005
|
+
return true;
|
|
4006
|
+
}
|
|
4007
|
+
return false;
|
|
4008
|
+
}
|
|
3995
4009
|
var LoopGuard = class {
|
|
3996
4010
|
routine;
|
|
3997
4011
|
repetitionThreshold;
|
|
@@ -4036,7 +4050,7 @@ var LoopGuard = class {
|
|
|
4036
4050
|
if (this.trippedResult) {
|
|
4037
4051
|
return this.trippedResult;
|
|
4038
4052
|
}
|
|
4039
|
-
const isStatusPolling =
|
|
4053
|
+
const isStatusPolling = isStatusPollingAction(toolName, args);
|
|
4040
4054
|
const isAnalyticsRoutine = this.routine === "analytics-review";
|
|
4041
4055
|
const isExemptFromRepetition = isStatusPolling || isAnalyticsRoutine || toolName === "view_file" || toolName === "read_file" || toolName === "replace_file_content" || toolName === "write_to_file";
|
|
4042
4056
|
const hash = computeActionHash(toolName, args);
|
|
@@ -4093,7 +4107,7 @@ var LoopGuard = class {
|
|
|
4093
4107
|
if (this.history.length >= requiredPingPongLength) {
|
|
4094
4108
|
const pingPongSlice = this.history.slice(-requiredPingPongLength);
|
|
4095
4109
|
const hasExemptPingPongAction = isAnalyticsRoutine || pingPongSlice.some(
|
|
4096
|
-
(item) =>
|
|
4110
|
+
(item) => isStatusPollingAction(item.toolName, item.args) || item.toolName === "replace_file_content" || item.toolName === "write_to_file"
|
|
4097
4111
|
);
|
|
4098
4112
|
if (!hasExemptPingPongAction) {
|
|
4099
4113
|
const hashA = pingPongSlice[0].hash;
|
|
@@ -4345,7 +4359,7 @@ function buildRoutinePrompt(targetDir, routine, options = {}) {
|
|
|
4345
4359
|
const promptFile = `.github/prompts/${routine}.md`;
|
|
4346
4360
|
const repoContext = `Working repository is located at ${targetDir}. All git, gh, and workspace commands must execute strictly within this repository.`;
|
|
4347
4361
|
const logPrompt = options.routineIssueNumber ? ` Tracking run log issue: #${options.routineIssueNumber}.` : "";
|
|
4348
|
-
const headlessGuardrail = ` Execution Guardrail: You are executing in a headless autonomous session. You MUST NEVER call schedule or yield your turn with plain text to wait on background tasks or verification checks. If a verification command (tests, type-check, lint) runs in the background, inspect its completion with manage_task(Action='status') or manage_subagents(Action='list') (status polling with these tools is explicitly exempted from loop guard circuit breakers), or execute commands with sufficient WaitMsBeforeAsync (up to 10000 ms). DO NOT busy-wait by repeatedly calling read tools (such as view_file) on unchanged files to pass time while waiting, as calling non-polling tools with identical parameters will trip the loop circuit breaker. Never stop calling tools or yield your turn until the routine's terminal Definition of Done is fully reached.`;
|
|
4362
|
+
const headlessGuardrail = ` Execution Guardrail: You are executing in a headless autonomous session. You MUST NEVER call schedule or yield your turn with plain text to wait on background tasks or verification checks. If a verification command (tests, type-check, lint) runs in the background, inspect its completion with manage_task(Action='status') or manage_subagents(Action='list') (status polling with these tools is explicitly exempted from loop guard circuit breakers), or execute commands with sufficient WaitMsBeforeAsync (up to 10000 ms). DO NOT busy-wait by repeatedly calling read tools (such as view_file) on unchanged files to pass time while waiting, as calling non-polling tools with identical parameters will trip the loop circuit breaker. Read-only status commands (gh run view, gh pr view, gh pr checks, git status) are also exempted from loop guard repetition limits. Never stop calling tools or yield your turn until the routine's terminal Definition of Done is fully reached.`;
|
|
4349
4363
|
if (routine === "autowork") {
|
|
4350
4364
|
if (options.issue) {
|
|
4351
4365
|
return `You are the Autowork routine for this repository. ${repoContext} Read and follow the instructions in ${promptFile} exactly. ${skillsPrompt}Your target is issue #${options.issue}. You are in Targeted mode: work issue #${options.issue} directly, ahead of Phase 1 convergence and priority scan.${logPrompt}${headlessGuardrail}`;
|
|
@@ -7310,5 +7324,6 @@ export {
|
|
|
7310
7324
|
formatLoopGuardReport,
|
|
7311
7325
|
getFleetFooter,
|
|
7312
7326
|
getFleetRunBadge,
|
|
7327
|
+
isStatusPollingAction,
|
|
7313
7328
|
renderFleetBanner
|
|
7314
7329
|
};
|
package/dist/lib/loop-guard.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export declare function canonicalStringify(value: any): string;
|
|
|
30
30
|
* Computes a deterministic SHA-256 action hash: SHA-256(tool_name + canonicalString(args))
|
|
31
31
|
*/
|
|
32
32
|
export declare function computeActionHash(toolName: string, args: any): string;
|
|
33
|
+
/**
|
|
34
|
+
* Checks whether an action is a read-only status or task polling action exempt from repetition / ping-pong loops.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isStatusPollingAction(toolName: string, args: any): boolean;
|
|
33
37
|
/**
|
|
34
38
|
* Deterministic Loop Guard & Circuit Breaker monitoring tool calls and execution events.
|
|
35
39
|
*/
|
|
@@ -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;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,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,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,OAAO,CAAC,CAAS;IACzB,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,EAOzC;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,
|
|
1
|
+
{"version":3,"file":"loop-guard.d.ts","sourceRoot":"","sources":["../../src/lib/loop-guard.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -306,7 +306,8 @@ _Generated by [Antigravity](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/ru
|
|
|
306
306
|
```
|
|
307
307
|
14. If run aborts before opening PR, release claim (unassign).
|
|
308
308
|
15. **In-Session Peer Review Wait & Immediate Convergence (Warm Context):**
|
|
309
|
-
-
|
|
309
|
+
- **Local Daemon Environment**: If running locally under `jonah-fleet daemon` or with local runner (`runner:local`): Do NOT busy-wait or poll PR status. Autonomous handoff is complete. Proceed immediately to Step 16 / Logging, unassign yourself from the PR (`gh pr edit <PR> --remove-assignee <login>`), record terminal SUCCESS, and exit cleanly so the daemon's Peer Review Watchdog can review the PR without delay.
|
|
310
|
+
- **Cloud CI Environment**: Poll PR status for up to 10–12 minutes using read-only status checks (`gh pr view`, `gh pr checks`, `gh run view`).
|
|
310
311
|
- If merged: unassign yourself, resolve and close any open past failed routine run issues for `#<TARGET_ISSUE>`, record terminal SUCCESS and exit cleanly:
|
|
311
312
|
```bash
|
|
312
313
|
PAST_FAILURES=$(gh issue list --label routine-log --search "Issue #<TARGET_ISSUE>" --state open --json number --jq '.[].number' || true)
|
|
@@ -38,6 +38,37 @@ export function computeActionHash(toolName, args) {
|
|
|
38
38
|
return crypto.createHash('sha256').update(`${toolName}:${canonicalArgs}`).digest('hex');
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export function isStatusPollingAction(toolName, args) {
|
|
42
|
+
if (
|
|
43
|
+
toolName === 'manage_task' &&
|
|
44
|
+
(args?.Action === 'status' ||
|
|
45
|
+
args?.action === 'status' ||
|
|
46
|
+
args?.Action === 'list' ||
|
|
47
|
+
args?.action === 'list')
|
|
48
|
+
) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (
|
|
53
|
+
toolName === 'manage_subagents' &&
|
|
54
|
+
(args?.Action === 'list' || args?.action === 'list')
|
|
55
|
+
) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
toolName === 'run_command' &&
|
|
61
|
+
typeof (args?.CommandLine || args?.command) === 'string' &&
|
|
62
|
+
/^\s*(?:gh\s+(?:run\s+(?:view|watch|list)|pr\s+(?:view|checks|status|list))|git\s+(?:status|log))\b/i.test(
|
|
63
|
+
args?.CommandLine || args?.command || ''
|
|
64
|
+
)
|
|
65
|
+
) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
41
72
|
export class LoopGuard {
|
|
42
73
|
constructor(options = {}) {
|
|
43
74
|
this.routine = options.routine;
|
|
@@ -64,15 +95,7 @@ export class LoopGuard {
|
|
|
64
95
|
recordAction(toolName, args, isError = false) {
|
|
65
96
|
if (this.trippedResult) return this.trippedResult;
|
|
66
97
|
|
|
67
|
-
const isStatusPolling =
|
|
68
|
-
(toolName === 'manage_task' &&
|
|
69
|
-
(args?.Action === 'status' ||
|
|
70
|
-
args?.action === 'status' ||
|
|
71
|
-
args?.Action === 'list' ||
|
|
72
|
-
args?.action === 'list')) ||
|
|
73
|
-
(toolName === 'manage_subagents' &&
|
|
74
|
-
(args?.Action === 'list' ||
|
|
75
|
-
args?.action === 'list'));
|
|
98
|
+
const isStatusPolling = isStatusPollingAction(toolName, args);
|
|
76
99
|
|
|
77
100
|
const isAnalyticsRoutine = this.routine === 'analytics-review';
|
|
78
101
|
|
|
@@ -151,14 +174,7 @@ export class LoopGuard {
|
|
|
151
174
|
isAnalyticsRoutine ||
|
|
152
175
|
pingPongSlice.some(
|
|
153
176
|
(item) =>
|
|
154
|
-
(item.toolName
|
|
155
|
-
(item.args?.Action === 'status' ||
|
|
156
|
-
item.args?.action === 'status' ||
|
|
157
|
-
item.args?.Action === 'list' ||
|
|
158
|
-
item.args?.action === 'list')) ||
|
|
159
|
-
(item.toolName === 'manage_subagents' &&
|
|
160
|
-
(item.args?.Action === 'list' ||
|
|
161
|
-
item.args?.action === 'list')) ||
|
|
177
|
+
isStatusPollingAction(item.toolName, item.args) ||
|
|
162
178
|
item.toolName === 'replace_file_content' ||
|
|
163
179
|
item.toolName === 'write_to_file'
|
|
164
180
|
);
|