@dev-loops/core 1.0.1 → 1.0.2-pre.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/package.json +4 -2
- package/src/claude/hook-decisions.mjs +144 -20
- package/src/config/extension-defaults.yaml +14 -9
- package/src/github/comment-id-guard.mjs +38 -0
- package/src/github/gh.mjs +49 -0
- package/src/loop/commit-msg-guard.mjs +1 -1
- package/src/loop/gate-carry-forward.mjs +45 -21
- package/src/loop/gate-evidence-reconcile.mjs +75 -0
- package/src/loop/gate-fanin.mjs +34 -13
- package/src/loop/handoff-envelope.mjs +2 -2
- package/src/loop/issue-refinement-artifact.mjs +358 -99
- package/src/loop/pr-gate-coordination.mjs +13 -13
- package/src/loop/queue-board-sync.mjs +1 -28
- package/src/loop/review-dispatch-plan.mjs +1 -0
- package/src/loop/spec-authority.mjs +759 -0
- package/src/loop/ui-e2e-scoping.mjs +1 -0
- package/src/loop/worktree-guard.mjs +55 -0
- package/src/projects/list-queue-items.mjs +1 -30
- package/src/projects/move-queue-item.mjs +1 -30
- package/src/security/secret-scan.mjs +13 -1
|
@@ -4,8 +4,8 @@ import { evaluateUiE2eScoping } from "./ui-e2e-scoping.mjs";
|
|
|
4
4
|
import { evaluateUiDesignerReviewScoping } from "./ui-designer-review-scoping.mjs";
|
|
5
5
|
import { trimmedOrNull } from "./normalize.mjs";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
MALFORMED_AC_DOD_MATRIX_FINDING,
|
|
8
|
+
MISSING_AC_DOD_MATRIX_FINDING,
|
|
9
9
|
MISSING_EXPLICIT_NON_GOALS_FINDING,
|
|
10
10
|
} from "./issue-refinement-artifact.mjs";
|
|
11
11
|
|
|
@@ -246,16 +246,16 @@ function normalizeRefinementArtifactStatus(value) {
|
|
|
246
246
|
// their own validation-failure reason from the detector; that reason must
|
|
247
247
|
// replace the "linked issue" wording, which does not apply when the PR is the
|
|
248
248
|
// spec-of-record and no linked issue was ever expected.
|
|
249
|
-
// #
|
|
250
|
-
//
|
|
251
|
-
// gate's guidance (decideEnqueueRefinementGate) and the detector
|
|
249
|
+
// #1951 matrix-floor vocabulary for the draft-gate blocked reason: which piece
|
|
250
|
+
// of the refinement floor is missing per finding — the SAME finding taxonomy
|
|
251
|
+
// the enqueue gate's guidance (decideEnqueueRefinementGate) and the detector
|
|
252
252
|
// (detectIssueRefinementArtifact) use, so the draft gate (the unconditional
|
|
253
|
-
// backstop for that floor) cannot drift from it.
|
|
254
|
-
// linked issue
|
|
255
|
-
// the
|
|
253
|
+
// backstop for that floor) cannot drift from it. A checklist-only or
|
|
254
|
+
// matrix-malformed linked issue names the actually-missing/invalid artifact so
|
|
255
|
+
// the fix is not misdirected.
|
|
256
256
|
const REFINEMENT_MISSING_ARM_BY_FINDING = Object.freeze({
|
|
257
|
-
[
|
|
258
|
-
[
|
|
257
|
+
[MISSING_AC_DOD_MATRIX_FINDING]: "an AC→DoD mapping matrix (a two-column table mapping each acceptance-criterion outcome to its required completion evidence)",
|
|
258
|
+
[MALFORMED_AC_DOD_MATRIX_FINDING]: "a valid AC→DoD mapping matrix (the existing table is empty or identifier-only/tautological)",
|
|
259
259
|
[MISSING_EXPLICIT_NON_GOALS_FINDING]: "an explicit Non-goals section",
|
|
260
260
|
});
|
|
261
261
|
|
|
@@ -269,12 +269,12 @@ function formatRefinementBlockedReason(linkedIssue, status, refinementArtifact)
|
|
|
269
269
|
: REFINEMENT_ARTIFACT_FINDING;
|
|
270
270
|
const missingArm = REFINEMENT_MISSING_ARM_BY_FINDING[finding];
|
|
271
271
|
if (missingArm !== undefined) {
|
|
272
|
-
return `Linked issue #${linkedIssue} has an incomplete refinement matrix — it is missing ${missingArm}. Add it to the issue body to complete the
|
|
272
|
+
return `Linked issue #${linkedIssue} has an incomplete refinement matrix — it is missing ${missingArm}. Add it to the issue body to complete the AC→DoD mapping matrix + Non-goals refinement floor, then re-open the draft PR. finding=${finding}`;
|
|
273
273
|
}
|
|
274
274
|
if (linkedIssue !== null && Number.isInteger(linkedIssue)) {
|
|
275
|
-
return `Linked issue #${linkedIssue} has no refinement artifact (no
|
|
275
|
+
return `Linked issue #${linkedIssue} has no refinement artifact (no AC→DoD mapping matrix, or a resolvable linked refinement doc). Refine the issue to the authoritative AC→DoD mapping matrix plus an explicit Non-goals section — or link a refinement doc (tmp/refinement/*.md), a complete artifact on its own — then re-open the draft PR. finding=${REFINEMENT_ARTIFACT_FINDING}`;
|
|
276
276
|
}
|
|
277
|
-
return `The draft gate cannot complete: the linked issue has no detectable refinement artifact (no
|
|
277
|
+
return `The draft gate cannot complete: the linked issue has no detectable refinement artifact (no AC→DoD mapping matrix, or a resolvable linked refinement doc). finding=${REFINEMENT_ARTIFACT_FINDING}`;
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// #1472: describes the CI state a round-cap-reached fallback branch actually
|
|
@@ -2,7 +2,7 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parse as parseYaml } from "yaml";
|
|
4
4
|
import { main as moveQueueItemMain } from "../projects/move-queue-item.mjs";
|
|
5
|
-
import { ghGraphql } from "../github/gh.mjs";
|
|
5
|
+
import { ghGraphql, resolveOwner } from "../github/gh.mjs";
|
|
6
6
|
|
|
7
7
|
const DEFAULT_NON_SUCCESS_COLUMN = "Backlog";
|
|
8
8
|
|
|
@@ -277,18 +277,6 @@ export function loadStateColumnMap(repoRoot) {
|
|
|
277
277
|
|
|
278
278
|
// ── Minimal project lookup (read-only, no create/repair) ────────────────
|
|
279
279
|
|
|
280
|
-
const GET_USER_ID = [
|
|
281
|
-
"query($login:String!) {",
|
|
282
|
-
" user(login:$login) { id }",
|
|
283
|
-
"}"
|
|
284
|
-
].join("\n");
|
|
285
|
-
|
|
286
|
-
const GET_ORG_ID = [
|
|
287
|
-
"query($login:String!) {",
|
|
288
|
-
" organization(login:$login) { id }",
|
|
289
|
-
"}"
|
|
290
|
-
].join("\n");
|
|
291
|
-
|
|
292
280
|
const LIST_USER_PROJECTS = [
|
|
293
281
|
"query($login:String!, $after:String) {",
|
|
294
282
|
" user(login:$login) {",
|
|
@@ -311,21 +299,6 @@ const LIST_ORG_PROJECTS = [
|
|
|
311
299
|
"}"
|
|
312
300
|
].join("\n");
|
|
313
301
|
|
|
314
|
-
async function resolveOwner(login, env, runChild) {
|
|
315
|
-
const userPayload = await ghGraphql(GET_USER_ID, { login }, env, runChild);
|
|
316
|
-
if (userPayload?.data?.user?.id) {
|
|
317
|
-
return { id: userPayload.data.user.id, kind: "user" };
|
|
318
|
-
}
|
|
319
|
-
const orgPayload = await ghGraphql(GET_ORG_ID, { login }, env, runChild);
|
|
320
|
-
if (orgPayload?.data?.organization?.id) {
|
|
321
|
-
return { id: orgPayload.data.organization.id, kind: "org" };
|
|
322
|
-
}
|
|
323
|
-
throw Object.assign(
|
|
324
|
-
new Error(`Could not resolve owner ID for "${login}"`),
|
|
325
|
-
{ code: "NO_USER_ID" },
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
302
|
async function listAllProjects(login, kind, env, runChild) {
|
|
330
303
|
const query = kind === "org" ? LIST_ORG_PROJECTS : LIST_USER_PROJECTS;
|
|
331
304
|
const projects = [];
|
|
@@ -869,6 +869,7 @@ export function verifyPromptLeadingAlignment({ promptLeading, prefixBytes, prefi
|
|
|
869
869
|
*/
|
|
870
870
|
export const DEFAULT_DIFF_EXCLUDE_GLOBS = Object.freeze([
|
|
871
871
|
// Lockfiles.
|
|
872
|
+
"bun.lock", "**/bun.lock",
|
|
872
873
|
"package-lock.json", "**/package-lock.json",
|
|
873
874
|
"npm-shrinkwrap.json", "**/npm-shrinkwrap.json",
|
|
874
875
|
"yarn.lock", "**/yarn.lock",
|