@ashlr/hub 3.2.7 → 3.3.2
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/CHANGELOG.md +314 -2
- package/README.md +54 -38
- package/dist/build-identity.json +2 -2
- package/dist/cli/audit.js +18 -0
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/backlog.d.ts +0 -5
- package/dist/cli/backlog.js +18 -0
- package/dist/cli/backlog.js.map +1 -1
- package/dist/cli/comms.js +20 -0
- package/dist/cli/comms.js.map +1 -1
- package/dist/cli/completions.d.ts +6 -1
- package/dist/cli/completions.js +33 -10
- package/dist/cli/completions.js.map +1 -1
- package/dist/cli/daemon.js +10 -3
- package/dist/cli/daemon.js.map +1 -1
- package/dist/cli/dashboard.js +5 -4
- package/dist/cli/dashboard.js.map +1 -1
- package/dist/cli/demo.d.ts +0 -27
- package/dist/cli/demo.js +17 -0
- package/dist/cli/demo.js.map +1 -1
- package/dist/cli/help.js +22 -9
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/inbox.d.ts +14 -2
- package/dist/cli/inbox.js +137 -23
- package/dist/cli/inbox.js.map +1 -1
- package/dist/cli/onboard.d.ts +0 -13
- package/dist/cli/onboard.js +20 -0
- package/dist/cli/onboard.js.map +1 -1
- package/dist/cli/resources.js +15 -0
- package/dist/cli/resources.js.map +1 -1
- package/dist/cli/run.js +1 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/sandbox.js +43 -0
- package/dist/cli/sandbox.js.map +1 -1
- package/dist/cli/serve.js +7 -3
- package/dist/cli/serve.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -3
- package/dist/cli/setup.js +14 -7
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/tui.d.ts +0 -6
- package/dist/cli/tui.js +14 -0
- package/dist/cli/tui.js.map +1 -1
- package/dist/cli/update.js +3 -1
- package/dist/cli/update.js.map +1 -1
- package/dist/core/config.js +70 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/daemon/loop.js +83 -3
- package/dist/core/daemon/loop.js.map +1 -1
- package/dist/core/daemon/runtime-activation-resident-start-protocol.d.ts +141 -0
- package/dist/core/daemon/runtime-activation-resident-start-protocol.js +462 -0
- package/dist/core/daemon/runtime-activation-resident-start-protocol.js.map +1 -0
- package/dist/core/daemon/runtime-activation-resident-start-runtime.d.ts +27 -0
- package/dist/core/daemon/runtime-activation-resident-start-runtime.js +28 -0
- package/dist/core/daemon/runtime-activation-resident-start-runtime.js.map +1 -0
- package/dist/core/daemon/runtime-activation-stopped-consumer.d.ts +139 -0
- package/dist/core/daemon/runtime-activation-stopped-consumer.js +995 -0
- package/dist/core/daemon/runtime-activation-stopped-consumer.js.map +1 -0
- package/dist/core/daemon/runtime-activation-stopped-runtime.d.ts +36 -0
- package/dist/core/daemon/runtime-activation-stopped-runtime.js +134 -0
- package/dist/core/daemon/runtime-activation-stopped-runtime.js.map +1 -0
- package/dist/core/daemon/runtime-activation-transaction.d.ts +41 -17
- package/dist/core/daemon/runtime-activation-transaction.js +80 -11
- package/dist/core/daemon/runtime-activation-transaction.js.map +1 -1
- package/dist/core/daemon/runtime-release-dependency-inventory.js +1 -0
- package/dist/core/daemon/runtime-release-dependency-inventory.js.map +1 -1
- package/dist/core/daemon/service-install-authority.d.ts +1 -1
- package/dist/core/daemon/service-install-authority.js +4 -2
- package/dist/core/daemon/service-install-authority.js.map +1 -1
- package/dist/core/dashboard.d.ts +10 -0
- package/dist/core/dashboard.js +103 -28
- package/dist/core/dashboard.js.map +1 -1
- package/dist/core/effective-config.js +7 -0
- package/dist/core/effective-config.js.map +1 -1
- package/dist/core/fleet/automerge-pass.js +57 -73
- package/dist/core/fleet/automerge-pass.js.map +1 -1
- package/dist/core/fleet/decisions-ledger.js +36 -13
- package/dist/core/fleet/decisions-ledger.js.map +1 -1
- package/dist/core/fleet/external-skill-git-capture.js +9 -1
- package/dist/core/fleet/external-skill-git-capture.js.map +1 -1
- package/dist/core/fleet/judge-decision-metadata.d.ts +8 -1
- package/dist/core/fleet/judge-decision-metadata.js +14 -1
- package/dist/core/fleet/judge-decision-metadata.js.map +1 -1
- package/dist/core/fleet/judge-trace.js +2 -1
- package/dist/core/fleet/judge-trace.js.map +1 -1
- package/dist/core/fleet/manager.d.ts +21 -1
- package/dist/core/fleet/manager.js +137 -41
- package/dist/core/fleet/manager.js.map +1 -1
- package/dist/core/fleet/post-merge-credit-label.d.ts +10 -0
- package/dist/core/fleet/post-merge-credit-label.js +13 -0
- package/dist/core/fleet/post-merge-credit-label.js.map +1 -0
- package/dist/core/fleet/post-merge-credit.d.ts +119 -12
- package/dist/core/fleet/post-merge-credit.js +353 -14
- package/dist/core/fleet/post-merge-credit.js.map +1 -1
- package/dist/core/fleet/self-improve.d.ts +38 -5
- package/dist/core/fleet/self-improve.js +201 -12
- package/dist/core/fleet/self-improve.js.map +1 -1
- package/dist/core/fleet/skill-library.d.ts +21 -2
- package/dist/core/fleet/skill-library.js +54 -12
- package/dist/core/fleet/skill-library.js.map +1 -1
- package/dist/core/fleet/worked-ledger.d.ts +22 -0
- package/dist/core/fleet/worked-ledger.js +32 -0
- package/dist/core/fleet/worked-ledger.js.map +1 -1
- package/dist/core/goals/store.js +60 -6
- package/dist/core/goals/store.js.map +1 -1
- package/dist/core/inbox/apply.js +2 -1
- package/dist/core/inbox/apply.js.map +1 -1
- package/dist/core/inbox/merge.d.ts +10 -1
- package/dist/core/inbox/merge.js +97 -18
- package/dist/core/inbox/merge.js.map +1 -1
- package/dist/core/integrations/github.d.ts +2 -0
- package/dist/core/integrations/github.js +2 -1
- package/dist/core/integrations/github.js.map +1 -1
- package/dist/core/learn/reflect.d.ts +42 -4
- package/dist/core/learn/reflect.js +66 -5
- package/dist/core/learn/reflect.js.map +1 -1
- package/dist/core/onboard.d.ts +2 -0
- package/dist/core/onboard.js +9 -3
- package/dist/core/onboard.js.map +1 -1
- package/dist/core/run/engines.d.ts +8 -0
- package/dist/core/run/engines.js +9 -1
- package/dist/core/run/engines.js.map +1 -1
- package/dist/core/run/learned-router.js +28 -3
- package/dist/core/run/learned-router.js.map +1 -1
- package/dist/core/run/orchestrator.d.ts +7 -2
- package/dist/core/run/orchestrator.js +88 -60
- package/dist/core/run/orchestrator.js.map +1 -1
- package/dist/core/swarm/rollback.d.ts +11 -0
- package/dist/core/swarm/rollback.js +54 -0
- package/dist/core/swarm/rollback.js.map +1 -1
- package/dist/core/swarm/runner.js +94 -8
- package/dist/core/swarm/runner.js.map +1 -1
- package/dist/core/types.d.ts +103 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/web/api.d.ts +6 -0
- package/dist/core/web/api.js +174 -18
- package/dist/core/web/api.js.map +1 -1
- package/dist/core/web/control.d.ts +20 -0
- package/dist/core/web/control.js +44 -32
- package/dist/core/web/control.js.map +1 -1
- package/dist/core/web/fleet-status-cache.d.ts +68 -0
- package/dist/core/web/fleet-status-cache.js +120 -0
- package/dist/core/web/fleet-status-cache.js.map +1 -0
- package/dist/core/web/public/app.js +5 -1
- package/dist/core/web/public/next/assets/index-CDHQraxS.css +1 -0
- package/dist/core/web/public/next/assets/index-zVKD9krw.js +69 -0
- package/dist/core/web/public/next/assets/index-zVKD9krw.js.map +1 -0
- package/dist/core/web/public/next/index.html +15 -0
- package/dist/core/web/read-session-revocations.d.ts +26 -0
- package/dist/core/web/read-session-revocations.js +48 -0
- package/dist/core/web/read-session-revocations.js.map +1 -0
- package/dist/core/web/server.js +73 -27
- package/dist/core/web/server.js.map +1 -1
- package/dist/core/web/static.d.ts +1 -1
- package/dist/core/web/static.js +54 -20
- package/dist/core/web/static.js.map +1 -1
- package/dist/release-dependency-inventory.json +1 -1
- package/docs/RUNTIME_ACTIVATION_AUTHORITY.md +115 -21
- package/docs/contracts/CONTRACT-M521.md +102 -0
- package/node_modules/fast-uri/index.js +201 -48
- package/node_modules/fast-uri/lib/schemes.js +9 -4
- package/node_modules/fast-uri/lib/utils.js +388 -91
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/component-safe-serialization.test.js +105 -0
- package/node_modules/fast-uri/test/equal.test.js +31 -3
- package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
- package/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
- package/node_modules/fast-uri/test/ipv6-validation.test.js +90 -0
- package/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
- package/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
- package/node_modules/fast-uri/test/parse.test.js +7 -3
- package/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
- package/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
- package/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
- package/node_modules/fast-uri/test/security-normalization.test.js +101 -0
- package/node_modules/fast-uri/test/security.test.js +75 -3
- package/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
- package/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
- package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
- package/node_modules/qs/CHANGELOG.md +26 -0
- package/node_modules/qs/README.md +19 -1
- package/node_modules/qs/dist/qs.js +25 -25
- package/node_modules/qs/eslint.config.mjs +1 -1
- package/node_modules/qs/lib/parse.js +16 -6
- package/node_modules/qs/lib/stringify.js +23 -8
- package/node_modules/qs/lib/utils.js +57 -11
- package/node_modules/qs/package.json +8 -7
- package/node_modules/qs/test/parse.js +419 -0
- package/node_modules/qs/test/stringify.js +317 -0
- package/node_modules/qs/test/utils.js +206 -0
- package/package.json +24 -6
- package/schema/config.schema.json +800 -5
- package/node_modules/which/CHANGELOG.md +0 -166
package/dist/core/inbox/merge.js
CHANGED
|
@@ -159,6 +159,20 @@ function decisionReadIsHealthy(decisions) {
|
|
|
159
159
|
const MERGE_BRANCH_PREFIX = 'ashlr/merge/';
|
|
160
160
|
/** Timeout for git operations (ms). */
|
|
161
161
|
const GIT_TIMEOUT = 30_000;
|
|
162
|
+
/**
|
|
163
|
+
* Gate 6.5 (self-eval parity, M54/M86): how many times to run test:invariants
|
|
164
|
+
* per flag state before declaring it red. >1 tolerates a one-off transient
|
|
165
|
+
* blip (lock timing, momentary contention) without weakening the gate — a
|
|
166
|
+
* genuinely broken invariant still fails every attempt. Kept small (one
|
|
167
|
+
* retry, short delay): sustained multi-minute contention from a concurrent
|
|
168
|
+
* test run can't be "waited out" here anyway — cross-tick retry (the
|
|
169
|
+
* proposal simply stays pending and is re-evaluated next pass, see
|
|
170
|
+
* automerge-pass.ts) is what actually absorbs that, and this must stay
|
|
171
|
+
* short enough to never turn a fast fail-closed refusal into a slow one.
|
|
172
|
+
*/
|
|
173
|
+
const SELF_EVAL_PARITY_RETRY_ATTEMPTS = 2;
|
|
174
|
+
/** Delay between self-eval parity retry attempts (ms). */
|
|
175
|
+
const SELF_EVAL_PARITY_RETRY_DELAY_MS = 500;
|
|
162
176
|
// ---------------------------------------------------------------------------
|
|
163
177
|
// git helpers — arg arrays, no shell
|
|
164
178
|
// ---------------------------------------------------------------------------
|
|
@@ -612,7 +626,23 @@ export function evaluateAutoMergeReadinessPreflight(proposal, cfg) {
|
|
|
612
626
|
return block('proposal has no repo');
|
|
613
627
|
if (proposal.verifyResult?.passed === false) {
|
|
614
628
|
const failed = proposal.verifyResult.failed?.filter(Boolean).join('; ');
|
|
615
|
-
|
|
629
|
+
const category = proposal.verifyResult.failureCategory;
|
|
630
|
+
// A verifier that could NOT be executed (missing binary, exit 127, spawn
|
|
631
|
+
// ENOENT) or that hit a bounded timeout/infra hiccup is a DIFFERENT
|
|
632
|
+
// outcome from a verifier that ran and found the diff broken. Both stay
|
|
633
|
+
// fail-closed (ready:false — this NEVER makes an unverified change
|
|
634
|
+
// eligible to merge), but only a real 'code' failure (or an
|
|
635
|
+
// unclassified/legacy record) may accrue toward stuckPassCount/
|
|
636
|
+
// autoArchive. An infra-flavored failure must not permanently kill a
|
|
637
|
+
// proposal whose only crime was that the verifier was momentarily
|
|
638
|
+
// unavailable — it stays pending and is retried next pass.
|
|
639
|
+
const explicitCodeFailure = category === 'code';
|
|
640
|
+
const advisories = !explicitCodeFailure
|
|
641
|
+
? [
|
|
642
|
+
`verifier-unavailable: verification could not run to completion (${category}) — not counted toward auto-archive; will retry`,
|
|
643
|
+
]
|
|
644
|
+
: [];
|
|
645
|
+
return block(`known verification failure: proposal.verifyResult.passed is false${failed ? ` (${failed})` : ''}`, advisories, explicitCodeFailure);
|
|
616
646
|
}
|
|
617
647
|
const trustBasis = cfg.foundry?.['autoMerge']
|
|
618
648
|
? cfg.foundry['autoMerge']?.['trustBasis'] ?? 'tier'
|
|
@@ -1417,6 +1447,7 @@ export function verifyResultFromProposalResult(result, source = 'auto-merge', ve
|
|
|
1417
1447
|
return {
|
|
1418
1448
|
passed: result.ok,
|
|
1419
1449
|
...(result.ok ? {} : { failed: [result.detail] }),
|
|
1450
|
+
...(result.ok || result.failureCategory === undefined ? {} : { failureCategory: result.failureCategory }),
|
|
1420
1451
|
detail: result.detail,
|
|
1421
1452
|
ran: [...result.ran],
|
|
1422
1453
|
...(result.browser ? { browser: result.browser } : {}),
|
|
@@ -1534,6 +1565,7 @@ function verifyResultFromStored(result) {
|
|
|
1534
1565
|
...(result.browser ? { browser: result.browser } : {}),
|
|
1535
1566
|
...(result.baseBranch ? { baseBranch: result.baseBranch } : {}),
|
|
1536
1567
|
...(result.baseHead ? { baseHead: result.baseHead } : {}),
|
|
1568
|
+
...(result.failureCategory ? { failureCategory: result.failureCategory } : {}),
|
|
1537
1569
|
};
|
|
1538
1570
|
}
|
|
1539
1571
|
function truncateEvidenceText(text, limit = 500) {
|
|
@@ -1685,6 +1717,8 @@ export async function verifyProposal(proposal, cfg) {
|
|
|
1685
1717
|
}
|
|
1686
1718
|
// Apply the diff to the worktree ONLY AFTER capturing the base-derived
|
|
1687
1719
|
// command list, then run those (immutable) commands against the patched tree.
|
|
1720
|
+
// Apply exactly to the verified index. Context drift is a refusal, not
|
|
1721
|
+
// authority to synthesize a three-way result that was never proposed.
|
|
1688
1722
|
patchFile = writeTmpFile(diff);
|
|
1689
1723
|
try {
|
|
1690
1724
|
gitRun(tmpDir, ['apply', '--index', patchFile]);
|
|
@@ -1711,6 +1745,7 @@ export async function verifyProposal(proposal, cfg) {
|
|
|
1711
1745
|
detail: `required verify '${vc.kind}' failed (exit ${res.exitCode}): ${res.command}`,
|
|
1712
1746
|
baseBranch: base,
|
|
1713
1747
|
baseHead,
|
|
1748
|
+
...(res.failureCategory ? { failureCategory: res.failureCategory } : {}),
|
|
1714
1749
|
};
|
|
1715
1750
|
}
|
|
1716
1751
|
// M281: for test commands, only block if NEW failures were introduced.
|
|
@@ -1788,6 +1823,7 @@ export async function verifyProposal(proposal, cfg) {
|
|
|
1788
1823
|
detail: `verify '${vc.kind}' failed (exit ${res.exitCode}): ${res.command}`,
|
|
1789
1824
|
baseBranch: base,
|
|
1790
1825
|
baseHead,
|
|
1826
|
+
...(res.failureCategory ? { failureCategory: res.failureCategory } : {}),
|
|
1791
1827
|
};
|
|
1792
1828
|
}
|
|
1793
1829
|
}
|
|
@@ -2467,11 +2503,12 @@ export async function autoMergeProposal(id, cfg, invocation = {}) {
|
|
|
2467
2503
|
let maxLinesForEvidence = 0;
|
|
2468
2504
|
// ── Gate 5.5 (M86): scope cap — only small, fully-bounded diffs auto-merge
|
|
2469
2505
|
// to main. Defaults are conservative; bounded config keys allow opt-in relaxation.
|
|
2470
|
-
//
|
|
2471
|
-
// maxRisk
|
|
2472
|
-
//
|
|
2473
|
-
//
|
|
2474
|
-
//
|
|
2506
|
+
// NOTE (was stale): this used to hard-require risk==='low' regardless of
|
|
2507
|
+
// cfg.maxRisk, silently overriding an operator's higher maxRisk for the
|
|
2508
|
+
// scope check even though Gate 5 above had already cleared it. M295 (below)
|
|
2509
|
+
// fixed that — the size cap now applies up to the CONFIGURED maxRisk, so
|
|
2510
|
+
// the two gates agree. File + line counts reuse the same diff parser as
|
|
2511
|
+
// classifyRisk so the two gates are consistent.
|
|
2475
2512
|
{
|
|
2476
2513
|
const autoMergeCfg = cfg.foundry
|
|
2477
2514
|
?.autoMerge;
|
|
@@ -2593,12 +2630,32 @@ export async function autoMergeProposal(id, cfg, invocation = {}) {
|
|
|
2593
2630
|
: 'npm';
|
|
2594
2631
|
if (scriptsForParity['test:invariants']) {
|
|
2595
2632
|
// Fast path: run only the invariant suite.
|
|
2633
|
+
//
|
|
2634
|
+
// Bounded retry (merge-pipeline reliability): test:invariants
|
|
2635
|
+
// includes concurrency/timing/disk-cap tests (h3/h5) that are
|
|
2636
|
+
// legitimately flaky under host contention — a second live daemon
|
|
2637
|
+
// tick, another sandboxed agent's test run, or transient disk
|
|
2638
|
+
// pressure can make ONE pass momentarily red for reasons that have
|
|
2639
|
+
// nothing to do with the proposal's diff. Unlike the main verify
|
|
2640
|
+
// path (Gate 6, M281/M293) there is no per-proposal baseline to
|
|
2641
|
+
// diff against here — this check runs against the UNPATCHED repo
|
|
2642
|
+
// tree, so a single flaky run previously meant 3 non-parity
|
|
2643
|
+
// refusals permanently auto-archived an otherwise-good proposal.
|
|
2644
|
+
// A genuinely broken invariant fails EVERY attempt and is still
|
|
2645
|
+
// refused — this only tolerates transient noise, never a real break.
|
|
2596
2646
|
const invariantCmd = {
|
|
2597
2647
|
kind: 'test',
|
|
2598
2648
|
cmd: [pm, 'run', 'test:invariants'],
|
|
2599
2649
|
};
|
|
2600
|
-
|
|
2601
|
-
|
|
2650
|
+
for (let attempt = 1; attempt <= SELF_EVAL_PARITY_RETRY_ATTEMPTS; attempt++) {
|
|
2651
|
+
const res = await runVerifyCommandAsync(invariantCmd, repo, parityCfg);
|
|
2652
|
+
if (res.ok)
|
|
2653
|
+
return true;
|
|
2654
|
+
if (attempt < SELF_EVAL_PARITY_RETRY_ATTEMPTS) {
|
|
2655
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, SELF_EVAL_PARITY_RETRY_DELAY_MS));
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
return false;
|
|
2602
2659
|
}
|
|
2603
2660
|
// Fallback: no targeted script — run all detected verify commands.
|
|
2604
2661
|
const cmds = detectVerifyCommands(repo, 'merge');
|
|
@@ -2608,8 +2665,18 @@ export async function autoMergeProposal(id, cfg, invocation = {}) {
|
|
|
2608
2665
|
return true;
|
|
2609
2666
|
}
|
|
2610
2667
|
for (const vc of cmds) {
|
|
2611
|
-
const
|
|
2612
|
-
|
|
2668
|
+
const attempts = vc.kind === 'test' ? SELF_EVAL_PARITY_RETRY_ATTEMPTS : 1;
|
|
2669
|
+
let ok = false;
|
|
2670
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
2671
|
+
const res = await runVerifyCommandAsync(vc, repo, parityCfg);
|
|
2672
|
+
ok = res.ok;
|
|
2673
|
+
if (ok)
|
|
2674
|
+
break;
|
|
2675
|
+
if (attempt < attempts) {
|
|
2676
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, SELF_EVAL_PARITY_RETRY_DELAY_MS));
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
if (!ok && vc.required !== false)
|
|
2613
2680
|
return false;
|
|
2614
2681
|
}
|
|
2615
2682
|
return true;
|
|
@@ -2741,7 +2808,7 @@ export async function autoMergeProposal(id, cfg, invocation = {}) {
|
|
|
2741
2808
|
let inlineAttestation;
|
|
2742
2809
|
const ts = new Date().toISOString();
|
|
2743
2810
|
const inlineReviewerIndependence = evaluateReviewerIndependence(proposal, inlineJudgeEngine);
|
|
2744
|
-
if (verdict.verdict === 'ship' && verdict.wouldMerge === true && isFrontierJudge(inlineJudgeEngine) &&
|
|
2811
|
+
if (verdict.considered === true && verdict.verdict === 'ship' && verdict.wouldMerge === true && isFrontierJudge(inlineJudgeEngine) &&
|
|
2745
2812
|
inlineReviewerIndependence.independent) {
|
|
2746
2813
|
try {
|
|
2747
2814
|
const { signJudgeAttestation: signAtt, hashDiff: hd } = await import('../foundry/provenance.js');
|
|
@@ -2772,22 +2839,31 @@ export async function autoMergeProposal(id, cfg, invocation = {}) {
|
|
|
2772
2839
|
action: 'judged',
|
|
2773
2840
|
engine: inlineJudgeEngine,
|
|
2774
2841
|
model: inlineJudgeEngine,
|
|
2775
|
-
verdict: verdict.verdict,
|
|
2776
|
-
|
|
2842
|
+
verdict: verdict.considered === true ? verdict.verdict : 'review',
|
|
2843
|
+
// M507: a judgeFailure verdict is a synthetic fail-closed fallback, not
|
|
2844
|
+
// a considered judgment. It must be distinguishable in the ledger from a
|
|
2845
|
+
// real 'review' — conflating them is what made ~22% of judge calls look
|
|
2846
|
+
// like deliberate rejections. Mirrors automerge-pass.ts:243 so BOTH judge
|
|
2847
|
+
// paths record the same way. `wouldMerge` is always false on a failure,
|
|
2848
|
+
// so this never displaces the 'would-merge' marker.
|
|
2849
|
+
detail: verdict.judgeFailure || verdict.considered !== true
|
|
2850
|
+
? (verdict.judgeFailure === 'network' ? 'judge-network-failure' : 'judge-parse-failure')
|
|
2851
|
+
: (verdict.wouldMerge && inlineReviewerIndependence.independent ? 'would-merge' : ''),
|
|
2777
2852
|
...(verdict.semanticEvents ? { semanticEvents: verdict.semanticEvents } : {}),
|
|
2778
2853
|
...(inlineAttestation !== undefined ? { judgeAttestation: inlineAttestation } : {}),
|
|
2779
2854
|
...(inlineAttestation !== undefined
|
|
2780
2855
|
? { judgeAttestationIssuedAt: ts, judgeAttestationIntent: 'would-merge' }
|
|
2781
2856
|
: {}),
|
|
2782
2857
|
});
|
|
2783
|
-
if (verdict.verdict === 'ship' && verdict.wouldMerge === true &&
|
|
2858
|
+
if (verdict.considered === true && verdict.verdict === 'ship' && verdict.wouldMerge === true &&
|
|
2784
2859
|
!inlineReviewerIndependence.independent) {
|
|
2785
2860
|
return refuse(`manager quality gate: ${inlineReviewerIndependence.reason}`, repo);
|
|
2786
2861
|
}
|
|
2862
|
+
const consideredVerdict = verdict.considered === true;
|
|
2787
2863
|
managerVerdict = {
|
|
2788
|
-
verdict: verdict.verdict,
|
|
2789
|
-
wouldMerge: verdict.wouldMerge,
|
|
2790
|
-
reasonCode: judgeDecisionReasonCode(verdict.verdict, verdict.wouldMerge && inlineReviewerIndependence.independent),
|
|
2864
|
+
verdict: consideredVerdict ? verdict.verdict : 'review',
|
|
2865
|
+
wouldMerge: consideredVerdict ? verdict.wouldMerge : false,
|
|
2866
|
+
reasonCode: judgeDecisionReasonCode(consideredVerdict ? verdict.verdict : 'review', consideredVerdict && verdict.wouldMerge && inlineReviewerIndependence.independent),
|
|
2791
2867
|
};
|
|
2792
2868
|
}
|
|
2793
2869
|
catch {
|
|
@@ -3385,7 +3461,10 @@ export async function autoMergeProposal(id, cfg, invocation = {}) {
|
|
|
3385
3461
|
mergeNote = 'PR opened; host auto-merge refused because canonical GitHub origin changed';
|
|
3386
3462
|
}
|
|
3387
3463
|
else {
|
|
3388
|
-
|
|
3464
|
+
// Protected PR handoff is the terminal autonomous action. A host
|
|
3465
|
+
// merge requires separate authority and remains intentionally
|
|
3466
|
+
// unavailable in this release.
|
|
3467
|
+
finalProtectedHandoffConfirmed = Boolean(url);
|
|
3389
3468
|
mergeNote = 'PR opened; host auto-merge is disabled until durable revocation is available';
|
|
3390
3469
|
}
|
|
3391
3470
|
}
|