@sjawhar/pi-legion-envoy 7.5.0 → 7.5.1
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/dist/legion.js
CHANGED
|
@@ -17475,7 +17475,7 @@ function endInjectedUserTurns(sessionID) {
|
|
|
17475
17475
|
// package.json
|
|
17476
17476
|
var package_default = {
|
|
17477
17477
|
name: "@sjawhar/pi-legion-envoy",
|
|
17478
|
-
version: "7.5.
|
|
17478
|
+
version: "7.5.1",
|
|
17479
17479
|
license: "Apache-2.0",
|
|
17480
17480
|
type: "module",
|
|
17481
17481
|
omp: {
|
|
@@ -17843,6 +17843,7 @@ var LegionThreadOutcome = exports_external.union([
|
|
|
17843
17843
|
]);
|
|
17844
17844
|
var LegionThreadsResolveResponse = exports_external.strictObject({
|
|
17845
17845
|
threads: exports_external.array(LegionThreadOutcome),
|
|
17846
|
+
withheld: exports_external.number().int().nonnegative(),
|
|
17846
17847
|
refused: exports_external.strictObject({ url: nonEmptyString, error: nonEmptyString }).optional()
|
|
17847
17848
|
});
|
|
17848
17849
|
var LegionEmptyResponse = exports_external.strictObject({});
|
|
@@ -18867,9 +18868,10 @@ var LEGION_HANDOFF_COMPLETE = {
|
|
|
18867
18868
|
},
|
|
18868
18869
|
refusal: (attempt) => `refused \`${attempt}\`: a phase is completed with the \`legion\` tool's ` + "`handoff_complete`, never a shell command: the tool call is what records the phase " + "complete. A root architect or a `task` subagent has no handoff actions: it leaves the " + "completion to the worker. Text that only names the command (a commit message, a PR body) " + "reads as the command: pass it in a file."
|
|
18869
18870
|
};
|
|
18871
|
+
var TREE_PANE_RULES = [JJ_LOG_REWRITE, LEGION_HANDOFF_COMPLETE];
|
|
18870
18872
|
var PANE_RULES = {
|
|
18871
|
-
"phase-worker":
|
|
18872
|
-
"root-architect":
|
|
18873
|
+
"phase-worker": TREE_PANE_RULES,
|
|
18874
|
+
"root-architect": TREE_PANE_RULES
|
|
18873
18875
|
};
|
|
18874
18876
|
function refusedCommand(command, commands, rule) {
|
|
18875
18877
|
if (commands === undefined) {
|
|
@@ -18916,7 +18918,11 @@ function paneRuleRefusal(toolCall, rules) {
|
|
|
18916
18918
|
}
|
|
18917
18919
|
var LEGION_LOADED_MARKER = Symbol.for("legion.pi-envoy.legion-loaded");
|
|
18918
18920
|
var CODE_MUTATION_TOOLS = ["edit", "write", "apply_patch"];
|
|
18919
|
-
var
|
|
18921
|
+
var CODE_TOOL_REFUSAL = {
|
|
18922
|
+
architect: "the architect delegates all code work to phase workers",
|
|
18923
|
+
reviewer: "the reviewer edits nothing except the final .legion/ cleanup commit via bash",
|
|
18924
|
+
merger: "the merger only verifies and reports"
|
|
18925
|
+
};
|
|
18920
18926
|
var TOOL_DEVICE_URL = /^xd:\/\//iu;
|
|
18921
18927
|
function isToolDeviceInvocation(toolCall) {
|
|
18922
18928
|
return toolCall.toolName === "write" && typeof toolCall.input.path === "string" && TOOL_DEVICE_URL.test(toolCall.input.path);
|
|
@@ -18999,24 +19005,10 @@ function legionExtension(pi) {
|
|
|
18999
19005
|
return;
|
|
19000
19006
|
const sessionID = context.sessionManager.getSessionId();
|
|
19001
19007
|
const active = claimSession.capability(sessionID);
|
|
19002
|
-
const
|
|
19003
|
-
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
if (active?.role === "architect" && toolCall.toolName === "task") {
|
|
19007
|
-
return {
|
|
19008
|
-
block: true,
|
|
19009
|
-
reason: "the architect delegates only through child issues and the daemon's phase workers; Legion runs one agent per process"
|
|
19010
|
-
};
|
|
19011
|
-
}
|
|
19012
|
-
if (active?.role === "reviewer" && !isToolDevice && CODE_MUTATION_TOOLS.includes(toolCall.toolName)) {
|
|
19013
|
-
return {
|
|
19014
|
-
block: true,
|
|
19015
|
-
reason: "the reviewer edits nothing except the final .legion/ cleanup commit via bash"
|
|
19016
|
-
};
|
|
19017
|
-
}
|
|
19018
|
-
if (active?.role === "merger" && !isToolDevice && MERGER_BLOCKED_TOOLS.includes(toolCall.toolName)) {
|
|
19019
|
-
return { block: true, reason: "the merger only verifies and reports" };
|
|
19008
|
+
const codeToolRefusal = active === undefined ? undefined : CODE_TOOL_REFUSAL[active.role];
|
|
19009
|
+
const mutatesCode = CODE_MUTATION_TOOLS.includes(toolCall.toolName) || active?.role === "architect" && toolCall.toolName === "bash" && !isSingleLegionCommand(toolCall.input.command);
|
|
19010
|
+
if (codeToolRefusal !== undefined && mutatesCode && !isToolDeviceInvocation(toolCall)) {
|
|
19011
|
+
return { block: true, reason: codeToolRefusal };
|
|
19020
19012
|
}
|
|
19021
19013
|
if (!needsGrant(toolCall))
|
|
19022
19014
|
return;
|
|
@@ -19108,5 +19100,6 @@ function legionExtension(pi) {
|
|
|
19108
19100
|
}
|
|
19109
19101
|
export {
|
|
19110
19102
|
setLegionBootstrapExitForTests,
|
|
19111
|
-
legionExtension as default
|
|
19103
|
+
legionExtension as default,
|
|
19104
|
+
CODE_TOOL_REFUSAL
|
|
19112
19105
|
};
|
|
@@ -285,6 +285,13 @@ is open. That is the one review-thread step a human takes: the review App cannot
|
|
|
285
285
|
on a pull request the implementer opened, and the implementer's and merger's runs of the command
|
|
286
286
|
close every accepted one.
|
|
287
287
|
|
|
288
|
+
If a reviewer reports that `legion threads resolve` exited 1 counting threads that hold the
|
|
289
|
+
implement App's pending draft (the daemon counts them and never names them), tell the worker
|
|
290
|
+
holding the issue's phase (`envoy_publish` to its role topic) to move the issue back to
|
|
291
|
+
`implementing` with `request_backward_move`, naming the count, so the implementer submits or
|
|
292
|
+
discards its pending review; its own run of the command names those threads `left open … an
|
|
293
|
+
unsubmitted draft in a pending review`. Open no ask for it: the implementer clears it.
|
|
294
|
+
|
|
288
295
|
## 7. Close
|
|
289
296
|
|
|
290
297
|
After the merge result and the implementer's production report are recorded, post the sign-off and
|
|
@@ -20,7 +20,16 @@ Every path it cites is in sjawhar/legion.
|
|
|
20
20
|
the daemon instead (`POST /legion/v1/threads/resolve`), which resolves as the implementer's App
|
|
21
21
|
only the threads a bot outside Legion's role Apps opened whose newest submitted comment is the
|
|
22
22
|
reviewer's `Accepted:`, on the pull request of the reviewer's own issue, and prints the same
|
|
23
|
-
lines; the reviewer never holds the implementer's token.
|
|
23
|
+
lines; the reviewer never holds the implementer's token. A thread whose newest comment is a
|
|
24
|
+
draft in the implement App's pending review (the implementer's or the merger's: GitHub shows it
|
|
25
|
+
to that App alone, as which the daemon reads) is left open and never named: the command prints
|
|
26
|
+
only how many there are (`<n> unresolved threads hold the implement App's pending draft and
|
|
27
|
+
were left open`) and exits 1, as it does on a refusal. Report that count to the architect before
|
|
28
|
+
you spend your one re-run of the failed workflow; the architect sends the issue back so the
|
|
29
|
+
implementer submits or discards its pending review. Once the review is submitted, the
|
|
30
|
+
implementer's reply is the thread's newest comment, which leaves it open: answer the thread
|
|
31
|
+
again, then run the command again. Once the review is discarded, your `Accepted:` is the newest
|
|
32
|
+
comment again, and running the command again closes the thread.
|
|
24
33
|
When `LEGION_GRANT_FILE` or `LEGION_GRANT` is set, use `legion threads resolve --pr <number> --repo <owner>/<repo>`.
|
|
25
34
|
When neither is set, add `--gh` to that command, which applies the fallback's rule below through
|
|
26
35
|
your own `gh`; where no `legion` command is installed, use `gh api graphql` with the session's
|