@valescoagency/runway 0.8.0 → 0.8.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/README.md CHANGED
@@ -392,7 +392,7 @@ These are tractable, just not v1.
392
392
 
393
393
  ## Status
394
394
 
395
- 0.8.0 — production-shaped and dogfooded against live Linear queues.
395
+ 0.8.1 — production-shaped and dogfooded against live Linear queues.
396
396
  The end-to-end pipeline (init → run → review → PR) is stable; surface
397
397
  may still shift as the orchestrator's policy and iteration mechanics
398
398
  mature. See [CHANGELOG.md](./CHANGELOG.md) for per-release detail.
package/dist/linear.js CHANGED
@@ -42,14 +42,20 @@ const WorkflowStateTypeNodeSchema = Schema.Struct({
42
42
  // integration comments can lack an author); we map a missing user to
43
43
  // the empty string so downstream filters can match by name without a
44
44
  // null-guard at every call site.
45
+ //
46
+ // VA-415: `user` can also be *absent from the payload entirely* (vs.
47
+ // present-and-null) on some system / deleted-user comments. The
48
+ // optional + nullable shape below accepts all three forms: missing,
49
+ // null, and full struct. Downstream code already null-coalesces via
50
+ // `comment.user?.name ?? ""`.
45
51
  const CommentNodeSchema = Schema.Struct({
46
52
  id: Schema.String,
47
53
  body: Schema.String,
48
54
  createdAt: Schema.Union(Schema.String, Schema.DateFromSelf),
49
- user: Schema.NullOr(Schema.Struct({
55
+ user: Schema.optional(Schema.NullOr(Schema.Struct({
50
56
  id: Schema.String,
51
57
  name: Schema.String,
52
- })),
58
+ }))),
53
59
  });
54
60
  const ViewerSchema = Schema.Struct({
55
61
  id: Schema.String,
@@ -358,21 +364,44 @@ export function createLinearGateway(config, limiter = null) {
358
364
  message: `Issue ${issueId} has no team`,
359
365
  });
360
366
  }
367
+ // VA-416: Linear labels can be team-scoped OR
368
+ // workspace-scoped (no team association). Earlier code
369
+ // filtered by team only, which silently excluded
370
+ // workspace-scoped labels like the default
371
+ // `ready-for-human`. Query by name alone, then prefer a
372
+ // team-scoped match when one exists so the team-vs-
373
+ // workspace name-collision edge resolves the obvious way.
361
374
  const labels = await client.issueLabels({
362
- filter: {
363
- team: { id: { eq: team.id } },
364
- name: { eq: labelName },
365
- },
375
+ filter: { name: { eq: labelName } },
366
376
  });
367
- const rawLabel = labels.nodes[0];
368
- if (!rawLabel) {
377
+ const decoded = labels.nodes.map((l) => ({
378
+ raw: l,
379
+ decoded: decodeIssueLabelNode(l),
380
+ }));
381
+ const teamScoped = await (async () => {
382
+ for (const { raw, decoded: d } of decoded) {
383
+ const labelTeam = await raw.team;
384
+ if (labelTeam?.id === team.id)
385
+ return d;
386
+ }
387
+ return undefined;
388
+ })();
389
+ const workspaceScoped = await (async () => {
390
+ for (const { raw, decoded: d } of decoded) {
391
+ const labelTeam = await raw.team;
392
+ if (!labelTeam)
393
+ return d;
394
+ }
395
+ return undefined;
396
+ })();
397
+ const label = teamScoped ?? workspaceScoped;
398
+ if (!label) {
369
399
  throw new LinearNotFound({
370
400
  resource: "label",
371
401
  identifier: labelName,
372
- message: `Linear label "${labelName}" not found on team ${team.id}`,
402
+ message: `Linear label "${labelName}" not found at workspace scope or on team ${team.id}`,
373
403
  });
374
404
  }
375
- const label = decodeIssueLabelNode(rawLabel);
376
405
  const existing = await issue.labels();
377
406
  const existingIds = existing.nodes.map((l) => decodeIssueLabelNode(l).id);
378
407
  const labelIds = [...existingIds, label.id];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valescoagency/runway",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Linear-driven orchestrator + scaffolder for coding agents on Sandcastle. `runway init` scaffolds a target repo (sandcastle + varlock + 1Password); `runway run` drains a Linear queue against it; `runway doctor`, `runway upgrade`, `runway upgrade-repo` round out the lifecycle.",
5
5
  "license": "MIT",
6
6
  "author": {