@askexenow/exe-os 0.9.365 → 0.9.368
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/deploy/compose/.env.askexe-control-plane.example +3 -1
- package/deploy/compose/.env.customer.example +6 -2
- package/deploy/compose/.env.example +8 -2
- package/deploy/compose/docker-compose.yml +21 -2
- package/deploy/compose/generate-env.ts +21 -1
- package/dist/.dist-verified.json +3 -3
- package/dist/{active-agent-MGF7J3HB.js → active-agent-6WNC756A.js} +3 -3
- package/dist/{active-agent-C6DPH43L.js → active-agent-RDTJGZHP.js} +3 -3
- package/dist/{agent-defs-generator-X7TVMPVB.js → agent-defs-generator-M5AUL3WM.js} +2 -2
- package/dist/agent-heartbeat-CQPGJIFF.js +13 -0
- package/dist/{agent-loop-E7RZCFDB.js → agent-loop-FOK2IRZQ.js} +1 -1
- package/dist/{agentic-ontology-CARDCG37.js → agentic-ontology-ZJBRYETW.js} +1 -1
- package/dist/{backfill-metadata-ANCJA6LA.js → backfill-metadata-Q4X23XLR.js} +5 -5
- package/dist/{backup-verify-F7BHVEF7.js → backup-verify-UKLX6IEK.js} +1 -1
- package/dist/behavior-injection-C3HEKSJY.js +60 -0
- package/dist/{behaviors-R2IE3PEN.js → behaviors-UCMAREU3.js} +8 -6
- package/dist/bin/agentic-ontology-backfill.js +6 -6
- package/dist/bin/agentic-reflection-backfill.js +7 -7
- package/dist/bin/agentic-semantic-label.js +6 -6
- package/dist/bin/backfill-conversations.js +5 -5
- package/dist/bin/backfill-responses.js +5 -5
- package/dist/bin/backfill-vectors.js +6 -6
- package/dist/bin/bulk-sync-postgres.js +10 -10
- package/dist/bin/cc-doctor.js +5 -5
- package/dist/bin/cleanup-stale-review-tasks.js +15 -14
- package/dist/bin/cli.js +20 -20
- package/dist/bin/deferred-daemon-restart.js +88 -83
- package/dist/bin/exe-agent-config.js +2 -2
- package/dist/bin/exe-agent.js +252 -14
- package/dist/bin/exe-assign.js +6 -6
- package/dist/bin/exe-boot.js +33 -31
- package/dist/bin/exe-call.js +4 -4
- package/dist/bin/exe-cloud.js +11 -11
- package/dist/bin/exe-config-dump.js +2 -2
- package/dist/bin/exe-dispatch.js +16 -15
- package/dist/bin/exe-doctor.js +6 -6
- package/dist/bin/exe-export-behaviors.js +10 -8
- package/dist/bin/exe-forget.js +7 -7
- package/dist/bin/exe-gateway.js +7 -7
- package/dist/bin/exe-healthcheck.js +5 -5
- package/dist/bin/exe-heartbeat.js +18 -17
- package/dist/bin/exe-kill.js +19 -18
- package/dist/bin/exe-launch-agent.js +25 -23
- package/dist/bin/exe-mcp.js +3 -3
- package/dist/bin/exe-memory-reads.js +5 -5
- package/dist/bin/exe-new-employee.js +8 -8
- package/dist/bin/exe-os-mcp-proxy.js +3 -3
- package/dist/bin/exe-pending-messages.js +16 -15
- package/dist/bin/exe-pending-notifications.js +15 -14
- package/dist/bin/exe-pending-reviews.js +15 -14
- package/dist/bin/exe-rename.js +4 -4
- package/dist/bin/exe-review.js +18 -17
- package/dist/bin/exe-search.js +6 -6
- package/dist/bin/exe-session-cleanup.js +20 -18
- package/dist/bin/exe-settings.js +10 -10
- package/dist/bin/exe-start-codex.js +81 -19
- package/dist/bin/exe-start-opencode.js +11 -9
- package/dist/bin/exe-status.js +17 -16
- package/dist/bin/exe-support.js +3 -3
- package/dist/bin/exe-team.js +4 -4
- package/dist/bin/exe-verify-running-images.js +123 -4
- package/dist/bin/exe-watchdog.js +44 -3
- package/dist/bin/git-sweep.js +25 -15
- package/dist/bin/graph-backfill.js +7 -7
- package/dist/bin/graph-export.js +6 -6
- package/dist/bin/import-history.js +10 -10
- package/dist/bin/install.js +90 -85
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +4 -4
- package/dist/bin/postgres-agentic-reflection-backfill.js +4 -4
- package/dist/bin/postgres-agentic-semantic-backfill.js +4 -4
- package/dist/bin/reconcile-backlog.js +47 -6
- package/dist/bin/registry-proxy.js +1 -1
- package/dist/bin/scan-tasks.js +15 -14
- package/dist/bin/setup.js +1 -1
- package/dist/bin/shard-migrate.js +5 -5
- package/dist/bin/stack-update.js +35 -6
- package/dist/bin/verify-stack.js +11 -1
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/{boot-generation-X45BSVZY.js → boot-generation-7H7Y4KC2.js} +3 -3
- package/dist/{boot-review-sections-OBVRXXSF.js → boot-review-sections-4AGCECCP.js} +14 -13
- package/dist/build-manifest.json +910 -845
- package/dist/{capability-cards-57FURUMR.js → capability-cards-6KAC5D2Z.js} +2 -2
- package/dist/{capacity-monitor-QEL62JDO.js → capacity-monitor-J2Y4SFLA.js} +16 -15
- package/dist/{catchup-brief-PMXTCASA.js → catchup-brief-F2HKF2CU.js} +19 -18
- package/dist/{chunk-5CBGH6RA.js → chunk-2AS6FG6C.js} +3 -3
- package/dist/{chunk-TO6TB75E.js → chunk-2UBMXN4D.js} +2 -2
- package/dist/{chunk-J6I7X272.js → chunk-2UGU3V63.js} +1 -1
- package/dist/{chunk-45EQTS7B.js → chunk-34BMZTWV.js} +1 -1
- package/dist/{chunk-JYFYIGYK.js → chunk-4DGIOK6T.js} +1 -1
- package/dist/{chunk-T6S45OLV.js → chunk-4GVJIMMK.js} +12 -6
- package/dist/{chunk-IXEFO6HD.js → chunk-4L732DE5.js} +3 -3
- package/dist/{chunk-MXEIZUXG.js → chunk-4RRMZJLG.js} +1 -1
- package/dist/{chunk-3JNVB5LG.js → chunk-5IVLOOJR.js} +1 -1
- package/dist/chunk-5YKNEL3W.js +356 -0
- package/dist/{chunk-EMZHB767.js → chunk-6EXOW5ZA.js} +9 -9
- package/dist/{chunk-6Q263OZE.js → chunk-6P7DVFKA.js} +1 -1
- package/dist/{chunk-ZDUO6QBH.js → chunk-6UZ3DEQI.js} +1 -1
- package/dist/{chunk-DJK45U7B.js → chunk-72JZQ7EV.js} +1 -1
- package/dist/{chunk-22YQBVMO.js → chunk-72QUZX6J.js} +4 -4
- package/dist/{chunk-DYWGIPVP.js → chunk-AAL6CDMQ.js} +7 -7
- package/dist/{chunk-E6ORBQHP.js → chunk-AAMGHW5W.js} +1 -0
- package/dist/{chunk-EJ4522YM.js → chunk-AJGX4Z34.js} +1 -1
- package/dist/{chunk-M7EES2KM.js → chunk-BEPO36MW.js} +3 -3
- package/dist/{chunk-WR75WUEP.js → chunk-BFL3UB77.js} +1 -1
- package/dist/{chunk-NV6A5HDN.js → chunk-BFPQXPN3.js} +1 -1
- package/dist/{chunk-VGE6IHZB.js → chunk-BJKC6ZJU.js} +110 -86
- package/dist/{chunk-R7RM766N.js → chunk-BLNSUBP3.js} +3 -3
- package/dist/{chunk-52TIQJEQ.js → chunk-BNDHQGOY.js} +1 -1
- package/dist/{chunk-QYJANQWC.js → chunk-BPQWRR4H.js} +2 -2
- package/dist/{chunk-ANPE3TT3.js → chunk-BTGR55GX.js} +3 -3
- package/dist/chunk-BTSWFMEH.js +14 -0
- package/dist/{chunk-OPNROU5B.js → chunk-C4IJ5IS5.js} +1 -1
- package/dist/{chunk-BEHLIRRJ.js → chunk-C5FOA5GO.js} +14 -3
- package/dist/{chunk-EHHMNKOA.js → chunk-CSBD7QLZ.js} +1 -1
- package/dist/{chunk-EKVTRI3N.js → chunk-CU2OUUSV.js} +27 -6
- package/dist/{chunk-P47MPWNU.js → chunk-CXHRNESJ.js} +1 -1
- package/dist/{chunk-F2S3M5MB.js → chunk-DRMGPZSC.js} +2 -2
- package/dist/{chunk-KRUYQFSH.js → chunk-DYPKSVB7.js} +5 -5
- package/dist/{chunk-KSVLBATT.js → chunk-E5QQZDQN.js} +53 -0
- package/dist/{chunk-ODBRU6BF.js → chunk-EDB3LXBQ.js} +1542 -984
- package/dist/{chunk-IIZITKBV.js → chunk-EDRXCUEP.js} +4 -4
- package/dist/{chunk-4QKKLK3C.js → chunk-ELY5WBZX.js} +10 -10
- package/dist/{chunk-MPQXQ5IE.js → chunk-EZUSIF66.js} +1 -1
- package/dist/{chunk-DEFSN2FQ.js → chunk-FHYX64H3.js} +3 -3
- package/dist/{chunk-YMJOLEPE.js → chunk-FSALI4B7.js} +4 -4
- package/dist/{chunk-6GQYPJPG.js → chunk-FWKTZURC.js} +8 -8
- package/dist/{chunk-EWZYFG5Q.js → chunk-FWVPGXHD.js} +5 -5
- package/dist/{chunk-DWAQOEXL.js → chunk-GILYOIMP.js} +2 -2
- package/dist/{chunk-RZIKSE6N.js → chunk-GP3J3AOT.js} +4 -4
- package/dist/{chunk-LHOKWZKL.js → chunk-H6J7N3BZ.js} +1 -1
- package/dist/{chunk-EVPBYX2Z.js → chunk-HQSUXAB4.js} +1 -1
- package/dist/{chunk-IM2I7OOS.js → chunk-HTLJHSN4.js} +1 -1
- package/dist/{chunk-JUOZLXLH.js → chunk-HXV3DGL7.js} +1 -1
- package/dist/{chunk-OFGFRT5J.js → chunk-IEE6X6R2.js} +1 -1
- package/dist/{chunk-SP37DONS.js → chunk-IKRIUEIF.js} +1 -1
- package/dist/{chunk-RHX6MNWY.js → chunk-J44774XC.js} +1 -1
- package/dist/{chunk-7C4FUNVO.js → chunk-J77ZIMH5.js} +5 -5
- package/dist/{chunk-NO3M2AFM.js → chunk-JDPV7W2L.js} +1 -1
- package/dist/{chunk-FXPAUDCZ.js → chunk-KGPWS4KE.js} +1 -1
- package/dist/{chunk-L3TB7CC3.js → chunk-KM6XSFHP.js} +12 -2
- package/dist/{chunk-ZEKCHV43.js → chunk-KWQ7RHYD.js} +4 -4
- package/dist/{chunk-QFIVK3G5.js → chunk-KYVIV54Y.js} +1 -1
- package/dist/chunk-KZXMP6JG.js +319 -0
- package/dist/{chunk-AGQAGOQN.js → chunk-LJWCK2DR.js} +9 -9
- package/dist/{chunk-O2MEBF23.js → chunk-MCXYNYZI.js} +30 -2
- package/dist/{chunk-L2VZBPJJ.js → chunk-MWEIBVBS.js} +13 -1
- package/dist/{chunk-RVWALVDT.js → chunk-MXP27XTP.js} +2 -2
- package/dist/{chunk-DQ5KHWFD.js → chunk-N3CGSO3S.js} +1 -1
- package/dist/{chunk-ZNEBZCZR.js → chunk-NNXPIJRB.js} +1 -1
- package/dist/{chunk-MZJBUAC3.js → chunk-NWE3CFX7.js} +4 -4
- package/dist/{chunk-BRLS5OLZ.js → chunk-OBESOWFJ.js} +35 -4
- package/dist/{chunk-5KLQCGI5.js → chunk-OL3QP3AU.js} +171 -1
- package/dist/{chunk-ESTR7QUP.js → chunk-P3PAD6AA.js} +1 -1
- package/dist/{chunk-2FYIMTQE.js → chunk-PGF5I7EV.js} +2 -2
- package/dist/{agent-heartbeat-I5UPGXAU.js → chunk-PHUHIVD5.js} +4 -5
- package/dist/{chunk-C3UAQ3JG.js → chunk-PVWM2WMM.js} +1 -1
- package/dist/{chunk-EWCEUO65.js → chunk-QCSAYYL6.js} +1 -1
- package/dist/{chunk-SBAU735L.js → chunk-QE5KWKVU.js} +27 -6
- package/dist/{chunk-LZKYVMBY.js → chunk-QKZEUCTS.js} +2 -2
- package/dist/{chunk-POPRJKAY.js → chunk-QS6HI4B6.js} +6 -0
- package/dist/{chunk-JNVQGLPX.js → chunk-QT6CNCXO.js} +3 -3
- package/dist/{chunk-J4U5Z7VX.js → chunk-QZYYCPNL.js} +4 -4
- package/dist/{chunk-RD4E5G3B.js → chunk-RDIZSXXD.js} +1 -1
- package/dist/{chunk-2RQT7TED.js → chunk-RFWOXKVL.js} +55 -3
- package/dist/chunk-S2YTU74T.js +76 -0
- package/dist/{chunk-X6A2VWVJ.js → chunk-TP7BFVQP.js} +2 -2
- package/dist/{chunk-CKG6CVKI.js → chunk-TTJWPV4G.js} +1 -1
- package/dist/chunk-TX3Q2GIL.js +97 -0
- package/dist/{chunk-Q7BU5Q6I.js → chunk-UATT6BNO.js} +3 -3
- package/dist/{chunk-PPGPCWRC.js → chunk-UVM5ZXO2.js} +4 -4
- package/dist/{chunk-BATQKSLI.js → chunk-V7E37GE3.js} +2 -2
- package/dist/{chunk-U373MEF5.js → chunk-VD3CVNGB.js} +3 -3
- package/dist/{chunk-ZSZPMUNX.js → chunk-VIW62NN5.js} +126 -7
- package/dist/{chunk-EPNWEOOE.js → chunk-VTOO5UB3.js} +10 -10
- package/dist/chunk-W5MCOZTW.js +304 -0
- package/dist/{chunk-2ESB5SDP.js → chunk-WJOJWRN5.js} +139 -33
- package/dist/{chunk-CPILYY2K.js → chunk-X4MRVNR3.js} +1 -1
- package/dist/{chunk-EPDNWY5P.js → chunk-XBTQPQN7.js} +1 -1
- package/dist/{behavior-injection-XQ4B7DCF.js → chunk-XOTDAKJL.js} +24 -38
- package/dist/{chunk-ORNCMRIX.js → chunk-Y4AYNLXU.js} +31 -37
- package/dist/{chunk-WYLFDSIE.js → chunk-YGPJ7VSJ.js} +48 -10
- package/dist/{chunk-ZRKEUCUZ.js → chunk-ZR3VMM3X.js} +12 -10
- package/dist/{chunk-JITNFE4W.js → chunk-ZWONQU5S.js} +1 -1
- package/dist/{cleanup-graph-garbage-CAA625RJ.js → cleanup-graph-garbage-FBSQI33K.js} +8 -8
- package/dist/{cloud-sync-command-DBB7WRHL.js → cloud-sync-command-NHGVDTLM.js} +11 -3
- package/dist/{cloud-sync-db-init-V7IB23W5.js → cloud-sync-db-init-I75VOTXC.js} +1 -1
- package/dist/{cloud-sync-shutdown-2D3B73CJ.js → cloud-sync-shutdown-JGOFGGET.js} +2 -2
- package/dist/{cloud-sync-state-5DFKLWNB.js → cloud-sync-state-QF3TMMJ4.js} +3 -1
- package/dist/{co-activation-JVN7EBS6.js → co-activation-AE5L2SJV.js} +2 -2
- package/dist/{co-occurrence-526PTFGT.js → co-occurrence-O65D4SCN.js} +6 -6
- package/dist/codex-consolidation-PPXNBXCV.js +96 -0
- package/dist/{conversation-entity-extractor-JO56DB2E.js → conversation-entity-extractor-LFIDTD2O.js} +4 -4
- package/dist/{crdt-sync-LIJLZKFE.js → crdt-sync-NRWDBRSE.js} +1 -1
- package/dist/{crm-webhook-55F7Y6D2.js → crm-webhook-XOQGX6DV.js} +2 -2
- package/dist/{cto-delegation-gate-QIYV4KFO.js → cto-delegation-gate-ZGOAXQI2.js} +14 -13
- package/dist/{daemon-orchestration-Q3GJA2JJ.js → daemon-orchestration-ZMQWYYDT.js} +19 -18
- package/dist/dispatch-intent-journal-VV6HMZC4.js +17 -0
- package/dist/{doc-graph-extractor-P46R4QME.js → doc-graph-extractor-6C5JBKPP.js} +6 -6
- package/dist/{documents-7KFEREWO.js → documents-FKSQGSO4.js} +6 -6
- package/dist/{dreaming-JMUXBAPU.js → dreaming-IB3H6NDZ.js} +18 -17
- package/dist/{employee-boot-brief-HN63D2BY.js → employee-boot-brief-5YRTUEJH.js} +25 -21
- package/dist/{exe-drift-7J7GX7DP.js → exe-drift-CUWUYX3O.js} +3 -3
- package/dist/{exe-export-KJ7B2OBU.js → exe-export-XWENYJNM.js} +7 -7
- package/dist/{exe-import-HPZDWKGE.js → exe-import-OWOMRF2S.js} +7 -7
- package/dist/{exe-key-2PREP464.js → exe-key-P356FGK5.js} +88 -83
- package/dist/{exe-org-VEIISATF.js → exe-org-UKIVF3KE.js} +8 -8
- package/dist/{exe-snapshot-JXQFLUKA.js → exe-snapshot-AZI2WW5Y.js} +19 -18
- package/dist/{fast-db-init-SCXJXOYX.js → fast-db-init-FPAPF3GB.js} +1 -1
- package/dist/{founder-context-U2SZPLYV.js → founder-context-QTQ6V3B5.js} +2 -2
- package/dist/gateway/index.js +11 -11
- package/dist/{git-staleness-S4NDR7NX.js → git-staleness-6ACWLV5Q.js} +2 -2
- package/dist/{global-procedures-ZOFTOXIR.js → global-procedures-RXIKBVLZ.js} +3 -3
- package/dist/{graph-auto-extract-CLVTSUSB.js → graph-auto-extract-Q4A4QMOF.js} +6 -6
- package/dist/{graph-rag-LSJLWGXV.js → graph-rag-RLRQMY54.js} +4 -4
- package/dist/{hook-integrity-SGTKBL6W.js → hook-integrity-3X2JRLBM.js} +1 -1
- package/dist/{hook-prefetch-BDSLB6F4.js → hook-prefetch-DU44UZQP.js} +15 -14
- package/dist/hooks/bug-report-worker.js +19 -18
- package/dist/hooks/codex-stop-task-finalizer.js +20 -19
- package/dist/hooks/commit-complete.js +35 -19
- package/dist/hooks/error-recall.js +8 -8
- package/dist/hooks/exe-heartbeat-hook.js +4 -4
- package/dist/hooks/ingest-worker.js +2 -2
- package/dist/hooks/ingest.js +11 -11
- package/dist/hooks/instructions-loaded.js +5 -5
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +5 -5
- package/dist/hooks/post-compact.js +4 -4
- package/dist/hooks/post-tool-combined.js +12 -12
- package/dist/hooks/pre-compact.js +18 -17
- package/dist/hooks/pre-tool-use.js +86 -34
- package/dist/hooks/prompt-submit.js +36 -31
- package/dist/hooks/session-end.js +114 -100
- package/dist/hooks/session-start.js +16 -16
- package/dist/hooks/stop.js +83 -20
- package/dist/hooks/subagent-stop.js +19 -18
- package/dist/hooks/summary-worker.js +23 -22
- package/dist/index.js +27 -26
- package/dist/{installer-RC2JCKSE.js → installer-B7QYQE56.js} +8 -6
- package/dist/{installer-EA7T3PBD.js → installer-EXR25DDG.js} +6 -6
- package/dist/{installer-KCEM4RCG.js → installer-TOPA7673.js} +152 -8
- package/dist/{intercom-queue-6DZPHHQ2.js → intercom-queue-BZ4M3L4S.js} +14 -13
- package/dist/lib/cloud-sync.js +10 -10
- package/dist/lib/consolidation.js +8 -8
- package/dist/lib/database.js +2 -2
- package/dist/lib/db-backup.js +1 -1
- package/dist/lib/db-write-worker.js +3 -3
- package/dist/lib/db.js +2 -2
- package/dist/lib/delivery-truth.js +25 -0
- package/dist/lib/device-registry.js +1 -1
- package/dist/lib/employee-templates.js +4 -4
- package/dist/lib/employees.js +2 -2
- package/dist/lib/exe-daemon.js +185 -79
- package/dist/lib/hybrid-search.js +6 -6
- package/dist/lib/identity.js +2 -2
- package/dist/lib/license.js +2 -2
- package/dist/lib/messaging.js +15 -14
- package/dist/lib/registry-proxy.js +1 -1
- package/dist/lib/reminders.js +3 -3
- package/dist/lib/schedules.js +6 -6
- package/dist/lib/session-registry.js +4 -4
- package/dist/lib/skill-learning.js +7 -7
- package/dist/lib/status-brief.js +2 -1
- package/dist/lib/store.js +5 -5
- package/dist/lib/task-router.js +3 -3
- package/dist/lib/tasks.js +16 -15
- package/dist/lib/tmux-routing.js +14 -13
- package/dist/lib/token-spend.js +3 -3
- package/dist/{license-gate-HMSMUIAU.js → license-gate-YTIOLKVV.js} +3 -3
- package/dist/{license-sync-FBCMPC4J.js → license-sync-5VE5OSTV.js} +2 -2
- package/dist/mcp/register-tools.js +87 -82
- package/dist/mcp/server.js +90 -85
- package/dist/mcp/tools/complete-reminder.js +4 -4
- package/dist/mcp/tools/create-reminder.js +4 -4
- package/dist/mcp/tools/create-task.js +26 -23
- package/dist/mcp/tools/deactivate-behavior.js +8 -8
- package/dist/mcp/tools/list-reminders.js +4 -4
- package/dist/mcp/tools/list-tasks.js +18 -17
- package/dist/mcp/tools/send-message.js +17 -16
- package/dist/mcp/tools/update-task.js +17 -16
- package/dist/{mcp-http-config-YKJN52HG.js → mcp-http-config-XUNRIGQH.js} +3 -3
- package/dist/{mcp-session-identity-QLUVYWPR.js → mcp-session-identity-4UIG7KLK.js} +14 -13
- package/dist/{memory-cards-K2OSX4AW.js → memory-cards-R74YU4CO.js} +5 -5
- package/dist/{memory-graph-extractor-YLTSKLSY.js → memory-graph-extractor-3B4QJUXI.js} +7 -7
- package/dist/{memory-poisoning-defense-IPO4ADRL.js → memory-poisoning-defense-OAKFL5O2.js} +2 -2
- package/dist/{memory-pressure-watchdog-ZI3TH2OF.js → memory-pressure-watchdog-FFC2CHFJ.js} +15 -14
- package/dist/{memory-reflection-ZKVRU3NT.js → memory-reflection-5IJ6RE2J.js} +2 -2
- package/dist/{notification-ledger-4REL6M3T.js → notification-ledger-P5XBUYKO.js} +17 -15
- package/dist/{notifications-UXJUAP3C.js → notifications-LLCCHRYV.js} +14 -13
- package/dist/{orchestration-events-GMRGGBMN.js → orchestration-events-VBGCIQSS.js} +3 -3
- package/dist/{orchestrator-5TV75HDJ.js → orchestrator-EB3SCTAJ.js} +16 -15
- package/dist/{org-brief-session-7AZZEO3F.js → org-brief-session-GDCDKBFF.js} +6 -6
- package/dist/{org-consent-policy-XT6UZENB.js → org-consent-policy-HCD42NBN.js} +2 -2
- package/dist/{org-partner-runtime-WLZAZJIY.js → org-partner-runtime-TPVKFR6E.js} +6 -6
- package/dist/{org-row-visibility-A5XM4MVO.js → org-row-visibility-ZZLOPZLH.js} +1 -1
- package/dist/{pipeline-router-UEVXDUHR.js → pipeline-router-3JTL2KF6.js} +3 -3
- package/dist/{plan-limits-QEP32X4W.js → plan-limits-MTHRP4WY.js} +5 -5
- package/dist/{projection-worker-GMRC6SBH.js → projection-worker-FLASNERC.js} +2 -2
- package/dist/{prospective-memory-QLHSAPSG.js → prospective-memory-HI3WUY4U.js} +2 -2
- package/dist/{push-notifications-GKRPXOGI.js → push-notifications-DFSR6P7V.js} +15 -14
- package/dist/{reranker-GB4VEMUV.js → reranker-XHBKUDGG.js} +1 -1
- package/dist/{retrieval-health-QIBPBGN6.js → retrieval-health-NYKSDS6M.js} +1 -1
- package/dist/{review-polling-MU47NQ2N.js → review-polling-UAV6DZIZ.js} +15 -14
- package/dist/runtime/index.js +23 -22
- package/dist/{session-events-YMQ3VGBJ.js → session-events-YCYPLWPG.js} +15 -14
- package/dist/{session-kill-telemetry-VGPKE57M.js → session-kill-telemetry-UEJTHL65.js} +15 -14
- package/dist/{session-scope-P46KAHXQ.js → session-scope-LXDW7LJJ.js} +14 -13
- package/dist/{setup-wizard-BRNHSJ4U.js → setup-wizard-OVJQYUUL.js} +1 -1
- package/dist/{skill-refinement-NLYDSFEH.js → skill-refinement-EWRJID73.js} +3 -3
- package/dist/{stack-promote-NHFTNIM2.js → stack-promote-4IJM36OG.js} +5 -4
- package/dist/{stack-release-AQVKZUS7.js → stack-release-BAIRY65H.js} +5 -4
- package/dist/{stack-update-LLX5KT7G.js → stack-update-VDM5WXRS.js} +10 -3
- package/dist/stalled-dispatch-escalation-MHLYH2PT.js +80 -0
- package/dist/{steward-gate-JKHYFAHA.js → steward-gate-Y4N2XY3R.js} +3 -3
- package/dist/{subagent-brief-injection-VDVOHDOU.js → subagent-brief-injection-7A6JEVTP.js} +22 -20
- package/dist/{support-inbox-S6YO5YZU.js → support-inbox-LT4WJECQ.js} +4 -3
- package/dist/{task-enforcement-LXW45H5Z.js → task-enforcement-WOIZ5TLK.js} +15 -14
- package/dist/{task-request-inbox-UCSKDC3R.js → task-request-inbox-D65BPUKZ.js} +2 -2
- package/dist/{task-scope-GDLFE26E.js → task-scope-PQ67YRWP.js} +18 -16
- package/dist/{tasks-crud-W7VGWRUV.js → tasks-crud-TJNMUKKH.js} +14 -13
- package/dist/{tasks-notify-CT7NWCS4.js → tasks-notify-7UVC3VGI.js} +15 -14
- package/dist/{tasks-review-WCSKOUFW.js → tasks-review-WDWYISZ2.js} +14 -13
- package/dist/{telemetry-upload-FK5WKXVB.js → telemetry-upload-6LBGRJUE.js} +7 -7
- package/dist/{token-budget-GBNGSIU3.js → token-budget-XO5XW6DL.js} +3 -3
- package/dist/{tool-gates-3IC7DK4R.js → tool-gates-2OZY3GZM.js} +1 -1
- package/dist/{tool-gates-GXSYBVK4.js → tool-gates-7PLIOLAL.js} +1 -1
- package/dist/{tool-telemetry-VKMRS6MP.js → tool-telemetry-ZL6TTZWG.js} +1 -1
- package/dist/tui/App.js +23 -22
- package/dist/{tui-data-FTPV2XBQ.js → tui-data-UK7ZPKN4.js} +14 -13
- package/dist/{update-support-J6UWPUOC.js → update-support-BGL5KAZO.js} +12 -12
- package/dist/work-claims-XZL2DKQ3.js +53 -0
- package/dist/{work-state-heartbeat-4LDF6DSM.js → work-state-heartbeat-267YQ75U.js} +1 -1
- package/dist/{worker-gate-35VZINZG.js → worker-gate-RUM6MLIR.js} +1 -1
- package/dist/{workflow-engine-4DA6RSHI.js → workflow-engine-YQHGHKSJ.js} +2 -2
- package/dist/{worktree-H3YFJ3NU.js → worktree-3FO6EQ4G.js} +4 -4
- package/dist/{worktree-sweep-4EDLLQ2E.js → worktree-sweep-X7MUEEQS.js} +5 -5
- package/package.json +7 -2
- package/release-notes.json +93 -81
- /package/dist/{chunk-7Y6AQWVT.js → chunk-4AN2PWUK.js} +0 -0
- /package/dist/{chunk-7DMCAGSC.js → chunk-5U4UJGTW.js} +0 -0
- /package/dist/{chunk-3THNS2T7.js → chunk-EYIX6JU7.js} +0 -0
- /package/dist/{chunk-QYECRPGD.js → chunk-FDA45THL.js} +0 -0
- /package/dist/{chunk-MBBFL2SP.js → chunk-GIO4VU4J.js} +0 -0
- /package/dist/{chunk-LKYGSJ2E.js → chunk-I76LRCNA.js} +0 -0
- /package/dist/{chunk-UY6HRDB2.js → chunk-LBWEAQ6Z.js} +0 -0
- /package/dist/{chunk-VS4LPG66.js → chunk-MQ5RUHNZ.js} +0 -0
- /package/dist/{chunk-G2EAYH4U.js → chunk-PFCE4AXQ.js} +0 -0
- /package/dist/{chunk-3NBWARKC.js → chunk-SXAERZL2.js} +0 -0
- /package/dist/{chunk-BY7WWPRM.js → chunk-TKTQRSSD.js} +0 -0
- /package/dist/{chunk-JRPYLUXH.js → chunk-U2AZUMBZ.js} +0 -0
- /package/dist/{chunk-CMBF5WCL.js → chunk-W6FVADZS.js} +0 -0
- /package/dist/{core-memory-CMPPHJN5.js → core-memory-W5ZHHBRR.js} +0 -0
- /package/dist/{memory-isolation-ZB5S5HCO.js → memory-isolation-ZE7EDBO4.js} +0 -0
- /package/dist/{oauth-server-NP7KGF7N.js → oauth-server-3HG62YYJ.js} +0 -0
- /package/dist/{project-boot-LEZSK3W7.js → project-boot-3OAWKYLO.js} +0 -0
- /package/dist/{wiki-acl-5DKOWOIH.js → wiki-acl-FQV4E6M4.js} +0 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
// src/lib/delivery-truth.ts
|
|
2
|
+
var DIGEST_RE = /@(sha256:[0-9a-f]{64})\b/i;
|
|
3
|
+
function parseDigest(ref) {
|
|
4
|
+
const m = DIGEST_RE.exec(ref ?? "");
|
|
5
|
+
return m?.[1] ? m[1].toLowerCase() : null;
|
|
6
|
+
}
|
|
7
|
+
function repositoryKey(ref) {
|
|
8
|
+
const withoutDigest = (ref ?? "").split("@")[0] ?? "";
|
|
9
|
+
const withoutTag = withoutDigest.replace(/:[^/:]+$/, "");
|
|
10
|
+
const segments = withoutTag.split("/").filter(Boolean);
|
|
11
|
+
return segments[segments.length - 1] ?? withoutTag;
|
|
12
|
+
}
|
|
13
|
+
function compareLiveArtifacts(running, declared, options) {
|
|
14
|
+
const declaredByDigest = /* @__PURE__ */ new Map();
|
|
15
|
+
const declaredByRepo = /* @__PURE__ */ new Map();
|
|
16
|
+
for (const d of declared) {
|
|
17
|
+
if (d.digest) declaredByDigest.set(d.digest.toLowerCase(), d);
|
|
18
|
+
declaredByRepo.set(repositoryKey(d.ref), d);
|
|
19
|
+
}
|
|
20
|
+
const entries = [];
|
|
21
|
+
const matchedDeclared = /* @__PURE__ */ new Set();
|
|
22
|
+
for (const r of running) {
|
|
23
|
+
const digest = r.digest ?? parseDigest(r.ref);
|
|
24
|
+
const repo = repositoryKey(r.ref);
|
|
25
|
+
const runningSide = { ref: r.ref, digest, containers: r.containers };
|
|
26
|
+
if (digest && declaredByDigest.has(digest)) {
|
|
27
|
+
const d = declaredByDigest.get(digest);
|
|
28
|
+
matchedDeclared.add(d.service);
|
|
29
|
+
entries.push({
|
|
30
|
+
service: d.service,
|
|
31
|
+
verdict: "agrees",
|
|
32
|
+
channel: d.channel,
|
|
33
|
+
running: runningSide,
|
|
34
|
+
declared: { ref: d.ref, digest: d.digest },
|
|
35
|
+
detail: `running digest is the digest the signed manifest pins`
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const byRepo = declaredByRepo.get(repo);
|
|
40
|
+
if (byRepo) {
|
|
41
|
+
matchedDeclared.add(byRepo.service);
|
|
42
|
+
if (!digest) {
|
|
43
|
+
entries.push({
|
|
44
|
+
service: byRepo.service,
|
|
45
|
+
verdict: "unknown-provenance",
|
|
46
|
+
channel: byRepo.channel,
|
|
47
|
+
running: runningSide,
|
|
48
|
+
declared: { ref: byRepo.ref, digest: byRepo.digest },
|
|
49
|
+
detail: `running ref "${r.ref}" carries no resolvable digest, so what is running cannot be traced to any published artifact \u2014 it cannot be shown to match or to differ from the manifest pin`
|
|
50
|
+
});
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
entries.push({
|
|
54
|
+
service: byRepo.service,
|
|
55
|
+
verdict: "disagrees",
|
|
56
|
+
channel: byRepo.channel,
|
|
57
|
+
running: runningSide,
|
|
58
|
+
declared: { ref: byRepo.ref, digest: byRepo.digest },
|
|
59
|
+
detail: `running ${digest} but the signed manifest pins ${byRepo.digest ?? "(no digest)"} \u2014 production is not the artifact we signed`
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!digest) {
|
|
64
|
+
entries.push({
|
|
65
|
+
service: repo,
|
|
66
|
+
verdict: "unknown-provenance",
|
|
67
|
+
channel: "signed-manifest",
|
|
68
|
+
running: runningSide,
|
|
69
|
+
detail: `running ref "${r.ref}" carries no resolvable digest and matches no declared repository \u2014 provenance unknown`
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
entries.push({
|
|
74
|
+
service: repo,
|
|
75
|
+
verdict: "undeclared",
|
|
76
|
+
channel: "signed-manifest",
|
|
77
|
+
running: runningSide,
|
|
78
|
+
detail: `running ${digest} under repository "${repo}", which the signed manifest does not declare at all \u2014 this artifact is outside the release contract`
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (options?.reportNotRunning) {
|
|
82
|
+
for (const d of declared) {
|
|
83
|
+
if (matchedDeclared.has(d.service)) continue;
|
|
84
|
+
entries.push({
|
|
85
|
+
service: d.service,
|
|
86
|
+
verdict: "not-running",
|
|
87
|
+
channel: d.channel,
|
|
88
|
+
declared: { ref: d.ref, digest: d.digest },
|
|
89
|
+
detail: `declared and pinned, but no running artifact in the inspected inventory carries this digest or repository`
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const counts = {
|
|
94
|
+
agrees: 0,
|
|
95
|
+
disagrees: 0,
|
|
96
|
+
undeclared: 0,
|
|
97
|
+
"unknown-provenance": 0,
|
|
98
|
+
"not-running": 0
|
|
99
|
+
};
|
|
100
|
+
for (const e of entries) counts[e.verdict]++;
|
|
101
|
+
return {
|
|
102
|
+
entries,
|
|
103
|
+
findings: entries.filter((e) => e.verdict !== "agrees"),
|
|
104
|
+
counts,
|
|
105
|
+
inventory: {
|
|
106
|
+
runningArtifacts: running.length,
|
|
107
|
+
declaredArtifacts: declared.length,
|
|
108
|
+
source: options?.source ?? "unspecified"
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function declaredArtifactsFromManifest(manifest, options) {
|
|
113
|
+
const m = manifest;
|
|
114
|
+
if (!m || typeof m !== "object" || !m.stacks) {
|
|
115
|
+
throw new Error("manifest has no `stacks` object");
|
|
116
|
+
}
|
|
117
|
+
const version = options?.stackVersion ?? m.latest;
|
|
118
|
+
if (!version) throw new Error("manifest has no `latest` and no stack version was given");
|
|
119
|
+
const stack = m.stacks[version];
|
|
120
|
+
if (!stack?.services) throw new Error(`manifest stack "${version}" is missing or has no services`);
|
|
121
|
+
const out = [];
|
|
122
|
+
for (const [service, svc] of Object.entries(stack.services)) {
|
|
123
|
+
const ref = typeof svc?.image === "string" ? svc.image : "";
|
|
124
|
+
if (!ref) continue;
|
|
125
|
+
out.push({ service, ref, digest: parseDigest(ref), channel: "signed-manifest" });
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
function evaluateDeliveryChannels(input) {
|
|
130
|
+
const { detected, registry, npmFiles } = input;
|
|
131
|
+
const normalizedFiles = npmFiles.map((f) => f.replace(/^\.\//, "").replace(/\/+$/, ""));
|
|
132
|
+
const covered = (p) => {
|
|
133
|
+
const path = p.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
134
|
+
return normalizedFiles.some((f) => f === path || path.startsWith(`${f}/`));
|
|
135
|
+
};
|
|
136
|
+
const out = [];
|
|
137
|
+
for (const d of detected) {
|
|
138
|
+
const channel = registry[d.path] ?? null;
|
|
139
|
+
if (!channel) {
|
|
140
|
+
out.push({
|
|
141
|
+
path: d.path,
|
|
142
|
+
channel: null,
|
|
143
|
+
verdict: "unclassified",
|
|
144
|
+
detail: `${d.path} is deployable (${d.evidence}) but declares no delivery channel. Nothing can say whether a change here reaches a customer.`
|
|
145
|
+
});
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (channel === "no-release-path") {
|
|
149
|
+
out.push({
|
|
150
|
+
path: d.path,
|
|
151
|
+
channel,
|
|
152
|
+
verdict: "no-release-path",
|
|
153
|
+
detail: `${d.path} has NO delivery path. Merging here delivers nothing to anyone.`
|
|
154
|
+
});
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (channel === "not-shipped") {
|
|
158
|
+
out.push({
|
|
159
|
+
path: d.path,
|
|
160
|
+
channel,
|
|
161
|
+
verdict: "not-shipped",
|
|
162
|
+
detail: `${d.path} ships nowhere itself. A change here reaches a customer only once it is vendored into a consuming artifact AND that artifact is rebuilt.`
|
|
163
|
+
});
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (channel === "npm" && !covered(d.path)) {
|
|
167
|
+
out.push({
|
|
168
|
+
path: d.path,
|
|
169
|
+
channel,
|
|
170
|
+
verdict: "undelivered",
|
|
171
|
+
detail: `${d.path} declares the npm channel but is not covered by package.json \`files\`, so it is in the git tag and ABSENT from the published tarball. Tag ancestry is not proof of delivery.`
|
|
172
|
+
});
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
out.push({
|
|
176
|
+
path: d.path,
|
|
177
|
+
channel,
|
|
178
|
+
verdict: "delivered",
|
|
179
|
+
detail: `${d.path} ships via ${channel}`
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
var GATE_COOKIE_RE = /\bexe_[a-z0-9_]*token[a-z0-9_]*\b/gi;
|
|
185
|
+
function extractGateCookieNames(html) {
|
|
186
|
+
const found = /* @__PURE__ */ new Set();
|
|
187
|
+
for (const m of (html ?? "").matchAll(GATE_COOKIE_RE)) found.add(m[0].toLowerCase());
|
|
188
|
+
return [...found].sort();
|
|
189
|
+
}
|
|
190
|
+
function evaluateAnonymousGate(input) {
|
|
191
|
+
const { service, url, html, setterNames } = input;
|
|
192
|
+
const gateCookies = extractGateCookieNames(html);
|
|
193
|
+
if (gateCookies.length === 0) {
|
|
194
|
+
return {
|
|
195
|
+
service,
|
|
196
|
+
url,
|
|
197
|
+
status: "no-client-gate",
|
|
198
|
+
gateCookies,
|
|
199
|
+
detail: `no SSO-shaped cookie name in the served document \u2014 this product does not gate client-side (it may bridge server-side, which is correct)`
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const setters = new Set(setterNames.map((s) => s.toLowerCase()));
|
|
203
|
+
if (setters.size === 0) {
|
|
204
|
+
return {
|
|
205
|
+
service,
|
|
206
|
+
url,
|
|
207
|
+
status: "inconclusive",
|
|
208
|
+
gateCookies,
|
|
209
|
+
detail: `the auth origin exposed no cookie name, so there is nothing to compare against. The probe cannot answer the question \u2014 fix the probe or the auth surface. This is NOT a pass.`
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const unsatisfiable = gateCookies.filter((c) => !setters.has(c));
|
|
213
|
+
if (unsatisfiable.length === gateCookies.length) {
|
|
214
|
+
return {
|
|
215
|
+
service,
|
|
216
|
+
url,
|
|
217
|
+
status: "unsatisfiable",
|
|
218
|
+
gateCookies,
|
|
219
|
+
detail: `gates on ${unsatisfiable.join(", ")}, which NO origin in the live auth flow sets (auth hands out: ${[...setters].sort().join(", ")}). Every visitor bounces between this product and auth forever. The served page answers HTTP 200 with zero redirects because the loop is client-side, so a status-code check sees a healthy service.`
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
service,
|
|
224
|
+
url,
|
|
225
|
+
status: "satisfiable",
|
|
226
|
+
gateCookies,
|
|
227
|
+
detail: `gates on ${gateCookies.join(", ")}; the live auth flow sets a matching name`
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
231
|
+
var DEPARTMENT_RE = /^(the\s+)?(team|eng|engineering|ops|devops|sre|infra|platform|everyone|tbd|unknown|n\/?a)$/i;
|
|
232
|
+
function applyLivenessAcks(input) {
|
|
233
|
+
const { findingKeys, acks, now } = input;
|
|
234
|
+
const present = new Set(findingKeys);
|
|
235
|
+
const evaluations = [];
|
|
236
|
+
const suppressed = /* @__PURE__ */ new Set();
|
|
237
|
+
for (const ack of acks) {
|
|
238
|
+
const missing = [];
|
|
239
|
+
if (!ack?.key) missing.push("key");
|
|
240
|
+
const owner = (ack?.owner ?? "").trim();
|
|
241
|
+
if (owner.length < 2) missing.push("owner");
|
|
242
|
+
else if (DEPARTMENT_RE.test(owner)) missing.push("owner (a person, not a team)");
|
|
243
|
+
if (!ack?.bug) missing.push("bug");
|
|
244
|
+
if (!ack?.expires || !ISO_DATE_RE.test(ack.expires)) missing.push("expires (YYYY-MM-DD)");
|
|
245
|
+
if (missing.length > 0) {
|
|
246
|
+
evaluations.push({
|
|
247
|
+
ack,
|
|
248
|
+
state: "invalid",
|
|
249
|
+
detail: `ack for "${ack?.key ?? "(no key)"}" is missing ${missing.join(", ")} \u2014 it suppresses nothing. An ack needs a person who defends it and a tracked fix, or it is just a mute.`
|
|
250
|
+
});
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const expiry = /* @__PURE__ */ new Date(`${ack.expires}T23:59:59Z`);
|
|
254
|
+
if (Number.isNaN(expiry.getTime()) || expiry.getTime() < now.getTime()) {
|
|
255
|
+
evaluations.push({
|
|
256
|
+
ack,
|
|
257
|
+
state: "expired",
|
|
258
|
+
detail: `ack for "${ack.key}" expired on ${ack.expires} (owner: ${ack.owner}, bug: ${ack.bug}). The finding is failing again, and the lapsed ack is itself a failure. Fix it or re-ack with a new date and a reason.`
|
|
259
|
+
});
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (!present.has(ack.key)) {
|
|
263
|
+
evaluations.push({
|
|
264
|
+
ack,
|
|
265
|
+
state: "stale",
|
|
266
|
+
detail: `ack for "${ack.key}" (owner: ${ack.owner}) suppresses a finding that is no longer present. Delete it \u2014 a suppression list that only grows becomes a permanent allow-list.`
|
|
267
|
+
});
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
suppressed.add(ack.key);
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
failing: findingKeys.filter((k) => !suppressed.has(k)),
|
|
274
|
+
acknowledged: [...suppressed],
|
|
275
|
+
ackProblems: evaluations
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function findingKey(f) {
|
|
279
|
+
return `${f.service}:${f.verdict}`;
|
|
280
|
+
}
|
|
281
|
+
function deliveryStateOf(report) {
|
|
282
|
+
return report.entries.map((e) => ({
|
|
283
|
+
service: e.service,
|
|
284
|
+
channel: e.channel,
|
|
285
|
+
delivered: e.verdict === "agrees" ? true : e.verdict === "unknown-provenance" ? null : false,
|
|
286
|
+
liveIdentity: e.running?.digest ?? e.running?.ref ?? null,
|
|
287
|
+
declaredIdentity: e.declared?.digest ?? e.declared?.ref ?? null,
|
|
288
|
+
verdict: e.verdict,
|
|
289
|
+
detail: e.detail
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export {
|
|
294
|
+
parseDigest,
|
|
295
|
+
repositoryKey,
|
|
296
|
+
compareLiveArtifacts,
|
|
297
|
+
declaredArtifactsFromManifest,
|
|
298
|
+
evaluateDeliveryChannels,
|
|
299
|
+
extractGateCookieNames,
|
|
300
|
+
evaluateAnonymousGate,
|
|
301
|
+
applyLivenessAcks,
|
|
302
|
+
findingKey,
|
|
303
|
+
deliveryStateOf
|
|
304
|
+
};
|
|
@@ -5,6 +5,9 @@ import {
|
|
|
5
5
|
supportTaskIdSchema,
|
|
6
6
|
supportVersionSchema
|
|
7
7
|
} from "./chunk-5H47VHB7.js";
|
|
8
|
+
import {
|
|
9
|
+
buildVerificationArtifact
|
|
10
|
+
} from "./chunk-KZXMP6JG.js";
|
|
8
11
|
import {
|
|
9
12
|
SUPPORT_PRODUCTS,
|
|
10
13
|
sanitizeProductFilter,
|
|
@@ -14,16 +17,88 @@ import {
|
|
|
14
17
|
import {
|
|
15
18
|
loadLicense,
|
|
16
19
|
readCachedLicenseToken
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-6UZ3DEQI.js";
|
|
18
21
|
|
|
19
22
|
// src/mcp/tools/support-inbox.ts
|
|
20
|
-
import { z } from "zod";
|
|
23
|
+
import { z as z2 } from "zod";
|
|
21
24
|
import { readFileSync } from "fs";
|
|
22
25
|
import { join } from "path";
|
|
23
26
|
import { homedir } from "os";
|
|
27
|
+
|
|
28
|
+
// src/lib/support-verification-input.ts
|
|
29
|
+
import { z } from "zod";
|
|
30
|
+
function isVerifiedStatus(status) {
|
|
31
|
+
return status === "fixed" || status === "closed";
|
|
32
|
+
}
|
|
33
|
+
var verificationArtifactInputSchema = {
|
|
34
|
+
verification_kind: z.enum(["regression_test", "manual"]).optional().describe(
|
|
35
|
+
"REQUIRED to set status=fixed or closed. 'regression_test' when you actually RAN a test that fails at the parent commit and passes at the fix. 'manual' when a named person reproduced the original defect and confirmed it is gone."
|
|
36
|
+
),
|
|
37
|
+
fix_commit: supportCommitSchema.optional().describe("SHA of the merged commit containing the fix. Its diff is measured locally \u2014 a comment-only or test-only commit is refused."),
|
|
38
|
+
repo_path: z.string().optional().describe("Absolute path to the repository containing fix_commit. Required when the fix landed outside the current working repo (e.g. exe-gateway, exe-crm). Defaults to the current directory."),
|
|
39
|
+
regression_test_id: z.string().optional().describe("regression_test only: the test that detects the defect, e.g. 'tests/raw-event-backlog.test.ts::counts unprocessed events'."),
|
|
40
|
+
parent_result: z.enum(["fail", "pass", "error"]).optional().describe("regression_test only: the result you OBSERVED running that test at the parent commit. Must be 'fail' \u2014 a test that already passed does not detect the defect."),
|
|
41
|
+
fix_result: z.enum(["fail", "pass", "error"]).optional().describe("regression_test only: the result you OBSERVED running that test at the fix commit. Must be 'pass'."),
|
|
42
|
+
verifier: z.string().optional().describe("manual only: the identity of the person or employee who confirmed the defect is gone. Checked server-side against the bug's filer and assignee \u2014 it may not be either. Placeholders ('me', 'agent') are refused."),
|
|
43
|
+
verification_method: z.string().optional().describe("manual only: how it was verified, in enough detail for someone else to repeat it."),
|
|
44
|
+
verification_observation: z.string().optional().describe("manual only: what was observed that shows the DEFECT IS ABSENT \u2014 not what the change did. 'It is fixed' is refused."),
|
|
45
|
+
delivery_proof: z.string().optional().describe('Optional JSON delivery declaration, e.g. {"channel":"npm","version":"0.9.364","tarball_shasum":"\u2026","fix_path_published":true}. Recorded, not required \u2014 delivery does not gate closing. A declaration that is present must still be true.')
|
|
46
|
+
};
|
|
47
|
+
var NO_ARTIFACT_HELP = [
|
|
48
|
+
"Refused locally: setting status=fixed or closed requires evidence that the defect is ABSENT.",
|
|
49
|
+
"",
|
|
50
|
+
"Supply ONE of:",
|
|
51
|
+
" regression_test \u2014 verification_kind='regression_test', fix_commit, repo_path,",
|
|
52
|
+
" regression_test_id, parent_result (must be the result you observed at the parent),",
|
|
53
|
+
" fix_result. Use this when you actually ran the test at both commits.",
|
|
54
|
+
" manual \u2014 verification_kind='manual', fix_commit, repo_path, verifier (a real identity,",
|
|
55
|
+
" not the bug's filer or assignee), verification_method, verification_observation",
|
|
56
|
+
" describing what you saw that shows the defect is gone.",
|
|
57
|
+
"",
|
|
58
|
+
"The fix commit's diff is measured from the repository; substance is never taken from the caller.",
|
|
59
|
+
"If you have not verified the defect is absent, do not close it \u2014 record what you found with notes instead."
|
|
60
|
+
].join("\n");
|
|
61
|
+
function resolveVerificationArtifact(status, input, context = {}) {
|
|
62
|
+
if (!isVerifiedStatus(status)) return { ok: true };
|
|
63
|
+
if (!input.verification_kind && !input.fix_commit) {
|
|
64
|
+
return { ok: false, message: NO_ARTIFACT_HELP };
|
|
65
|
+
}
|
|
66
|
+
if (!input.verification_kind) {
|
|
67
|
+
return { ok: false, message: "verification_kind is required (regression_test or manual) when setting status=fixed or closed." };
|
|
68
|
+
}
|
|
69
|
+
if (!input.fix_commit) {
|
|
70
|
+
return { ok: false, message: "fix_commit is required when setting status=fixed or closed \u2014 the diff is measured, not described." };
|
|
71
|
+
}
|
|
72
|
+
const request = {
|
|
73
|
+
kind: input.verification_kind,
|
|
74
|
+
fix_commit: input.fix_commit,
|
|
75
|
+
repo_path: input.repo_path?.trim() || process.cwd(),
|
|
76
|
+
test_id: input.regression_test_id,
|
|
77
|
+
parent_result: input.parent_result,
|
|
78
|
+
fix_result: input.fix_result,
|
|
79
|
+
verifier: input.verifier,
|
|
80
|
+
method: input.verification_method,
|
|
81
|
+
observation: input.verification_observation
|
|
82
|
+
};
|
|
83
|
+
const built = buildVerificationArtifact(request, context);
|
|
84
|
+
if (!built.ok) {
|
|
85
|
+
return { ok: false, message: `Refused locally [${built.code}]: ${built.message}` };
|
|
86
|
+
}
|
|
87
|
+
return { ok: true, artifact: built.artifact };
|
|
88
|
+
}
|
|
89
|
+
function parseDeliveryProof(raw) {
|
|
90
|
+
if (raw === void 0 || !raw.trim()) return { ok: true };
|
|
91
|
+
try {
|
|
92
|
+
return { ok: true, value: JSON.parse(raw) };
|
|
93
|
+
} catch {
|
|
94
|
+
return { ok: false, message: "delivery_proof must be valid JSON (or omitted \u2014 delivery does not gate closing)." };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/mcp/tools/support-inbox.ts
|
|
24
99
|
var DEFAULT_ENDPOINT = "https://api.askexe.com/admin/support/bug-reports";
|
|
25
100
|
var DEFAULT_OWNER_ENDPOINT = "https://api.askexe.com/v1/support/bug-reports";
|
|
26
|
-
var STATUS =
|
|
101
|
+
var STATUS = z2.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
|
|
27
102
|
var SupportHttpError = class extends Error {
|
|
28
103
|
constructor(status, message) {
|
|
29
104
|
super(message);
|
|
@@ -158,13 +233,13 @@ function registerListBugReports(server) {
|
|
|
158
233
|
title: "List Bug Reports",
|
|
159
234
|
description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
|
|
160
235
|
inputSchema: {
|
|
161
|
-
status:
|
|
162
|
-
severity:
|
|
236
|
+
status: z2.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
|
|
237
|
+
severity: z2.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
163
238
|
// Round 8: constrain to the known enum at the schema — a `product` filter is
|
|
164
239
|
// NOT free text, and it was sent raw as a query param.
|
|
165
|
-
product:
|
|
166
|
-
limit:
|
|
167
|
-
offset:
|
|
240
|
+
product: z2.enum(SUPPORT_PRODUCTS).optional().describe("Filter by product"),
|
|
241
|
+
limit: z2.number().int().min(1).max(500).default(25),
|
|
242
|
+
offset: z2.number().int().min(0).default(0).describe("Number of results to skip for pagination. Use next_offset from a prior response.")
|
|
168
243
|
}
|
|
169
244
|
},
|
|
170
245
|
async ({ status, severity, product, limit, offset }) => {
|
|
@@ -215,7 +290,7 @@ function registerAddBugReportComment(server) {
|
|
|
215
290
|
description: "AskExe-internal only: append a comment to a bug report's thread (POST /comments). Non-destructive \u2014 does not touch triage_notes or status.",
|
|
216
291
|
inputSchema: {
|
|
217
292
|
id: supportIdSchema,
|
|
218
|
-
comment:
|
|
293
|
+
comment: z2.string().min(1).describe("Comment text to append to the bug report thread")
|
|
219
294
|
}
|
|
220
295
|
},
|
|
221
296
|
async ({ id, comment }) => {
|
|
@@ -246,22 +321,50 @@ function registerTriageBugReport(server) {
|
|
|
246
321
|
"triage_bug_report",
|
|
247
322
|
{
|
|
248
323
|
title: "Triage Bug Report",
|
|
249
|
-
description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
|
|
324
|
+
description: "AskExe-internal only: update bug report status and link task/commit/release metadata. Setting status=fixed or closed requires a verification artifact (verification_kind + fix_commit + either the regression-test fields or the manual verifier fields); the fix commit's diff is measured locally.",
|
|
250
325
|
inputSchema: {
|
|
251
326
|
id: supportIdSchema,
|
|
252
327
|
status: STATUS.optional(),
|
|
253
|
-
triage_notes:
|
|
254
|
-
add_note:
|
|
328
|
+
triage_notes: z2.string().optional(),
|
|
329
|
+
add_note: z2.string().optional().describe("Append a timestamped progress note without changing status or replacing triage_notes"),
|
|
255
330
|
linked_task_id: supportTaskIdSchema.optional(),
|
|
256
331
|
linked_commit: supportCommitSchema.optional(),
|
|
257
332
|
fixed_version: supportVersionSchema.optional(),
|
|
258
|
-
product: supportProductSchema.optional().describe("Re-label this bug's product: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp")
|
|
333
|
+
product: supportProductSchema.optional().describe("Re-label this bug's product: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp"),
|
|
334
|
+
...verificationArtifactInputSchema
|
|
259
335
|
}
|
|
260
336
|
},
|
|
261
|
-
async ({ id, status, triage_notes, add_note, linked_task_id, linked_commit, fixed_version, product }) => {
|
|
262
|
-
const
|
|
337
|
+
async ({ id, status, triage_notes, add_note, linked_task_id, linked_commit, fixed_version, product, ...verification }) => {
|
|
338
|
+
const bugUrl = `${endpoint()}/${encodeURIComponent(sanitizeUpstreamId(id))}`;
|
|
339
|
+
let authorIdentities = [];
|
|
340
|
+
if (isVerifiedStatus(status) && verification.verification_kind === "manual") {
|
|
341
|
+
try {
|
|
342
|
+
const row = await requestJson(bugUrl);
|
|
343
|
+
authorIdentities = [row?.agent_id, row?.license_email];
|
|
344
|
+
} catch {
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const resolved = resolveVerificationArtifact(status, verification, { authorIdentities });
|
|
348
|
+
if (!resolved.ok) {
|
|
349
|
+
return { isError: true, content: [{ type: "text", text: resolved.message }] };
|
|
350
|
+
}
|
|
351
|
+
const delivery = parseDeliveryProof(verification.delivery_proof);
|
|
352
|
+
if (!delivery.ok) {
|
|
353
|
+
return { isError: true, content: [{ type: "text", text: delivery.message }] };
|
|
354
|
+
}
|
|
355
|
+
const data = await requestJson(bugUrl, {
|
|
263
356
|
method: "PATCH",
|
|
264
|
-
body: sanitizedUpstreamBody({
|
|
357
|
+
body: sanitizedUpstreamBody({
|
|
358
|
+
status,
|
|
359
|
+
triage_notes,
|
|
360
|
+
add_note,
|
|
361
|
+
linked_task_id,
|
|
362
|
+
linked_commit,
|
|
363
|
+
fixed_version,
|
|
364
|
+
product,
|
|
365
|
+
verification_artifact: resolved.artifact,
|
|
366
|
+
delivery_proof: delivery.value
|
|
367
|
+
}, "support-inbox:triage_bug")
|
|
265
368
|
});
|
|
266
369
|
const response = fixed_version && !status ? withStatusNotice(
|
|
267
370
|
data,
|
|
@@ -271,7 +374,7 @@ function registerTriageBugReport(server) {
|
|
|
271
374
|
}
|
|
272
375
|
);
|
|
273
376
|
}
|
|
274
|
-
var FEATURE_STATUS =
|
|
377
|
+
var FEATURE_STATUS = z2.enum(["open", "planned", "in_progress", "shipped", "closed", "wontdo"]);
|
|
275
378
|
function featureEndpoint() {
|
|
276
379
|
return endpoint().replace(/\/bug-reports\/?$/, "/feature-requests");
|
|
277
380
|
}
|
|
@@ -285,11 +388,11 @@ function registerListFeatureRequests(server) {
|
|
|
285
388
|
title: "List Feature Requests",
|
|
286
389
|
description: "AskExe-internal only: list incoming customer feature requests from the support inbox.",
|
|
287
390
|
inputSchema: {
|
|
288
|
-
status:
|
|
289
|
-
priority:
|
|
290
|
-
product:
|
|
291
|
-
limit:
|
|
292
|
-
offset:
|
|
391
|
+
status: z2.enum(["all", "open", "planned", "in_progress", "shipped", "closed", "wontdo"]).default("open"),
|
|
392
|
+
priority: z2.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
393
|
+
product: z2.string().optional().describe("Filter by product: exe-os, exe-create, exe-wiki, exe-gateway, exe-crm, exe-build, exe-chat, exe-auth, exe-monitor, exe-db, exe-erp"),
|
|
394
|
+
limit: z2.number().int().min(1).max(500).default(25),
|
|
395
|
+
offset: z2.number().int().min(0).default(0).describe("Number of results to skip for pagination. Use next_offset from a prior response.")
|
|
293
396
|
}
|
|
294
397
|
},
|
|
295
398
|
async ({ status, priority, product, limit, offset }) => {
|
|
@@ -328,8 +431,8 @@ function registerTriageFeatureRequest(server) {
|
|
|
328
431
|
inputSchema: {
|
|
329
432
|
id: supportIdSchema,
|
|
330
433
|
status: FEATURE_STATUS.optional(),
|
|
331
|
-
response_notes:
|
|
332
|
-
add_note:
|
|
434
|
+
response_notes: z2.string().optional(),
|
|
435
|
+
add_note: z2.string().optional().describe("Append a timestamped progress note without changing status or replacing response_notes"),
|
|
333
436
|
target_version: supportVersionSchema.optional(),
|
|
334
437
|
shipped_version: supportVersionSchema.optional(),
|
|
335
438
|
// bug b8e990ed: allow admin re-label of a feature's product. Typed with the
|
|
@@ -350,7 +453,7 @@ function registerTriageFeatureRequest(server) {
|
|
|
350
453
|
}
|
|
351
454
|
);
|
|
352
455
|
}
|
|
353
|
-
var REVIEW_STATUS =
|
|
456
|
+
var REVIEW_STATUS = z2.enum(["open", "in_review", "approved", "merged", "closed", "rejected"]);
|
|
354
457
|
function reviewEndpoint() {
|
|
355
458
|
return endpoint().replace(/\/bug-reports\/?$/, "/reviews");
|
|
356
459
|
}
|
|
@@ -361,10 +464,10 @@ function registerListReviews(server) {
|
|
|
361
464
|
title: "List Reviews",
|
|
362
465
|
description: "AskExe-internal only: list incoming review requests from the support inbox.",
|
|
363
466
|
inputSchema: {
|
|
364
|
-
status:
|
|
365
|
-
priority:
|
|
366
|
-
limit:
|
|
367
|
-
offset:
|
|
467
|
+
status: z2.enum(["all", "open", "in_review", "approved", "merged", "closed", "rejected"]).default("open"),
|
|
468
|
+
priority: z2.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
469
|
+
limit: z2.number().int().min(1).max(500).default(25),
|
|
470
|
+
offset: z2.number().int().min(0).default(0).describe("Number of results to skip for pagination. Use next_offset from a prior response.")
|
|
368
471
|
}
|
|
369
472
|
},
|
|
370
473
|
async ({ status, priority, limit, offset }) => {
|
|
@@ -401,10 +504,10 @@ function registerTriageReview(server) {
|
|
|
401
504
|
inputSchema: {
|
|
402
505
|
id: supportIdSchema,
|
|
403
506
|
status: REVIEW_STATUS.optional(),
|
|
404
|
-
response_notes:
|
|
405
|
-
add_note:
|
|
406
|
-
resolution:
|
|
407
|
-
pr_url:
|
|
507
|
+
response_notes: z2.string().optional(),
|
|
508
|
+
add_note: z2.string().optional().describe("Append a timestamped progress note without changing status or replacing response_notes"),
|
|
509
|
+
resolution: z2.string().optional(),
|
|
510
|
+
pr_url: z2.string().optional()
|
|
408
511
|
}
|
|
409
512
|
},
|
|
410
513
|
async ({ id, status, response_notes, add_note, resolution, pr_url }) => {
|
|
@@ -418,6 +521,9 @@ function registerTriageReview(server) {
|
|
|
418
521
|
}
|
|
419
522
|
|
|
420
523
|
export {
|
|
524
|
+
verificationArtifactInputSchema,
|
|
525
|
+
resolveVerificationArtifact,
|
|
526
|
+
parseDeliveryProof,
|
|
421
527
|
registerListBugReports,
|
|
422
528
|
registerGetBugReport,
|
|
423
529
|
registerAddBugReportComment,
|
|
@@ -351,7 +351,7 @@ async function runRegistryProxy(options = registryProxyOptionsFromEnv()) {
|
|
|
351
351
|
await new Promise((resolve) => server.listen(options.port, options.host, resolve));
|
|
352
352
|
console.log(`exe-registry-proxy listening on ${options.host ?? "0.0.0.0"}:${options.port}`);
|
|
353
353
|
console.log(`proxying /v2/${options.allowedNamespace ?? "askexe"}/* -> ${options.upstream ?? "https://ghcr.io"}`);
|
|
354
|
-
const { licenseSyncConfigFromEnv, startLicenseSyncScheduler } = await import("./license-sync-
|
|
354
|
+
const { licenseSyncConfigFromEnv, startLicenseSyncScheduler } = await import("./license-sync-5VE5OSTV.js");
|
|
355
355
|
const syncConfig = licenseSyncConfigFromEnv();
|
|
356
356
|
if (syncConfig) {
|
|
357
357
|
startLicenseSyncScheduler(syncConfig);
|