@dev-loops/core 1.0.1 → 1.0.2-slim.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 +5 -2
- package/src/analysis/diff-analyzer.mjs +85 -137
- package/src/claude/asset-generation.mjs +7 -7
- package/src/claude/hook-decisions.mjs +167 -50
- package/src/config/config.mjs +388 -787
- package/src/config/extension-defaults.yaml +14 -9
- package/src/github/comment-id-guard.mjs +39 -1
- package/src/github/copilot-helpers.mjs +90 -158
- package/src/github/gh.mjs +49 -0
- package/src/loop/bash-command-classify.mjs +34 -49
- package/src/loop/commit-msg-guard.mjs +1 -1
- package/src/loop/conductor-routing.mjs +15 -23
- package/src/loop/copilot-loop-state.mjs +46 -94
- package/src/loop/gate-carry-forward.mjs +46 -22
- package/src/loop/gate-evidence-reconcile.mjs +75 -0
- package/src/loop/gate-fanin.mjs +266 -435
- package/src/loop/handoff-envelope.mjs +21 -21
- package/src/loop/issue-refinement-artifact.mjs +449 -284
- package/src/loop/lifecycle-state.mjs +10 -21
- package/src/loop/pr-gate-coordination.mjs +49 -49
- package/src/loop/queue-board-sync.mjs +16 -82
- package/src/loop/review-dispatch-plan.mjs +61 -122
- package/src/loop/review-lineage.mjs +19 -44
- package/src/loop/spec-authority.mjs +729 -0
- package/src/loop/steering.mjs +16 -68
- package/src/loop/ui-e2e-scoping.mjs +1 -0
- package/src/loop/worktree-guard.mjs +55 -0
- package/src/projects/list-queue-items.mjs +16 -175
- package/src/projects/move-queue-item.mjs +16 -171
- package/src/projects/projects-access.mjs +202 -0
- package/src/security/secret-scan.mjs +13 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gate-evidence-reconcile.mjs — deterministic self-heal for a stuck
|
|
3
|
+
* `gate-evidence` required status (issue #1935).
|
|
4
|
+
*
|
|
5
|
+
* The server-side `gate-evidence` check (`.github/workflows/gate-evidence.yml`)
|
|
6
|
+
* re-fires when a gate verdict is posted (ADR 0043). That native re-fire is
|
|
7
|
+
* racy: a verdict-post run can be CANCELLED by `cancel-in-progress` when a
|
|
8
|
+
* superseding event lands, or evaluate before the just-posted verdict is
|
|
9
|
+
* API-visible, leaving the required status stuck at `failure` even though a
|
|
10
|
+
* clean current-head `pre_approval_gate` verdict now exists. Nothing re-fires
|
|
11
|
+
* afterward, so the merge stays `UNSTABLE` until a manual `gh run rerun`
|
|
12
|
+
* (observed on PR #1934; ADR 0057).
|
|
13
|
+
*
|
|
14
|
+
* This pure decision separates the two cases the reconcile must never confuse:
|
|
15
|
+
* - evidence genuinely satisfied but the status is stuck non-green → re-fire
|
|
16
|
+
* the concrete run that posted the stale status (automating the manual
|
|
17
|
+
* rerun; the rerun re-evaluates LIVE evidence, which is now satisfied).
|
|
18
|
+
* - evidence genuinely NOT satisfied → do nothing. A head that truly lacks a
|
|
19
|
+
* clean current-head verdict MUST keep failing the check (fail-closed).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Required commit-status context posted by the gate-evidence workflow. */
|
|
23
|
+
export const GATE_EVIDENCE_STATUS_CONTEXT = "gate-evidence";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Extract the Actions run id from a gate-evidence commit-status `target_url`.
|
|
27
|
+
* The workflow points every posted status at its own run:
|
|
28
|
+
* https://github.com/<owner>/<repo>/actions/runs/<run_id>
|
|
29
|
+
* Returns the numeric run id as a string, or null when the URL is absent or
|
|
30
|
+
* not an Actions-run URL (an unexpected target_url must not be coerced).
|
|
31
|
+
*
|
|
32
|
+
* @param {string} [targetUrl]
|
|
33
|
+
* @returns {string|null}
|
|
34
|
+
*/
|
|
35
|
+
export function parseRunIdFromTargetUrl(targetUrl) {
|
|
36
|
+
if (typeof targetUrl !== "string") return null;
|
|
37
|
+
const match = targetUrl.match(/\/actions\/runs\/(\d+)(?:[/?#]|$)/);
|
|
38
|
+
return match ? match[1] : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Decide whether a stuck `gate-evidence` status should be re-fired.
|
|
43
|
+
*
|
|
44
|
+
* @param {object} input
|
|
45
|
+
* @param {boolean} input.evidenceSatisfied detect-checkpoint-evidence reports
|
|
46
|
+
* `evidenceState === "satisfied"` for the current head (clean draft_gate +
|
|
47
|
+
* current-head pre_approval_gate verdicts present).
|
|
48
|
+
* @param {string} [input.statusState] the `gate-evidence` commit-status state
|
|
49
|
+
* on the current head: `success` | `failure` | `error` | `pending` | `none`
|
|
50
|
+
* (`none` = no gate-evidence status posted for this head yet).
|
|
51
|
+
* @param {string|null} [input.runId] the Actions run id that posted the stale
|
|
52
|
+
* status (from `parseRunIdFromTargetUrl`), or null when unknown.
|
|
53
|
+
* @returns {{ action: "refire"|"none", runId?: string, reason: string }}
|
|
54
|
+
*/
|
|
55
|
+
export function resolveGateEvidenceStatusReconcile({ evidenceSatisfied, statusState, runId } = {}) {
|
|
56
|
+
// Fail-closed: never re-fire when the verdict evidence is genuinely not
|
|
57
|
+
// satisfied. This preserves the "verdict genuinely missing" case — the head
|
|
58
|
+
// keeps failing closed exactly as before (issue #1935 AC #3).
|
|
59
|
+
if (evidenceSatisfied !== true) {
|
|
60
|
+
return { action: "none", reason: "evidence-not-satisfied-fail-closed" };
|
|
61
|
+
}
|
|
62
|
+
// Already green — nothing to reconcile.
|
|
63
|
+
if (statusState === "success") {
|
|
64
|
+
return { action: "none", reason: "already-success" };
|
|
65
|
+
}
|
|
66
|
+
// Evidence IS satisfied for the current head, but the required status is not
|
|
67
|
+
// success (the push-before-verdict race: a cancelled/stale re-fire). Re-fire
|
|
68
|
+
// the concrete run that posted the stale status. Without a run id there is
|
|
69
|
+
// nothing to re-fire deterministically; leave it to the native path rather
|
|
70
|
+
// than forging a status.
|
|
71
|
+
if (!runId) {
|
|
72
|
+
return { action: "none", reason: "no-run-to-refire" };
|
|
73
|
+
}
|
|
74
|
+
return { action: "refire", runId, reason: "evidence-satisfied-status-stale" };
|
|
75
|
+
}
|