@dev-loops/core 1.0.0-rc.4 → 1.0.0-rc.6

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.
@@ -1,5 +1,7 @@
1
1
  import { runChild as _runChild } from "../cli/primitives.mjs";
2
2
  import { parseJsonText } from "../github/review-threads.mjs";
3
+ import { runPickupRefinementGate } from "../loop/issue-refinement-artifact.mjs";
4
+ import { loadStateColumnMap, LOGICAL_COLUMN } from "../loop/queue-board-sync.mjs";
3
5
  import { resolveProjectSelector, findProject, parseItemRef } from "./resolve-project.mjs";
4
6
 
5
7
  // ── Validation ───────────────────────────────────────────────────────────
@@ -252,6 +254,7 @@ function statusOf(node) {
252
254
  function classifyExitCode(err) {
253
255
  if (err.code === "INVALID_REPO" || err.code === "INVALID_PROJECT" || err.code === "INVALID_ITEM" ||
254
256
  err.code === "INVALID_COLUMN" || err.code === "INVALID_ARGS") return 1;
257
+ if (err.code === "MISSING_REFINEMENT_ARTIFACT") return 4;
255
258
  if (err.code === "PROJECT_NOT_FOUND" || err.code === "FIELD_NOT_FOUND" || err.code === "COLUMN_NOT_FOUND" ||
256
259
  err.code === "ITEM_NOT_FOUND") return 3;
257
260
  return 2;
@@ -259,7 +262,7 @@ function classifyExitCode(err) {
259
262
 
260
263
  // ── Main logic ──────────────────────────────────────────────────────────
261
264
 
262
- async function main(args, { env = process.env, runChild } = {}) {
265
+ async function main(args, { env = process.env, runChild, cwd = null } = {}) {
263
266
  const child = runChild ?? _runChild;
264
267
  const repo = validateRepo(args.repo);
265
268
  const [owner, repoName] = repo.split("/");
@@ -365,6 +368,38 @@ async function main(args, { env = process.env, runChild } = {}) {
365
368
  };
366
369
  }
367
370
 
371
+ // 5b. QUEUE-ENQUEUE-REFINEMENT-GATE: moving an ISSUE into the pickup column
372
+ // must pass the same refinement gate `queue add` applies — a guard at one
373
+ // entry point but not its sibling is exactly the asymmetry this closes. Put
374
+ // here (in core, not the script wrapper) so every caller routing through core
375
+ // is covered — reconcile-queue.mjs included. reconcile is unaffected because
376
+ // it passes no cwd and never derives the pickup column. The column name is
377
+ // only derivable when cwd/config is supplied: an interactive `queue move` from
378
+ // a worktree passes cwd (gate fires), while headless callers (e.g.
379
+ // reconcile-queue.mjs) omit it and are unaffected — we simply never derive
380
+ // the column.
381
+ let refinement = null;
382
+ if (issueNumber !== null && typeof cwd === "string" && cwd.length > 0) {
383
+ const { columnNames, error: columnError } = loadStateColumnMap(cwd);
384
+ const pickupColumn = columnNames[LOGICAL_COLUMN.NEXT_UP];
385
+ if (pickupColumn && toColumn === pickupColumn) {
386
+ // Mirror queue add's fail-closed posture on a malformed `.devloops` when the
387
+ // interactive path supplied cwd AND the target is actually the pickup
388
+ // column: a config parse failure must never silently bypass the just-moved
389
+ // pickup refinement gate (the exact sibling asymmetry this issue closes).
390
+ // Scoped here (after the pickup-column guard) so an unrelated column move
391
+ // is not over-broadened into a hard CONFIG_ERROR failure.
392
+ if (columnError) {
393
+ throw Object.assign(
394
+ new Error(`could not resolve the pickup column (config read/parse error: ${columnError})`),
395
+ { code: "CONFIG_ERROR" },
396
+ );
397
+ }
398
+ const decision = await runPickupRefinementGate({ issueNumber, repo, env, runChild: child, auto: false });
399
+ refinement = { refined: decision.action === "enqueue" };
400
+ }
401
+ }
402
+
368
403
  // 6. Update Status via mutation
369
404
  const updatePayload = await ghGraphql(UPDATE_ITEM_FIELD, {
370
405
  projectId: project.id,
@@ -388,6 +423,7 @@ async function main(args, { env = process.env, runChild } = {}) {
388
423
  newColumn: toColumn,
389
424
  unchanged: false,
390
425
  },
426
+ ...(refinement ? { refinement } : {}),
391
427
  };
392
428
  }
393
429