@sjawhar/pi-legion-envoy 0.21.2 → 0.23.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/dist/envoy.js CHANGED
@@ -29691,7 +29691,7 @@ function dispatchToolSchema(spec, z, opts) {
29691
29691
  const shape = spec.arguments(z);
29692
29692
  return spec.validation === undefined ? z.object(shape, opts) : z.refineObject(shape, spec.validation.check, spec.validation.message, opts);
29693
29693
  }
29694
- var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue on first use in the repository's mapped project (DISPATCH_REPO_PROJECTS) or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
29694
+ var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue in the repository's dashboard-configured project or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
29695
29695
  var ASK_URGENCIES = ["low", "med", "high", "blocking"];
29696
29696
  var DOC_EDIT_OPS = ["replace", "delete", "insert"];
29697
29697
  var dispatchToolSpecs = [
@@ -30065,25 +30065,10 @@ var LegionDaemonApi = {
30065
30065
  request: architectCapability.extend({ issue: nonEmptyString, comment: string2().optional() }),
30066
30066
  response: object({})
30067
30067
  },
30068
- SpawnToken: {
30069
- request: architectCapability.extend({ issue: nonEmptyString, role: legionRole }),
30070
- response: object({ spawnToken: nonEmptyString })
30071
- },
30072
30068
  ProvisioningCredential: {
30073
30069
  request: architectCapability.extend({ issue: nonEmptyString }),
30074
30070
  response: object({ token: nonEmptyString })
30075
30071
  },
30076
- RoleBacking: {
30077
- request: strictObject({
30078
- tree: nonEmptyString,
30079
- issue: nonEmptyString,
30080
- role: legionRole,
30081
- sessionId: nonEmptyString,
30082
- agentId: nonEmptyString,
30083
- spawnToken: nonEmptyString
30084
- }),
30085
- response: object({})
30086
- },
30087
30072
  WorkerStarted: {
30088
30073
  request: strictObject({
30089
30074
  tree: nonEmptyString,
@@ -30130,20 +30115,6 @@ var LegionDaemonApi = {
30130
30115
  roleToken: nonEmptyString
30131
30116
  })
30132
30117
  },
30133
- Phase: {
30134
- request: strictObject({
30135
- tree: nonEmptyString,
30136
- issue: nonEmptyString,
30137
- phase: nonEmptyString,
30138
- sessionId: nonEmptyString,
30139
- spawnToken: nonEmptyString
30140
- }),
30141
- response: object({
30142
- secret: nonEmptyString,
30143
- gitName: nonEmptyString,
30144
- gitEmail: nonEmptyString
30145
- })
30146
- },
30147
30118
  WorkerSession: {
30148
30119
  request: strictObject({
30149
30120
  sessionId: nonEmptyString,
@@ -30182,6 +30153,10 @@ var LegionDaemonApi = {
30182
30153
  response: object({ token: nonEmptyString, appLogin: string2().endsWith("[bot]") })
30183
30154
  }
30184
30155
  };
30156
+ // ../contracts/src/repo.ts
30157
+ function canonicalRepo(owner, repo) {
30158
+ return `${owner.trim().toLowerCase()}/${repo.trim().toLowerCase().replace(/\.git$/, "")}`;
30159
+ }
30185
30160
  // ../contracts/src/tool-schema.ts
30186
30161
  function zodSchemaApi(zod) {
30187
30162
  const api = zod;
@@ -31112,7 +31087,7 @@ function parseGitHubRemoteUrl(url) {
31112
31087
  for (const pattern of GITHUB_REMOTE_PATTERNS) {
31113
31088
  const match = trimmed.match(pattern);
31114
31089
  if (match)
31115
- return `${match[1]}/${match[2]}`;
31090
+ return canonicalRepo(match[1] ?? "", match[2] ?? "");
31116
31091
  }
31117
31092
  return null;
31118
31093
  }
@@ -31346,6 +31321,10 @@ class DispatchClient {
31346
31321
  var nativeIssueKeyPattern = /^[A-Z][A-Z0-9]{1,9}-[0-9]+$/;
31347
31322
  var externalIssueRefPattern = /^([^/\s]+)\/([^/\s#]+)#([1-9][0-9]*)$/;
31348
31323
  var bareIssueNumberPattern = /^[1-9][0-9]*$/;
31324
+ function canonicalExternalIssueRef(value) {
31325
+ const match = value.trim().match(externalIssueRefPattern);
31326
+ return match ? `${canonicalRepo(match[1] ?? "", match[2] ?? "")}#${match[3]}` : value;
31327
+ }
31349
31328
  function stringArg(args, name) {
31350
31329
  const value = args[name];
31351
31330
  if (typeof value !== "string")
@@ -31415,7 +31394,7 @@ async function resolveIssueArguments(tool, args, cwd, env, exec) {
31415
31394
  return {
31416
31395
  args: {
31417
31396
  ...args,
31418
- ...issueArgument === undefined && ref?.issue !== undefined ? { issue: ref.issue } : {},
31397
+ ...typeof issueArgument === "string" ? { issue: canonicalExternalIssueRef(issueArgument) } : issueArgument === undefined && ref?.issue !== undefined ? { issue: ref.issue } : {},
31419
31398
  ...artifactArgument === undefined && (ref?.kind === "spec" || ref?.kind === "artifact") ? { artifact: ref.id } : {},
31420
31399
  ...versionArgument === undefined && ref?.version !== undefined ? { version: ref.version } : {}
31421
31400
  },
@@ -31426,7 +31405,7 @@ async function resolveIssueArguments(tool, args, cwd, env, exec) {
31426
31405
  if (!legionIssue)
31427
31406
  throw new Error("issue is required; supply issue or set LEGION_ISSUE");
31428
31407
  if (nativeIssueKeyPattern.test(legionIssue) || externalIssueRefPattern.test(legionIssue)) {
31429
- return { args: { ...args, issue: legionIssue }, ref: null };
31408
+ return { args: { ...args, issue: canonicalExternalIssueRef(legionIssue) }, ref: null };
31430
31409
  }
31431
31410
  if (!bareIssueNumberPattern.test(legionIssue)) {
31432
31411
  throw new Error("LEGION_ISSUE must be a native issue key (e.g. LEGION-3), an external owner/repo#n reference, or a bare positive issue number");
@@ -31759,7 +31738,7 @@ async function ensureIssue(client, issueReference, actor) {
31759
31738
  } catch (error) {
31760
31739
  if (error instanceof DispatchServiceError && error.code === "PROJECT_UNMAPPED") {
31761
31740
  const repository = issueReference.slice(0, issueReference.lastIndexOf("#"));
31762
- throw new Error(`repository ${repository} is not mapped in DISPATCH_REPO_PROJECTS and no DISPATCH_DEFAULT_PROJECT is configured`);
31741
+ throw new Error(`repository ${repository} is not mapped in repository settings and no DISPATCH_DEFAULT_PROJECT is configured`);
31763
31742
  }
31764
31743
  throw error;
31765
31744
  }
package/dist/legion.js CHANGED
@@ -29689,7 +29689,7 @@ function dispatchToolSchema(spec, z, opts) {
29689
29689
  const shape = spec.arguments(z);
29690
29690
  return spec.validation === undefined ? z.object(shape, opts) : z.refineObject(shape, spec.validation.check, spec.validation.message, opts);
29691
29691
  }
29692
- var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue on first use in the repository's mapped project (DISPATCH_REPO_PROJECTS) or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
29692
+ var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue in the repository's dashboard-configured project or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
29693
29693
  var ASK_URGENCIES = ["low", "med", "high", "blocking"];
29694
29694
  var DOC_EDIT_OPS = ["replace", "delete", "insert"];
29695
29695
  var dispatchToolSpecs = [
@@ -30063,25 +30063,10 @@ var LegionDaemonApi = {
30063
30063
  request: architectCapability.extend({ issue: nonEmptyString, comment: string2().optional() }),
30064
30064
  response: object({})
30065
30065
  },
30066
- SpawnToken: {
30067
- request: architectCapability.extend({ issue: nonEmptyString, role: legionRole }),
30068
- response: object({ spawnToken: nonEmptyString })
30069
- },
30070
30066
  ProvisioningCredential: {
30071
30067
  request: architectCapability.extend({ issue: nonEmptyString }),
30072
30068
  response: object({ token: nonEmptyString })
30073
30069
  },
30074
- RoleBacking: {
30075
- request: strictObject({
30076
- tree: nonEmptyString,
30077
- issue: nonEmptyString,
30078
- role: legionRole,
30079
- sessionId: nonEmptyString,
30080
- agentId: nonEmptyString,
30081
- spawnToken: nonEmptyString
30082
- }),
30083
- response: object({})
30084
- },
30085
30070
  WorkerStarted: {
30086
30071
  request: strictObject({
30087
30072
  tree: nonEmptyString,
@@ -30128,20 +30113,6 @@ var LegionDaemonApi = {
30128
30113
  roleToken: nonEmptyString
30129
30114
  })
30130
30115
  },
30131
- Phase: {
30132
- request: strictObject({
30133
- tree: nonEmptyString,
30134
- issue: nonEmptyString,
30135
- phase: nonEmptyString,
30136
- sessionId: nonEmptyString,
30137
- spawnToken: nonEmptyString
30138
- }),
30139
- response: object({
30140
- secret: nonEmptyString,
30141
- gitName: nonEmptyString,
30142
- gitEmail: nonEmptyString
30143
- })
30144
- },
30145
30116
  WorkerSession: {
30146
30117
  request: strictObject({
30147
30118
  sessionId: nonEmptyString,
@@ -30180,6 +30151,10 @@ var LegionDaemonApi = {
30180
30151
  response: object({ token: nonEmptyString, appLogin: string2().endsWith("[bot]") })
30181
30152
  }
30182
30153
  };
30154
+ // ../contracts/src/repo.ts
30155
+ function canonicalRepo(owner, repo) {
30156
+ return `${owner.trim().toLowerCase()}/${repo.trim().toLowerCase().replace(/\.git$/, "")}`;
30157
+ }
30183
30158
  // ../contracts/src/tool-schema.ts
30184
30159
  function zodSchemaApi(zod) {
30185
30160
  const api = zod;
@@ -31597,7 +31572,7 @@ function parseGitHubRemoteUrl(url) {
31597
31572
  for (const pattern of GITHUB_REMOTE_PATTERNS) {
31598
31573
  const match = trimmed.match(pattern);
31599
31574
  if (match)
31600
- return `${match[1]}/${match[2]}`;
31575
+ return canonicalRepo(match[1] ?? "", match[2] ?? "");
31601
31576
  }
31602
31577
  return null;
31603
31578
  }
@@ -31831,6 +31806,10 @@ class DispatchClient {
31831
31806
  var nativeIssueKeyPattern = /^[A-Z][A-Z0-9]{1,9}-[0-9]+$/;
31832
31807
  var externalIssueRefPattern = /^([^/\s]+)\/([^/\s#]+)#([1-9][0-9]*)$/;
31833
31808
  var bareIssueNumberPattern = /^[1-9][0-9]*$/;
31809
+ function canonicalExternalIssueRef(value) {
31810
+ const match = value.trim().match(externalIssueRefPattern);
31811
+ return match ? `${canonicalRepo(match[1] ?? "", match[2] ?? "")}#${match[3]}` : value;
31812
+ }
31834
31813
  function stringArg(args, name) {
31835
31814
  const value = args[name];
31836
31815
  if (typeof value !== "string")
@@ -31900,7 +31879,7 @@ async function resolveIssueArguments(tool, args, cwd, env, exec) {
31900
31879
  return {
31901
31880
  args: {
31902
31881
  ...args,
31903
- ...issueArgument === undefined && ref?.issue !== undefined ? { issue: ref.issue } : {},
31882
+ ...typeof issueArgument === "string" ? { issue: canonicalExternalIssueRef(issueArgument) } : issueArgument === undefined && ref?.issue !== undefined ? { issue: ref.issue } : {},
31904
31883
  ...artifactArgument === undefined && (ref?.kind === "spec" || ref?.kind === "artifact") ? { artifact: ref.id } : {},
31905
31884
  ...versionArgument === undefined && ref?.version !== undefined ? { version: ref.version } : {}
31906
31885
  },
@@ -31911,7 +31890,7 @@ async function resolveIssueArguments(tool, args, cwd, env, exec) {
31911
31890
  if (!legionIssue)
31912
31891
  throw new Error("issue is required; supply issue or set LEGION_ISSUE");
31913
31892
  if (nativeIssueKeyPattern.test(legionIssue) || externalIssueRefPattern.test(legionIssue)) {
31914
- return { args: { ...args, issue: legionIssue }, ref: null };
31893
+ return { args: { ...args, issue: canonicalExternalIssueRef(legionIssue) }, ref: null };
31915
31894
  }
31916
31895
  if (!bareIssueNumberPattern.test(legionIssue)) {
31917
31896
  throw new Error("LEGION_ISSUE must be a native issue key (e.g. LEGION-3), an external owner/repo#n reference, or a bare positive issue number");
@@ -32244,7 +32223,7 @@ async function ensureIssue(client, issueReference, actor) {
32244
32223
  } catch (error) {
32245
32224
  if (error instanceof DispatchServiceError && error.code === "PROJECT_UNMAPPED") {
32246
32225
  const repository = issueReference.slice(0, issueReference.lastIndexOf("#"));
32247
- throw new Error(`repository ${repository} is not mapped in DISPATCH_REPO_PROJECTS and no DISPATCH_DEFAULT_PROJECT is configured`);
32226
+ throw new Error(`repository ${repository} is not mapped in repository settings and no DISPATCH_DEFAULT_PROJECT is configured`);
32248
32227
  }
32249
32228
  throw error;
32250
32229
  }
@@ -18,7 +18,7 @@ Every session works on an issue. Legion pre-fills `issue` from `LEGION_ISSUE`: u
18
18
  such as `LEGION-3`, an external `owner/repo#n` reference, or a bare positive number (resolved
19
19
  against the cwd repository). Otherwise pass the issue to every issue-scoped tool as its native key
20
20
  or an external `owner/repo#n` reference. On first use, an external reference creates its native issue in the
21
- project mapped by `DISPATCH_REPO_PROJECTS`.
21
+ project configured for that repository in Dispatch Settings, then falls back to `DISPATCH_DEFAULT_PROJECT`.
22
22
 
23
23
  Architects create newly tracked child work with:
24
24
  ```ts
@@ -213,7 +213,7 @@ corresponding lifecycle procedure.
213
213
  | `pr-closed-unmerged` | Decide from current scope whether to reopen the work, send a fresh implementer, or cancel it with a reason. Delegate the repository action to the responsible phase worker and keep ownership. |
214
214
  | `issue-comment` | Interpret the comment in the issue's design context. Answer it, adjust the plan, or relay it via `envoy_publish` to the responsible worker's role token; scope and product decisions remain with you. |
215
215
  | `catchup-overseer` | Verify its gates, child counts, and PR verdicts against current artifacts, then resume the applicable numbered lifecycle step. It is a current-state snapshot, not a raw-event replay. For each entry in its `phaseCompletions` (`{issue, role, summary, at}`, phases that completed while you were not live), handle it exactly as a `phase-complete` wake. |
216
- | `revive-worker` | The extension has revived the backed worker. Do not create a duplicate; message the restored worker via `envoy_publish` to its role token if action is needed and rely on its committed handoff over recollection. |
216
+ | `worker-died` | Payload `{type:"worker-died", issue, role}`. The daemon probed and retried this role's worker through `MAX_LAUNCH_FAILURES` attempts and could not confirm a boot — never a raw-event replay or a silent revive. Reassess the work and `spawn_worker` again for the role (it resumes the same agent via `--resume` if a session file survived) or reassign it if the failure looks environmental, not agent-specific. |
217
217
  | `reopened` | Reopen the root lifecycle: inspect the reason and current artifacts, reassess scope and children, and resume at the first applicable numbered step. |
218
218
 
219
219
  ## Escalation judgment
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "0.21.2",
3
+ "version": "0.23.0",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [