chainlesschain 0.166.80 → 0.166.82
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 +8 -8
- package/package.json +2 -2
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-C5NtVVBN.js → AIOps-DMzLSUWK.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CE9-HsoR.js → ActionButton-CgnA23oA.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DRO6sI0Z.js → Analytics-CtXmm8Qe.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-CuVJiyC_.js → AppLayout-C5RIh5jA.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-GNahHsyZ.js → Artifacts-DM525zx0.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DWvTomfm.js → Audit-ChBx6f2l.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-k4TuA3ec.js → BackgroundAgents-BBHDxCda.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BxqN-65D.js → Backup-B-qzCAoM.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CYYLvwwD.js → BaseInput-C5yoIWAD.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CoDmZ9yb.js → Chat-NmTrci9a.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-pPuUDG2V.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-CRVlfbkN.js → Checkbox-KdFSU3vd.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-BttMy7rW.js → Codegen-L__BOv_4.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DsdlE4QC.js → Col-Dfuw4IQV.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BulheyO-.js → Community-BRlEhSbx.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BC_7wMxW.js → Compact-D7dRkv8n.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BA3PDNLK.js → Compliance-CdlFYNR3.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-B6Y3L-GP.js → Cowork-Ey7ksHq4.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-DLk_CG77.js → Cron-DBH__wGJ.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CvsKV-90.js → Crosschain-D3nu9dw7.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CD8K9G3F.js → DID-DS6vZBNv.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CXNE434f.js → Dashboard-DwFRk2T0.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-C_P5mttB.js → Dropdown-D7b73q3I.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-MxZvItNA.js → EmailListRenderer-DPNaVH36.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DRoJQrDb.js → EvolutionSettings-BEsOtdpf.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CBrz9T6T.js → FamilyGuardDashboard-ijSqsSsF.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DKlGgjNs.js → Federation-C0BOzPDh.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CteicPS5.js → FormItemContext-DkF5NoAg.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-Bs10mDna.js → GenericCardRenderer-DQsMcyJj.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CXwzFBIh.js → Git-DQRt88PU.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CYzcwfwf.js → Governance-DIjPmDN8.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-pYpCF1ws.js → Inference-BWMFtT7i.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-B0YJnOpj.js → KnowledgeGraph-M7TfkUVl.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-D-hJWfq-.js → Logs-BZv9Z6BY.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-D5NZGdg3.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-D5ZmI-si.js → Marketplace-Crd9MYHg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DByD6jY1.js → McpTools-C37yOQV0.js} +2 -2
- package/src/assets/web-panel/assets/{Memory--lsjJd7Y.js → Memory-BBsijJCd.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-GQ3vGZO9.js → MobileBridge-CiXIQCju.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-Dh2wq-NU.js → MobileProjects-C0KSvQm5.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-uQFoRe_Z.js → Mtc-C0XaQsOY.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BUBYbvuz.js → MtcAudit-DPqggKhw.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-D790SLqM.js → Multisig-Bie0ZVHe.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-DcV9gSqn.js → NLProgramming-BbuJlQ5b.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-sVl7Y_vt.js → Notes-CgqrJV8w.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-BHRPqBZ3.js → NotificationSettings-CusdZEQl.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-B029pIMF.js → OrderTableRenderer-B7RrCvCQ.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BKrF-dtp.js → Organization-BnFpz3bb.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-DOAGxhhi.js → Overflow-C_4_HyyZ.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-7uQ4F7lh.js → P2P-D0KpHxeg.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-Cfd_C9nc.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-C0qK0tAi.js → Permissions-D2LxL66N.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-DCnfXKyb.js → PersonalDataHub-CvSNIxt0.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-D8wdVvao.js → Pipeline-rUl-SM7V.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-C-dGmb9y.js → Privacy-BD8cWSNd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-ChKvrsfc.js → ProjectInit-RM7J4X2F.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CaWnzNBi.js → ProjectSettings-BIH38RsB.js} +2 -2
- package/src/assets/web-panel/assets/Projects-CTgx3Fxc.js +1 -0
- package/src/assets/web-panel/assets/{Providers-DTufbN-S.js → Providers-B9Kja2RK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CGv6QJMC.js → QrScannerModal-ByDKowTD.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BfNcUCfG.js → QuickAsk-DqEN1QOE.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B0s5YT2K.js → Recommend-CLrYwNiv.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-YCs5wa8P.js → RemoteSession-DyDltVPC.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-DBC__Ylq.js → Reputation-BfP8rJ1-.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D_NT1ROe.js → Row-BpnP6r1H.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-Dd9ktNRw.js → RssFeed-CBNI1lCN.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BsmlT4PY.js → Search-CLjrM-xj.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DN-_e3oM.js → Security-dRXtg-Mq.js} +2 -2
- package/src/assets/web-panel/assets/{Services-Bm_KqSDz.js → Services-DAHCtOHL.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BYldeYI0.js → Skeleton-D11Jgtur.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-h7XAXSls.js → Skills-DchvTO4k.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-4ArxAaMJ.js → Sla-BFOc2SbL.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-B639ejZr.js → SpeechSettings-Dud1xDd2.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DR6RRo1O.js → SyncSettings-CILfsA2S.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DysrrJVE.js → Tasks-C6Qrah_5.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DyyB9L9f.js → Templates--puiHyCR.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-XbmWbUl1.js → Tenant-cz5vITz_.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-C5GeciJG.js → Terminal-YRs75Gz8.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Db-NjeVy.js → TimelineRenderer-C5myb_QZ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-Btm9pYvJ.js → Tokens-Bk60iMIj.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-BhJ35b0V.js → Trigger-BAb-Fd4z.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-C5T4GJky.js → Trust-BlqwmpEB.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CqWxh5U0.js → UkeySign-C6jvuF-7.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DKyI9zg1.js → VideoEditing-7zbsdQUj.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-kgvyQOtT.js → Wallet-BAouk_kp.js} +2 -2
- package/src/assets/web-panel/assets/{WebAuthn-1wWucdJt.js → WebAuthn-BQapv504.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-rHVIbLME.js → WorkflowEditor-ChUXM-Qx.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DV8ZtfWQ.js → chat-7B6U8zgJ.js} +1 -1
- package/src/assets/web-panel/assets/{colors-zznFfEpj.js → colors-C8UqaLpe.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CWk10Qsu.js → compact-item-x47giTCj.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CtoMW-kY.js → createContext-D6ZwjgaZ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BFfV5AtN.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-ieyHKAZZ.js → hasIn-Cv3d9-Bu.js} +1 -1
- package/src/assets/web-panel/assets/{index-14ADEHo7.js → index-B7Dorc7r.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dz1TqS34.js → index-BGxo1YH0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNlvUg0O.js → index-BM-NYjej.js} +1 -1
- package/src/assets/web-panel/assets/{index-zY56IXHj.js → index-BMPk5D1m.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7yq9nAq.js → index-BTBkdyLk.js} +1 -1
- package/src/assets/web-panel/assets/{index-CrBful_u.js → index-BTisPSqa.js} +1 -1
- package/src/assets/web-panel/assets/{index-G9bqTRu6.js → index-BUzw-kDo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGYCtfL-.js → index-C1ElqYDD.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9w6Zr_O.js → index-CQ0-ny-o.js} +1 -1
- package/src/assets/web-panel/assets/{index-BrpyZMUe.js → index-CUUgXcPh.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bf9069uM.js → index-CUtcWTSe.js} +1 -1
- package/src/assets/web-panel/assets/{index-McW2cdbg.js → index-CXG6yiAf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DPwOEcUt.js → index-CXIUyx4U.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cn71LASJ.js → index-CaPZ_8kP.js} +1 -1
- package/src/assets/web-panel/assets/{index-B2WI4Jse.js → index-Cbf4RqOd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BG9KlVJl.js → index-Cc2bhSuI.js} +1 -1
- package/src/assets/web-panel/assets/{index-0GSB8LOT.js → index-Cc6jr0Yb.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdSnkhrR.js → index-Ce666S9v.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjkiJdIX.js → index-CiVEatgH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CewbVIM8.js → index-CrGQsbpb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DR1Uw5as.js → index-D4ZHX6wo.js} +1 -1
- package/src/assets/web-panel/assets/{index-2TTLREp7.js → index-D9lFBkS4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjNjO-VL.js → index-DD-V-N_m.js} +3 -3
- package/src/assets/web-panel/assets/{index-9fgmdiB_.js → index-DLHnYXVa.js} +1 -1
- package/src/assets/web-panel/assets/index-DUz_bv5i.js +1 -0
- package/src/assets/web-panel/assets/{index-Cqpfzkch.js → index-DVBG0Jqz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGZGQTF5.js → index-Dc0hePXV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSnQWQ4L.js → index-DtBUgc0G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLeX8Qp7.js → index-Dv5E07PZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdMho2Wr.js → index-DvoMGeL9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CxSgg3Xc.js → index-EDWA9JL1.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9jmNLfO.js → index-IVelXaiQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmtyRKy8.js → index-N9hNOl1i.js} +1 -1
- package/src/assets/web-panel/assets/{index--6zQrvYc.js → index-WhoNHp50.js} +1 -1
- package/src/assets/web-panel/assets/{index-CBS8OtL2.js → index-dbM4QvQZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-fmwnODwg.js → index-jgN2e0Oy.js} +1 -1
- package/src/assets/web-panel/assets/{index-esCpkxIZ.js → index-nogjrcQE.js} +1 -1
- package/src/assets/web-panel/assets/index-rQ59l7GO.js +1 -0
- package/src/assets/web-panel/assets/{index-DRuSuXJh.js → index-yYdCdtY1.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CVk4LKJK.js → initDefaultProps-DkKS5xtR.js} +1 -1
- package/src/assets/web-panel/assets/{motion-IAABGXc_.js → motion-CU-zBUIg.js} +1 -1
- package/src/assets/web-panel/assets/{move-B9HSYeZc.js → move-zBE0VEd4.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CJfDtM89.js → mtc-parser-B9WyO1je.js} +1 -1
- package/src/assets/web-panel/assets/{omit-D5dYnom7.js → omit-6sCoBNTL.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-xbUkaZdY.js → pickAttrs-DDRv_sFc.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CIUU5NKN.js → placementArrow-Cy_CBDw5.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BZpgHE8P.js → responsiveObserve-CIczLq9K.js} +1 -1
- package/src/assets/web-panel/assets/{slide-x_8rsSKk.js → slide-DFfZCvnG.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BZyDnVJs.js → statusUtils-DW-0HUl-.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DusfWp6J.js → styleChecker-BPYaBorP.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-022JzYAL.js → useFlexGapSupport-DYPoOaZc.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DRDxX7-3.js → useFs-ODUEWR17.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DFrCp7m_.js → usePersonalDataHub-CstUt15X.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-bCuSFOmr.js → vnode-D2GW8xCL.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-sCpZ0sw7.js → zoom-Bz6GoDwq.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/ws-approval-gate.js +7 -0
- package/src/lib/auto-mode-config.js +129 -40
- package/src/lib/context-memory-kernel/task-worklog-port.js +73 -24
- package/src/lib/diagnostic-excerpt.js +91 -10
- package/src/lib/diagnostic-workflow.js +2 -0
- package/src/lib/git-tool-input.js +7 -0
- package/src/lib/plan-mode.js +15 -4
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +2 -2
- package/src/lib/process-execution-broker/linux-open-flags.js +26 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +5 -9
- package/src/lib/remote-read-loop-guard.js +59 -14
- package/src/lib/task-progress-tracker.js +112 -12
- package/src/repl/agent-repl.js +15 -14
- package/src/runtime/agent-core.js +88 -2
- package/src/assets/web-panel/assets/ChatBubbleRenderer-ChTIMWch.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-BPQlDtB7.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-BegpATva.js +0 -7
- package/src/assets/web-panel/assets/Projects-2uNBqS05.js +0 -1
- package/src/assets/web-panel/assets/devWarning-_Wlo1cZJ.js +0 -1
- package/src/assets/web-panel/assets/index-Cj8Mcdok.js +0 -1
- package/src/assets/web-panel/assets/index-vira2aS_.js +0 -1
|
@@ -1,12 +1,41 @@
|
|
|
1
|
+
// Prefer test-runner verdicts over arbitrary "Error:" lines printed by tests.
|
|
2
|
+
// A verdict is evidence to retain, not a claim about which defect caused it.
|
|
3
|
+
const TEST_FAILURE =
|
|
4
|
+
/\bFAIL(?:ED)?\s+[^\r\n]*\.(?:[cm]?[jt]sx?|py|go|rs|java)(?=[:\s]|$)|(?:^|\s)not ok \d+\s+-|\bTest Files\s+\d+ failed/;
|
|
5
|
+
export function hasTestFailureVerdict(value) {
|
|
6
|
+
return (
|
|
7
|
+
typeof value === "string" &&
|
|
8
|
+
TEST_FAILURE.test(stripVTControlCharacters(value))
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
/** Retain source context for several errors; an error line is not a root cause. */
|
|
2
13
|
export function diagnosticExcerpt(value, limit = 1600) {
|
|
3
|
-
const text =
|
|
14
|
+
const text = stripVTControlCharacters(
|
|
15
|
+
typeof value === "string" ? value : JSON.stringify(value ?? ""),
|
|
16
|
+
);
|
|
4
17
|
if (text.length <= limit) return text;
|
|
18
|
+
if (limit < 256) return text.slice(0, Math.max(0, limit));
|
|
5
19
|
const marker = "\n[... omitted ...]\n";
|
|
6
|
-
|
|
20
|
+
// gh prefixes every log line with job/step/timestamp. Keep the original
|
|
21
|
+
// head/tail, but spend diagnostic windows on the actual failure and stack.
|
|
22
|
+
const lines = text
|
|
23
|
+
.split("\n")
|
|
24
|
+
.map((line) =>
|
|
25
|
+
line.replace(/^[^\t\r\n]+\t[^\t\r\n]+\t\d{4}-\d\d-\d\dT[\d:.]+Z\s?/, ""),
|
|
26
|
+
);
|
|
7
27
|
const errors = [];
|
|
8
28
|
const workers = [];
|
|
29
|
+
const failures = [];
|
|
30
|
+
const summaries = [];
|
|
9
31
|
for (let i = 0; i < lines.length; i++) {
|
|
32
|
+
if (TEST_FAILURE.test(lines[i])) failures.push(i);
|
|
33
|
+
if (
|
|
34
|
+
/\b(?:Test Files|Tests)\s+\d+ (?:failed|passed)|\b[\w -]+ tests (?:PASSED|FAILED)\b|\b(?:PASS|ok \d+ -)\b.*(?:negative|spawn|gate)/i.test(
|
|
35
|
+
lines[i],
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
summaries.push(i);
|
|
10
39
|
if (
|
|
11
40
|
/\b\w*Error:|Exception in thread|Caused by:|\bpanic:|panicked at|\bFAIL\b|error TS\d+|##\[error\]/.test(
|
|
12
41
|
lines[i],
|
|
@@ -20,11 +49,21 @@ export function diagnosticExcerpt(value, limit = 1600) {
|
|
|
20
49
|
)
|
|
21
50
|
workers.push(i);
|
|
22
51
|
}
|
|
23
|
-
//
|
|
24
|
-
// and
|
|
52
|
+
// A middle failed-test block used to disappear between an expected early
|
|
53
|
+
// error and the final gate error. Keep its location and adjacent assertion,
|
|
54
|
+
// alongside process summaries; never infer causality from their ordering.
|
|
55
|
+
const lastError = errors.at(-1);
|
|
56
|
+
const finalError =
|
|
57
|
+
lastError !== undefined &&
|
|
58
|
+
/Process completed with exit code/.test(lines[lastError]) &&
|
|
59
|
+
errors.at(-2) >= lastError - 2
|
|
60
|
+
? errors.at(-2)
|
|
61
|
+
: lastError;
|
|
25
62
|
const indices = [
|
|
26
63
|
...new Set(
|
|
27
|
-
[workers[0], errors[0],
|
|
64
|
+
[failures[0], workers[0], errors[0], finalError].filter(
|
|
65
|
+
(i) => i !== undefined,
|
|
66
|
+
),
|
|
28
67
|
),
|
|
29
68
|
].sort((a, b) => a - b);
|
|
30
69
|
if (!indices.length) {
|
|
@@ -33,19 +72,61 @@ export function diagnosticExcerpt(value, limit = 1600) {
|
|
|
33
72
|
text.slice(0, head) + marker + text.slice(-(limit - marker.length - head))
|
|
34
73
|
);
|
|
35
74
|
}
|
|
36
|
-
const
|
|
75
|
+
const failedSuites = summaries.filter((index) =>
|
|
76
|
+
/tests FAILED\b/.test(lines[index]),
|
|
77
|
+
);
|
|
78
|
+
const verdictIndices = failedSuites.length
|
|
79
|
+
? [
|
|
80
|
+
...new Set(
|
|
81
|
+
[
|
|
82
|
+
...failedSuites,
|
|
83
|
+
summaries.find((index) => /tests PASSED\b/.test(lines[index])),
|
|
84
|
+
...failedSuites.map((index) => {
|
|
85
|
+
const suite = /([\w-]+ tests) FAILED\b/.exec(lines[index])?.[1];
|
|
86
|
+
return suite
|
|
87
|
+
? summaries.findLast((next) =>
|
|
88
|
+
lines[next].includes(`${suite} PASSED`),
|
|
89
|
+
)
|
|
90
|
+
: undefined;
|
|
91
|
+
}),
|
|
92
|
+
].filter((index) => index !== undefined),
|
|
93
|
+
),
|
|
94
|
+
]
|
|
95
|
+
: summaries.slice(-5);
|
|
96
|
+
const verdicts = verdictIndices
|
|
97
|
+
.map((index) => lines[index])
|
|
98
|
+
.join("\n")
|
|
99
|
+
.slice(0, Math.floor(limit * 0.2));
|
|
100
|
+
const available =
|
|
101
|
+
limit -
|
|
102
|
+
marker.length * (indices.length + 1 + (verdicts ? 1 : 0)) -
|
|
103
|
+
verdicts.length;
|
|
37
104
|
const head = Math.floor(available * 0.1);
|
|
38
105
|
const tail = Math.floor(available * 0.15);
|
|
39
|
-
const
|
|
106
|
+
const windowBudget = available - head - tail;
|
|
107
|
+
const failureBudget = failures.length
|
|
108
|
+
? Math.floor(windowBudget * (indices.length > 1 ? 0.55 : 1))
|
|
109
|
+
: 0;
|
|
110
|
+
const perWindow = Math.floor(
|
|
111
|
+
(windowBudget - failureBudget) /
|
|
112
|
+
Math.max(1, indices.length - (failures.length ? 1 : 0)),
|
|
113
|
+
);
|
|
40
114
|
const windows = indices.map((index) => {
|
|
115
|
+
const size = index === failures[0] ? failureBudget : perWindow;
|
|
41
116
|
const before = lines
|
|
42
117
|
.slice(Math.max(0, index - 2), index)
|
|
43
118
|
.join("\n")
|
|
44
|
-
.slice(-Math.floor(
|
|
119
|
+
.slice(-Math.floor(size * 0.1));
|
|
45
120
|
return (before + "\n" + lines.slice(index, index + 10).join("\n")).slice(
|
|
46
121
|
0,
|
|
47
|
-
|
|
122
|
+
size,
|
|
48
123
|
);
|
|
49
124
|
});
|
|
50
|
-
return [
|
|
125
|
+
return [
|
|
126
|
+
text.slice(0, head),
|
|
127
|
+
...windows,
|
|
128
|
+
...(verdicts ? [verdicts] : []),
|
|
129
|
+
text.slice(-tail),
|
|
130
|
+
].join(marker);
|
|
51
131
|
}
|
|
132
|
+
import { stripVTControlCharacters } from "node:util";
|
|
@@ -4,6 +4,8 @@ export const DIAGNOSTIC_WORKFLOW_GUIDANCE =
|
|
|
4
4
|
"For debugging, retain the original failure signature (error, source location, stack, command, environment and revision when verified). " +
|
|
5
5
|
"Label each observation by its source and reproduction scope. A passing subset is not a successful full reproduction; a different error is a separate finding until evidence connects it to the original failure. " +
|
|
6
6
|
"Expected negative-test output, dependency/setup failures, failed assertions and runner/infrastructure failures are different possibilities. Inspect surrounding output and process outcomes before selecting one. Timing alone does not identify the cause, and argument order is not execution order. " +
|
|
7
|
+
"Keep confirmed facts separate from hypotheses and ruled-out signals, with their source. Preserve an established failure and excluded negative-test errors across compaction; a later command syntax error does not invalidate an earlier successful observation. Reopen a ruled-out hypothesis only when new evidence contradicts it. " +
|
|
8
|
+
"An issue, its linked PR, the PR head, a synthetic merge ref, the merged commit, and each workflow run/attempt are separate identities. Keep their numbers and revisions distinct. A green diagnostic retry does not replace the primary failure or prove that a flaky test was fixed. A different release workflow failing on that commit is a separate finding until connected to this task. " +
|
|
7
9
|
"State one hypothesis and the smallest check that can disprove it; after that check, update the hypothesis from the observed result instead of restarting discovery. " +
|
|
8
10
|
"Do not change dependencies while a reproduction using them is running. Poll background tasks by task_id and drain has_more_output after exit. " +
|
|
9
11
|
"Bind reports to verified paths, runs and attempts; do not substitute a local or stale report for the target run. A green report alone does not override a nonzero exit, unhandled errors or incomplete output. " +
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
// The git tool accepts argv text, not a shell program. Diagnose shell syntax
|
|
2
2
|
// before spawning git while preserving literal operators in quoted arguments.
|
|
3
3
|
export function gitToolInputError(command) {
|
|
4
|
+
if (/^\s*(?:git\s+)?gh(?:\.exe)?(?:\s|$)/i.test(command))
|
|
5
|
+
return {
|
|
6
|
+
success: false,
|
|
7
|
+
code: "CC_GIT_WRONG_TOOL",
|
|
8
|
+
error: "gh is the GitHub CLI, not a Git subcommand.",
|
|
9
|
+
hint: "Use run_shell for the original gh command, subject to its normal permissions. Use the git tool only for Git arguments such as status or log. No command was executed.",
|
|
10
|
+
};
|
|
4
11
|
let quote = null;
|
|
5
12
|
for (let i = 0; i < command.length; i++) {
|
|
6
13
|
const char = command[i];
|
package/src/lib/plan-mode.js
CHANGED
|
@@ -893,8 +893,8 @@ export class PlanModeManager extends EventEmitter {
|
|
|
893
893
|
}
|
|
894
894
|
|
|
895
895
|
_commitMutation(transaction, eventType) {
|
|
896
|
+
const previousRevision = this.revision;
|
|
896
897
|
if (!this._persistence) {
|
|
897
|
-
const previousRevision = this.revision;
|
|
898
898
|
this.revision += 1;
|
|
899
899
|
this.updatedAt = Date.now();
|
|
900
900
|
this.lastEvent = this.sessionId
|
|
@@ -906,6 +906,11 @@ export class PlanModeManager extends EventEmitter {
|
|
|
906
906
|
timestamp: this.updatedAt,
|
|
907
907
|
})
|
|
908
908
|
: null;
|
|
909
|
+
this.emit("revision-changed", {
|
|
910
|
+
revision: this.revision,
|
|
911
|
+
previousRevision,
|
|
912
|
+
type: eventType,
|
|
913
|
+
});
|
|
909
914
|
if (this.lastEvent) this.emit("session-event", { ...this.lastEvent });
|
|
910
915
|
return null;
|
|
911
916
|
}
|
|
@@ -920,6 +925,11 @@ export class PlanModeManager extends EventEmitter {
|
|
|
920
925
|
this.revision = snapshot.revision;
|
|
921
926
|
this.updatedAt = snapshot.updatedAt;
|
|
922
927
|
this.lastEvent = snapshot.event;
|
|
928
|
+
this.emit("revision-changed", {
|
|
929
|
+
revision: this.revision,
|
|
930
|
+
previousRevision,
|
|
931
|
+
type: eventType,
|
|
932
|
+
});
|
|
923
933
|
this.emit("session-event", { ...this.lastEvent });
|
|
924
934
|
return null;
|
|
925
935
|
} catch (error) {
|
|
@@ -1369,7 +1379,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
1369
1379
|
/**
|
|
1370
1380
|
* Check if a tool is allowed in current state
|
|
1371
1381
|
*/
|
|
1372
|
-
isToolAllowed(toolName) {
|
|
1382
|
+
isToolAllowed(toolName, { recordBlocked = true } = {}) {
|
|
1373
1383
|
if (!this.isActive()) return true;
|
|
1374
1384
|
if (
|
|
1375
1385
|
this.state === PlanState.APPROVED ||
|
|
@@ -1377,7 +1387,8 @@ export class PlanModeManager extends EventEmitter {
|
|
|
1377
1387
|
) {
|
|
1378
1388
|
const allowed =
|
|
1379
1389
|
this.executionLock?.allowedTools.includes(toolName) === true;
|
|
1380
|
-
if (!allowed
|
|
1390
|
+
if (!allowed && recordBlocked)
|
|
1391
|
+
this._recordBlockedTool(toolName, "execution-lock");
|
|
1381
1392
|
return allowed;
|
|
1382
1393
|
}
|
|
1383
1394
|
|
|
@@ -1386,7 +1397,7 @@ export class PlanModeManager extends EventEmitter {
|
|
|
1386
1397
|
|
|
1387
1398
|
// Block write tools and log
|
|
1388
1399
|
if (WRITE_TOOLS.has(toolName)) {
|
|
1389
|
-
this._recordBlockedTool(toolName, "planning");
|
|
1400
|
+
if (recordBlocked) this._recordBlockedTool(toolName, "planning");
|
|
1390
1401
|
return false;
|
|
1391
1402
|
}
|
|
1392
1403
|
|
|
@@ -21,13 +21,13 @@ import {
|
|
|
21
21
|
buildLinuxBwrapDescriptorScrubbedLaunch,
|
|
22
22
|
LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PATH,
|
|
23
23
|
} from "./linux-bwrap-descriptor-launch.js";
|
|
24
|
+
import { linuxTmpfileFlag } from "./linux-open-flags.js";
|
|
24
25
|
|
|
25
26
|
const BWRAP_PATH = "/usr/bin/bwrap";
|
|
26
27
|
const MAX_ATTESTED_FILE_BYTES = 256 * 1024 * 1024;
|
|
27
28
|
const MAX_MOUNTINFO_BYTES = 4 * 1024 * 1024;
|
|
28
29
|
const MOUNTINFO_PATH = "/proc/self/mountinfo";
|
|
29
30
|
const MOUNT_TOPOLOGY_VERSION = 1;
|
|
30
|
-
const O_TMPFILE = 0x410000;
|
|
31
31
|
const SYSTEM_DESTINATIONS = [
|
|
32
32
|
"/usr",
|
|
33
33
|
"/bin",
|
|
@@ -1085,7 +1085,7 @@ function createTrustedResources(
|
|
|
1085
1085
|
const flags =
|
|
1086
1086
|
Number(constants.O_RDWR) |
|
|
1087
1087
|
Number(constants.O_EXCL) |
|
|
1088
|
-
|
|
1088
|
+
linuxTmpfileFlag(constants) |
|
|
1089
1089
|
Number(constants.O_NOFOLLOW || 0) |
|
|
1090
1090
|
Number(constants.O_NONBLOCK || 0);
|
|
1091
1091
|
const fd = track(runtime.fs.openSync("/tmp", flags, 0o400), phase);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Linux defines O_TMPFILE as __O_TMPFILE | O_DIRECTORY. O_DIRECTORY is
|
|
2
|
+
// architecture-specific (0x4000 on ARM64, 0x10000 on x64), while Node does
|
|
3
|
+
// not expose O_TMPFILE on every supported build.
|
|
4
|
+
const LINUX_ANONYMOUS_TMPFILE_BIT = 0x400000;
|
|
5
|
+
|
|
6
|
+
export function linuxTmpfileFlag(constants) {
|
|
7
|
+
const directoryFlag = constants?.O_DIRECTORY;
|
|
8
|
+
if (
|
|
9
|
+
!Number.isSafeInteger(directoryFlag) ||
|
|
10
|
+
directoryFlag <= 0 ||
|
|
11
|
+
(directoryFlag & (directoryFlag - 1)) !== 0
|
|
12
|
+
) {
|
|
13
|
+
throw new Error("linux_o_directory_unavailable");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const fallbackFlag = LINUX_ANONYMOUS_TMPFILE_BIT | directoryFlag;
|
|
17
|
+
const tmpfileFlag = constants.O_TMPFILE ?? fallbackFlag;
|
|
18
|
+
if (
|
|
19
|
+
!Number.isSafeInteger(tmpfileFlag) ||
|
|
20
|
+
(tmpfileFlag & LINUX_ANONYMOUS_TMPFILE_BIT) === 0 ||
|
|
21
|
+
(tmpfileFlag & directoryFlag) !== directoryFlag
|
|
22
|
+
) {
|
|
23
|
+
throw new Error("linux_o_tmpfile_invalid");
|
|
24
|
+
}
|
|
25
|
+
return tmpfileFlag;
|
|
26
|
+
}
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
applyLinuxGenericWorkspaceSandbox,
|
|
34
34
|
isLinuxGenericWorkspaceContract,
|
|
35
35
|
} from "./linux-generic-bwrap-runtime.js";
|
|
36
|
+
import { linuxTmpfileFlag } from "./linux-open-flags.js";
|
|
36
37
|
import {
|
|
37
38
|
buildLinuxBwrapDescriptorScrubbedLaunch,
|
|
38
39
|
LINUX_BWRAP_DESCRIPTOR_SCRUBBER_PATH,
|
|
@@ -288,10 +289,7 @@ const LINUX_ELF_MACHINES = Object.freeze({
|
|
|
288
289
|
arm64: 183,
|
|
289
290
|
riscv64: 243,
|
|
290
291
|
});
|
|
291
|
-
//
|
|
292
|
-
// x64, arm64, and riscv64 use this value; unsupported seccomp architectures
|
|
293
|
-
// already fail closed before the anonymous filter is created.
|
|
294
|
-
const LINUX_O_TMPFILE = 0x410000;
|
|
292
|
+
// Anonymous snapshots and seccomp filters require the native O_TMPFILE flag.
|
|
295
293
|
const LINUX_CLONE_NEWNS = 0x00020000;
|
|
296
294
|
const LINUX_CLONE_NEWUSER = 0x10000000;
|
|
297
295
|
const LINUX_NAMESPACE_CLONE_FLAGS = LINUX_CLONE_NEWNS | LINUX_CLONE_NEWUSER;
|
|
@@ -2728,9 +2726,7 @@ function sameWindowsFileIdentity(left, right) {
|
|
|
2728
2726
|
// the deletion authority.
|
|
2729
2727
|
function sameWindowsFileObjectIdentity(left, right) {
|
|
2730
2728
|
return (
|
|
2731
|
-
left.dev === right.dev &&
|
|
2732
|
-
left.ino === right.ino &&
|
|
2733
|
-
left.mode === right.mode
|
|
2729
|
+
left.dev === right.dev && left.ino === right.ino && left.mode === right.mode
|
|
2734
2730
|
);
|
|
2735
2731
|
}
|
|
2736
2732
|
|
|
@@ -5853,7 +5849,7 @@ function createLinuxRegularFileSnapshot(
|
|
|
5853
5849
|
const writerFlags =
|
|
5854
5850
|
Number(constants.O_RDWR) |
|
|
5855
5851
|
Number(constants.O_EXCL) |
|
|
5856
|
-
|
|
5852
|
+
linuxTmpfileFlag(constants) |
|
|
5857
5853
|
Number(constants.O_NOFOLLOW || 0) |
|
|
5858
5854
|
Number(constants.O_NONBLOCK || 0);
|
|
5859
5855
|
writerFd = runtime.fs.openSync("/tmp", writerFlags, snapshotSourceMode);
|
|
@@ -7442,7 +7438,7 @@ function pinLinuxNetworkSeccompFilter(runtime, options = {}) {
|
|
|
7442
7438
|
const flags =
|
|
7443
7439
|
Number(constants.O_RDWR) |
|
|
7444
7440
|
Number(constants.O_EXCL) |
|
|
7445
|
-
|
|
7441
|
+
linuxTmpfileFlag(constants) |
|
|
7446
7442
|
Number(constants.O_NOFOLLOW || 0) |
|
|
7447
7443
|
Number(constants.O_NONBLOCK || 0);
|
|
7448
7444
|
// An anonymous inode avoids a same-UID process opening the filter by path.
|
|
@@ -18,6 +18,19 @@ function pullRequestTarget(repo, id = "list") {
|
|
|
18
18
|
return { ...githubTarget(repo, "pulls", id), pullRequest: true };
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function issueTarget(repo, id = "list") {
|
|
22
|
+
return { ...githubTarget(repo, "issues", id), issue: true };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const ISSUE_WORKFLOW_GUIDANCE =
|
|
26
|
+
"Issue investigation: retain the issue, linked PR and workflow run as separate targets, with verified revisions and observed test outcomes. " +
|
|
27
|
+
"Use gh issue view for an issue and gh pr view for its linked PR; their numbers need not match. " +
|
|
28
|
+
"Use gh run view <run-id> for one run; gh run list accepts filters, not a positional run ID. " +
|
|
29
|
+
"For unknown JSON fields, inspect stderr/help and request supported fields without jq or shell pipelines first. " +
|
|
30
|
+
"A completed metadata read remains evidence after an unrelated command fails; do not restart the same investigation. " +
|
|
31
|
+
"Once the failing test and source are known, state a falsifiable hypothesis, run the focused reproduction, then make and validate the authorized fix. " +
|
|
32
|
+
"A merged PR or a passing diagnostic retry alone does not resolve the reported failure. Perform issue closure only when authorized and supported by the requested resolution evidence. ";
|
|
33
|
+
|
|
21
34
|
function commandFlag(command, names) {
|
|
22
35
|
return new RegExp(
|
|
23
36
|
`(?:^|\\s)(?:${names})(?:=|\\s+)(?:"([^"]*)"|'([^']*)'|([^\\s;&|]+))`,
|
|
@@ -27,13 +40,16 @@ function commandFlag(command, names) {
|
|
|
27
40
|
.find((value) => value !== undefined);
|
|
28
41
|
}
|
|
29
42
|
|
|
30
|
-
function
|
|
43
|
+
function discussionCommandTarget(command) {
|
|
31
44
|
const match =
|
|
32
|
-
/(?:^|[\s;&|])gh(?:\.exe)?\s+pr\s+(list|view|diff)\b([^;&|\r\n]*)/i.exec(
|
|
45
|
+
/(?:^|[\s;&|])gh(?:\.exe)?\s+(pr|issue)\s+(list|view|diff)\b([^;&|\r\n]*)/i.exec(
|
|
33
46
|
command,
|
|
34
47
|
);
|
|
35
48
|
if (!match) return null;
|
|
36
|
-
const
|
|
49
|
+
const target =
|
|
50
|
+
match[1].toLowerCase() === "issue" ? issueTarget : pullRequestTarget;
|
|
51
|
+
const tail = match[3];
|
|
52
|
+
const fields = commandFlag(tail, "--json")?.split(",");
|
|
37
53
|
// Lightweight status polling is intentional waiting, not repeated review.
|
|
38
54
|
if (
|
|
39
55
|
fields?.length &&
|
|
@@ -44,18 +60,20 @@ function pullRequestCommandTarget(command) {
|
|
|
44
60
|
)
|
|
45
61
|
)
|
|
46
62
|
return null;
|
|
47
|
-
const repo = commandFlag(
|
|
48
|
-
if (match[
|
|
63
|
+
const repo = commandFlag(tail, "--repo|-R") || "current-repo";
|
|
64
|
+
if (match[2].toLowerCase() === "list") return target(repo);
|
|
49
65
|
const prUrl =
|
|
50
|
-
/https:\/\/github\.com\/([^/\s]+\/[^/\s]+)\/pull\/(\d+)\b/i.exec(
|
|
51
|
-
|
|
66
|
+
/https:\/\/github\.com\/([^/\s]+\/[^/\s]+)\/(?:pull|issues)\/(\d+)\b/i.exec(
|
|
67
|
+
tail,
|
|
68
|
+
);
|
|
69
|
+
if (prUrl) return target(prUrl[1], prUrl[2]);
|
|
52
70
|
// Remove flags that consume values before finding the positional PR number.
|
|
53
|
-
const positional =
|
|
71
|
+
const positional = tail.replace(
|
|
54
72
|
/(?:^|\s)(?:--repo|-R|--json|--jq|-q|--template|-t|--color)(?:=|\s+)(?:"[^"]*"|'[^']*'|[^\s]+)/g,
|
|
55
73
|
" ",
|
|
56
74
|
);
|
|
57
75
|
const number = /(?:^|\s)["']?(\d+)["']?(?=\s|$)/.exec(positional)?.[1];
|
|
58
|
-
return number ?
|
|
76
|
+
return number ? target(repo, number) : null;
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
function urlTarget(value) {
|
|
@@ -69,6 +87,10 @@ function urlTarget(value) {
|
|
|
69
87
|
};
|
|
70
88
|
}
|
|
71
89
|
if (url.hostname === "github.com") {
|
|
90
|
+
const issue = /^\/([^/]+\/[^/]+)\/issues(?:\/(\d+))?\/?$/.exec(
|
|
91
|
+
url.pathname,
|
|
92
|
+
);
|
|
93
|
+
if (issue) return issueTarget(issue[1], issue[2]);
|
|
72
94
|
const pr =
|
|
73
95
|
/^\/([^/]+\/[^/]+)\/(?:pulls\/?|pull\/(\d+)(?:\/(?:files|commits|checks))?\/?|pull\/(\d+)\.(?:diff|patch))$/.exec(
|
|
74
96
|
url.pathname,
|
|
@@ -87,6 +109,11 @@ function urlTarget(value) {
|
|
|
87
109
|
);
|
|
88
110
|
}
|
|
89
111
|
if (url.hostname === "api.github.com") {
|
|
112
|
+
const issue =
|
|
113
|
+
/^\/repos\/([^/]+\/[^/]+)\/issues(?:\/(\d+)(?:\/(?:comments|events|timeline))?)?\/?$/.exec(
|
|
114
|
+
url.pathname,
|
|
115
|
+
);
|
|
116
|
+
if (issue) return issueTarget(issue[1], issue[2]);
|
|
90
117
|
const pr =
|
|
91
118
|
/^\/repos\/([^/]+\/[^/]+)\/pulls(?:\/(\d+)(?:\/(?:files|commits|reviews|comments))?)?\/?$/.exec(
|
|
92
119
|
url.pathname,
|
|
@@ -144,8 +171,8 @@ export function remoteReadTarget(tool, args = {}) {
|
|
|
144
171
|
}
|
|
145
172
|
if (tool !== "run_shell") return null;
|
|
146
173
|
const command = typeof args.command === "string" ? args.command : "";
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
174
|
+
const discussion = discussionCommandTarget(command);
|
|
175
|
+
if (discussion) return discussion;
|
|
149
176
|
const view = /(?:^|[\s;&|])gh(?:\.exe)?\s+run\s+view\s+([^;&|\r\n]+)/i.exec(
|
|
150
177
|
command,
|
|
151
178
|
);
|
|
@@ -172,6 +199,11 @@ export function remoteReadTarget(tool, args = {}) {
|
|
|
172
199
|
/(?:^|\s)(?:(?:--field|--raw-field|--input)(?:=|\s)|-[fF])/.test(command)
|
|
173
200
|
)
|
|
174
201
|
return null;
|
|
202
|
+
const issueApi =
|
|
203
|
+
/(?:https:\/\/api\.github\.com\/)?\/?repos\/([\w.-]+\/[\w.-]+)\/issues(?:\/(\d+)(?:\/(?:comments|events|timeline))?)?(?=[?\s"']|$)/.exec(
|
|
204
|
+
command,
|
|
205
|
+
);
|
|
206
|
+
if (issueApi) return issueTarget(issueApi[1], issueApi[2]);
|
|
175
207
|
const prApi =
|
|
176
208
|
/(?:https:\/\/api\.github\.com\/)?\/?repos\/([\w.-]+\/[\w.-]+)\/pulls(?:\/(\d+)(?:\/(?:files|commits|reviews|comments))?)?(?=[?\s"']|$)/.exec(
|
|
177
209
|
command,
|
|
@@ -369,6 +401,14 @@ export class RemoteReadLoopGuard {
|
|
|
369
401
|
get recoveryHint() {
|
|
370
402
|
if (!(this.targets.get(this.activeKey)?.repeats >= RECOVERY_AFTER))
|
|
371
403
|
return null;
|
|
404
|
+
if (this.targets.get(this.activeKey)?.issue) {
|
|
405
|
+
return (
|
|
406
|
+
"Remote-read loop recovery: repeated issue reads returned failures or already-seen evidence. " +
|
|
407
|
+
"Use the retained observations; identify the exact missing fact before a new focused read. " +
|
|
408
|
+
ISSUE_WORKFLOW_GUIDANCE +
|
|
409
|
+
DIAGNOSTIC_WORKFLOW_GUIDANCE
|
|
410
|
+
);
|
|
411
|
+
}
|
|
372
412
|
if (this.targets.get(this.activeKey)?.shellPolicy) {
|
|
373
413
|
return (
|
|
374
414
|
"Tool-policy loop recovery: the same execution policy keeps rejecting commands, even when their arguments change. " +
|
|
@@ -449,6 +489,8 @@ export class RemoteReadLoopGuard {
|
|
|
449
489
|
}
|
|
450
490
|
|
|
451
491
|
get workflowHint() {
|
|
492
|
+
if (this.targets.get(this.activeKey)?.issue)
|
|
493
|
+
return ISSUE_WORKFLOW_GUIDANCE + DIAGNOSTIC_WORKFLOW_GUIDANCE;
|
|
452
494
|
const active = this.targets.get(this.activeKey);
|
|
453
495
|
if (active?.github && !active.pullRequest) {
|
|
454
496
|
return (
|
|
@@ -505,6 +547,7 @@ export class RemoteReadLoopGuard {
|
|
|
505
547
|
page,
|
|
506
548
|
localLog,
|
|
507
549
|
pullRequest,
|
|
550
|
+
issue,
|
|
508
551
|
shellPolicy,
|
|
509
552
|
gitRepository,
|
|
510
553
|
}) => ({
|
|
@@ -515,9 +558,11 @@ export class RemoteReadLoopGuard {
|
|
|
515
558
|
: github
|
|
516
559
|
? pullRequest
|
|
517
560
|
? "GitHub pull requests"
|
|
518
|
-
:
|
|
519
|
-
? "
|
|
520
|
-
:
|
|
561
|
+
: issue
|
|
562
|
+
? "GitHub issues"
|
|
563
|
+
: localLog
|
|
564
|
+
? "saved GitHub Actions log"
|
|
565
|
+
: "GitHub Actions logs"
|
|
521
566
|
: tool === "web_search"
|
|
522
567
|
? "web_search"
|
|
523
568
|
: "web_fetch",
|