@vibgrate/cli 2026.819.1 → 2026.819.3
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/DOCS.md +3 -3
- package/dist/agent-AFMDB4GM.js +30 -0
- package/dist/{agent-3CKNTCRX.js.map → agent-AFMDB4GM.js.map} +1 -1
- package/dist/{approvals-DHTG3HI4.js → approvals-F2DJGPU7.js} +7 -7
- package/dist/{approvals-DHTG3HI4.js.map → approvals-F2DJGPU7.js.map} +1 -1
- package/dist/attach-XTX2Q3AD.js +10 -0
- package/dist/{attach-OCQ3I76L.js.map → attach-XTX2Q3AD.js.map} +1 -1
- package/dist/baseline-KTE2C3LW.js +9 -0
- package/dist/{baseline-QDC6OQ2X.js.map → baseline-KTE2C3LW.js.map} +1 -1
- package/dist/{chunk-D33M2ARL.js → chunk-3SOJZ3VV.js} +3 -3
- package/dist/{chunk-D33M2ARL.js.map → chunk-3SOJZ3VV.js.map} +1 -1
- package/dist/{chunk-JGBOYZAF.js → chunk-3XMTRK24.js} +99 -19
- package/dist/chunk-3XMTRK24.js.map +1 -0
- package/dist/{chunk-OV4KGXPD.js → chunk-57ZRSCHY.js} +3 -3
- package/dist/{chunk-OV4KGXPD.js.map → chunk-57ZRSCHY.js.map} +1 -1
- package/dist/{chunk-KFEM6FWP.js → chunk-5R4HYDTC.js} +4 -4
- package/dist/{chunk-KFEM6FWP.js.map → chunk-5R4HYDTC.js.map} +1 -1
- package/dist/{chunk-EI5AKDSC.js → chunk-5RMME7PT.js} +3 -3
- package/dist/{chunk-EI5AKDSC.js.map → chunk-5RMME7PT.js.map} +1 -1
- package/dist/{chunk-OQT3JBWW.js → chunk-5UG4UHKU.js} +205 -36
- package/dist/chunk-5UG4UHKU.js.map +1 -0
- package/dist/{chunk-NDNNOAS6.js → chunk-6H2QV5DR.js} +3 -3
- package/dist/{chunk-NDNNOAS6.js.map → chunk-6H2QV5DR.js.map} +1 -1
- package/dist/{chunk-LJSJX6U4.js → chunk-A3WWRW7U.js} +3 -3
- package/dist/{chunk-LJSJX6U4.js.map → chunk-A3WWRW7U.js.map} +1 -1
- package/dist/{chunk-O5ASXWKF.js → chunk-ARGYMFST.js} +3 -3
- package/dist/{chunk-O5ASXWKF.js.map → chunk-ARGYMFST.js.map} +1 -1
- package/dist/{chunk-FFY6NW7P.js → chunk-C5AOLTQS.js} +5 -5
- package/dist/{chunk-FFY6NW7P.js.map → chunk-C5AOLTQS.js.map} +1 -1
- package/dist/{chunk-F46Q3AEI.js → chunk-CEJIX3O7.js} +44 -15
- package/dist/chunk-CEJIX3O7.js.map +1 -0
- package/dist/{chunk-QMRSCJUN.js → chunk-DMI4BMUL.js} +3 -3
- package/dist/{chunk-QMRSCJUN.js.map → chunk-DMI4BMUL.js.map} +1 -1
- package/dist/{chunk-TS25WFAT.js → chunk-EXFA7QFC.js} +9 -9
- package/dist/{chunk-TS25WFAT.js.map → chunk-EXFA7QFC.js.map} +1 -1
- package/dist/{chunk-VYSDR2QE.js → chunk-HB3SONYP.js} +4 -4
- package/dist/{chunk-VYSDR2QE.js.map → chunk-HB3SONYP.js.map} +1 -1
- package/dist/{chunk-KKQX3F5F.js → chunk-HRYF4PWE.js} +7 -5
- package/dist/chunk-HRYF4PWE.js.map +1 -0
- package/dist/{chunk-EIESBKLW.js → chunk-HVJHFTIV.js} +7 -7
- package/dist/{chunk-EIESBKLW.js.map → chunk-HVJHFTIV.js.map} +1 -1
- package/dist/{chunk-JFE7XCAE.js → chunk-IASO2HCI.js} +3 -3
- package/dist/{chunk-JFE7XCAE.js.map → chunk-IASO2HCI.js.map} +1 -1
- package/dist/chunk-MQJY4EQV.js +6 -0
- package/dist/{chunk-DHU3OOEI.js.map → chunk-MQJY4EQV.js.map} +1 -1
- package/dist/{chunk-7AVYKZEM.js → chunk-NV7XNBX4.js} +4 -4
- package/dist/{chunk-7AVYKZEM.js.map → chunk-NV7XNBX4.js.map} +1 -1
- package/dist/{chunk-NZELMYT4.js → chunk-OLIMW4PQ.js} +8 -56
- package/dist/chunk-OLIMW4PQ.js.map +1 -0
- package/dist/{chunk-NWWLUFN5.js → chunk-PQISIPYP.js} +5 -5
- package/dist/{chunk-NWWLUFN5.js.map → chunk-PQISIPYP.js.map} +1 -1
- package/dist/{chunk-5XY4EFR7.js → chunk-QLNJ3VWO.js} +3 -3
- package/dist/{chunk-5XY4EFR7.js.map → chunk-QLNJ3VWO.js.map} +1 -1
- package/dist/{chunk-D44PGMH7.js → chunk-QOU2Q5L4.js} +12 -12
- package/dist/{chunk-D44PGMH7.js.map → chunk-QOU2Q5L4.js.map} +1 -1
- package/dist/{chunk-TS7STRMI.js → chunk-RTURQXQL.js} +4 -4
- package/dist/{chunk-TS7STRMI.js.map → chunk-RTURQXQL.js.map} +1 -1
- package/dist/{chunk-74UBGF4P.js → chunk-SHD5TCZ5.js} +3 -3
- package/dist/{chunk-74UBGF4P.js.map → chunk-SHD5TCZ5.js.map} +1 -1
- package/dist/{chunk-WJYJCDNY.js → chunk-SOAEPTSW.js} +13 -13
- package/dist/{chunk-WJYJCDNY.js.map → chunk-SOAEPTSW.js.map} +1 -1
- package/dist/{chunk-EMEMHNE3.js → chunk-TD4JAEMH.js} +6 -6
- package/dist/{chunk-EMEMHNE3.js.map → chunk-TD4JAEMH.js.map} +1 -1
- package/dist/{chunk-5O6O7DJH.js → chunk-UAPA5AHX.js} +3 -3
- package/dist/{chunk-5O6O7DJH.js.map → chunk-UAPA5AHX.js.map} +1 -1
- package/dist/{chunk-4VAA2XSM.js → chunk-UEXDSWKN.js} +6 -6
- package/dist/{chunk-4VAA2XSM.js.map → chunk-UEXDSWKN.js.map} +1 -1
- package/dist/{chunk-YIEP5GK5.js → chunk-UP2BR6TV.js} +15 -11
- package/dist/chunk-UP2BR6TV.js.map +1 -0
- package/dist/{chunk-6F52QR6F.js → chunk-VEQA2FSM.js} +4 -4
- package/dist/{chunk-6F52QR6F.js.map → chunk-VEQA2FSM.js.map} +1 -1
- package/dist/{chunk-E53WBVUQ.js → chunk-VHRSG6CF.js} +3 -3
- package/dist/{chunk-E53WBVUQ.js.map → chunk-VHRSG6CF.js.map} +1 -1
- package/dist/{chunk-I5LP55B6.js → chunk-W44THEXF.js} +3 -3
- package/dist/{chunk-I5LP55B6.js.map → chunk-W44THEXF.js.map} +1 -1
- package/dist/{chunk-FQVAQVJV.js → chunk-WI66PODG.js} +3 -3
- package/dist/{chunk-FQVAQVJV.js.map → chunk-WI66PODG.js.map} +1 -1
- package/dist/{chunk-CQDUBAQY.js → chunk-WNKGRXUA.js} +3 -3
- package/dist/{chunk-CQDUBAQY.js.map → chunk-WNKGRXUA.js.map} +1 -1
- package/dist/{chunk-FJG5AXKZ.js → chunk-WUFIXAEJ.js} +22 -6
- package/dist/chunk-WUFIXAEJ.js.map +1 -0
- package/dist/{chunk-QSLVOVNZ.js → chunk-XAS45W3G.js} +10 -10
- package/dist/{chunk-QSLVOVNZ.js.map → chunk-XAS45W3G.js.map} +1 -1
- package/dist/{chunk-BWPBB45M.js → chunk-XP6UUCZZ.js} +3 -3
- package/dist/{chunk-BWPBB45M.js.map → chunk-XP6UUCZZ.js.map} +1 -1
- package/dist/{chunk-BPF3YX2U.js → chunk-XQNKCA2J.js} +6 -3
- package/dist/chunk-XQNKCA2J.js.map +1 -0
- package/dist/{chunk-U7A7D2HP.js → chunk-XZDI2N7M.js} +7 -7
- package/dist/{chunk-U7A7D2HP.js.map → chunk-XZDI2N7M.js.map} +1 -1
- package/dist/{chunk-7N4Y3E47.js → chunk-YJYEPYB2.js} +13 -18
- package/dist/chunk-YJYEPYB2.js.map +1 -0
- package/dist/cli.js +104 -94
- package/dist/cli.js.map +1 -1
- package/dist/client-P5XSRFV4.js +8 -0
- package/dist/{client-UQIELEEZ.js.map → client-P5XSRFV4.js.map} +1 -1
- package/dist/daemon-VMQKIIYP.js +30 -0
- package/dist/{daemon-UNL65PTP.js.map → daemon-VMQKIIYP.js.map} +1 -1
- package/dist/embed-worker-main.js +5 -5
- package/dist/ensure-map-YIUJWMBK.js +40 -0
- package/dist/{ensure-map-4D2HJ6MA.js.map → ensure-map-YIUJWMBK.js.map} +1 -1
- package/dist/{federation-SZYVHYB2.js → federation-M4ZNXOPX.js} +5 -5
- package/dist/{federation-SZYVHYB2.js.map → federation-M4ZNXOPX.js.map} +1 -1
- package/dist/git-ref-LMT3EXYY.js +4 -0
- package/dist/{git-ref-RSRAN4OH.js.map → git-ref-LMT3EXYY.js.map} +1 -1
- package/dist/graph-backend-FDZUY4TR.js +16 -0
- package/dist/{graph-backend-36EIAAPQ.js.map → graph-backend-FDZUY4TR.js.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +23 -23
- package/dist/{interactive-ZZMHSZ3W.js → interactive-CS4PGZPK.js} +40 -40
- package/dist/{interactive-ZZMHSZ3W.js.map → interactive-CS4PGZPK.js.map} +1 -1
- package/dist/{llm-host-XFYFOAAX.js → llm-host-QVTJJVER.js} +5 -5
- package/dist/{llm-host-XFYFOAAX.js.map → llm-host-QVTJJVER.js.map} +1 -1
- package/dist/load-4EY64JJO.js +11 -0
- package/dist/{load-6CYLMUT5.js.map → load-4EY64JJO.js.map} +1 -1
- package/dist/local-runtime-GA43KYS5.js +6 -0
- package/dist/{local-runtime-6SNWKSA7.js.map → local-runtime-GA43KYS5.js.map} +1 -1
- package/dist/model-manager-6H3TMZKK.js +10 -0
- package/dist/{model-manager-SXHZ5VD4.js.map → model-manager-6H3TMZKK.js.map} +1 -1
- package/dist/{model-orchestrator-LHYPJBFH.js → model-orchestrator-X3NE3Y2G.js} +6 -6
- package/dist/{model-orchestrator-LHYPJBFH.js.map → model-orchestrator-X3NE3Y2G.js.map} +1 -1
- package/dist/parse-worker.js +2 -2
- package/dist/{paths-62AKTFSR.js → paths-RVK6FKRN.js} +4 -4
- package/dist/{paths-62AKTFSR.js.map → paths-RVK6FKRN.js.map} +1 -1
- package/dist/publish-27S66NOW.js +9 -0
- package/dist/{publish-7YHRTBRA.js.map → publish-27S66NOW.js.map} +1 -1
- package/dist/resolve-gguf-WVKVDN45.js +9 -0
- package/dist/{resolve-gguf-SDIYGGI6.js.map → resolve-gguf-WVKVDN45.js.map} +1 -1
- package/dist/{run-outcome-ADEAKXHH.js → run-outcome-T7VDBNWB.js} +7 -7
- package/dist/{run-outcome-ADEAKXHH.js.map → run-outcome-T7VDBNWB.js.map} +1 -1
- package/dist/runtime-session-WZLVADPQ.js +26 -0
- package/dist/{runtime-session-VNSXQAEO.js.map → runtime-session-WZLVADPQ.js.map} +1 -1
- package/dist/session-VPP2VGUN.js +17 -0
- package/dist/{session-3A6LKJHD.js.map → session-VPP2VGUN.js.map} +1 -1
- package/dist/{slot-subscription-25GOARW5.js → slot-subscription-C2ZUJED6.js} +5 -5
- package/dist/{slot-subscription-25GOARW5.js.map → slot-subscription-C2ZUJED6.js.map} +1 -1
- package/dist/{stream-json-S2TP2VPU.js → stream-json-XXCFN4MF.js} +17 -17
- package/dist/{stream-json-S2TP2VPU.js.map → stream-json-XXCFN4MF.js.map} +1 -1
- package/dist/version-2UBJ7N2I.js +4 -0
- package/dist/{version-SZI6I3A2.js.map → version-2UBJ7N2I.js.map} +1 -1
- package/dist/{vg-mcp-bridge-IIBEAOEB.js → vg-mcp-bridge-H6GXYNKV.js} +14 -14
- package/dist/{vg-mcp-bridge-IIBEAOEB.js.map → vg-mcp-bridge-H6GXYNKV.js.map} +1 -1
- package/dist/{vgd-KGXIKGOS.js → vgd-SBZO4ONQ.js} +13 -13
- package/dist/vgd-SBZO4ONQ.js.map +1 -0
- package/package.json +1 -1
- package/dist/agent-3CKNTCRX.js +0 -30
- package/dist/attach-OCQ3I76L.js +0 -10
- package/dist/baseline-QDC6OQ2X.js +0 -9
- package/dist/chunk-7N4Y3E47.js.map +0 -1
- package/dist/chunk-BPF3YX2U.js.map +0 -1
- package/dist/chunk-DHU3OOEI.js +0 -6
- package/dist/chunk-F46Q3AEI.js.map +0 -1
- package/dist/chunk-FJG5AXKZ.js.map +0 -1
- package/dist/chunk-JGBOYZAF.js.map +0 -1
- package/dist/chunk-KKQX3F5F.js.map +0 -1
- package/dist/chunk-NZELMYT4.js.map +0 -1
- package/dist/chunk-OQT3JBWW.js.map +0 -1
- package/dist/chunk-YIEP5GK5.js.map +0 -1
- package/dist/client-UQIELEEZ.js +0 -8
- package/dist/daemon-UNL65PTP.js +0 -30
- package/dist/ensure-map-4D2HJ6MA.js +0 -40
- package/dist/git-ref-RSRAN4OH.js +0 -4
- package/dist/graph-backend-36EIAAPQ.js +0 -16
- package/dist/load-6CYLMUT5.js +0 -11
- package/dist/local-runtime-6SNWKSA7.js +0 -6
- package/dist/model-manager-SXHZ5VD4.js +0 -10
- package/dist/publish-7YHRTBRA.js +0 -9
- package/dist/resolve-gguf-SDIYGGI6.js +0 -9
- package/dist/runtime-session-VNSXQAEO.js +0 -26
- package/dist/session-3A6LKJHD.js +0 -17
- package/dist/version-SZI6I3A2.js +0 -4
- package/dist/vgd-KGXIKGOS.js.map +0 -1
package/DOCS.md
CHANGED
|
@@ -1191,11 +1191,11 @@ vg llm-host serve --socket /tmp/vg-llm.sock --yes
|
|
|
1191
1191
|
|
|
1192
1192
|
Default isolation is **embedded** (same process as the agent). Set `VIBGRATE_INFERENCE_ISOLATION=process` to use the host. Management never moves into the host process.
|
|
1193
1193
|
|
|
1194
|
-
**First-party weights.**
|
|
1194
|
+
**First-party weights.** Code Mode packs are first-party GGUF only: `vg models install` downloads the catalogued refs into the Vibgrate weight store under the cache directory (HTTPS hosts allowlisted, including Hugging Face LFS/Xet CDNs). Catalog entries carry **sha256 pins**; a download that does not match is rejected. Ollama is used only for models you select explicitly (`vg models pull <name>`, `--provider ollama`) — never for a Code Mode pack.
|
|
1195
1195
|
|
|
1196
1196
|
**Foundry Local.** On Windows (or any host running Microsoft Foundry Local), use `--provider foundry-local --model <id>` with the OpenAI-compatible server (default `http://127.0.0.1:5272/v1`, override with `FOUNDRY_LOCAL_BASE_URL`). `vg models status` lists models when the server responds.
|
|
1197
1197
|
|
|
1198
|
-
**Warm local inference (Approach B default).** Code Mode packs (channel 2026.
|
|
1198
|
+
**Warm local inference (Approach B default).** Code Mode packs (channel 2026.08.1) install first-party GGUF weights and run on embedded llama.cpp only — there is no Ollama fallback in a pack. When a GGUF is on disk (weight store or `~/models`), `vg code` prefers embedded llama.cpp automatically. Set `VG_PREFER_OLLAMA=1` to try your own Ollama models first outside Code Modes. Spark constrained decoding is **fail-closed**: if the binding cannot attach a PatchIR grammar, generation errors instead of free-text (opt-in raw string GBNF only via `VG_ALLOW_GRAMMAR_STRING_FALLBACK=1`).
|
|
1199
1199
|
|
|
1200
1200
|
**Identifier enforce (before apply).** Edits and `apply_patch` that invent identifiers not present in the code graph are **blocked** (not merely annotated). Identifiers already in the target file (locals, params, existing helpers) and tokens only in comments/strings are allowed. After an approved edit, the session trie updates so new symbols become legal.
|
|
1201
1201
|
|
|
@@ -1223,7 +1223,7 @@ Default isolation is **embedded** (same process as the agent). Set `VIBGRATE_INF
|
|
|
1223
1223
|
|
|
1224
1224
|
**Named install commands run by default** (same polarity as the rest of `vg`: the command does what it says). Pass `--dry-run` to print the plan only. Status/resolve never download. Destructive `rm` confirms on a TTY; non-interactive remove needs `--yes`.
|
|
1225
1225
|
|
|
1226
|
-
`install` / `pull` install the **full provider dependency closure**
|
|
1226
|
+
`install` / `pull` install the **full provider dependency closure** (e.g. runtime npm deps for llama-cpp, then the pinned GGUF from the first-party weight store; `pull` fetches your named model via Ollama). Third-party apps such as Ollama itself are never auto-installed — install them separately if the plan lists them as blocked.
|
|
1227
1227
|
|
|
1228
1228
|
```bash
|
|
1229
1229
|
vg models # Code Modes status + fleet summary
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { CONTEXT_POLICY_VERSION, DISCOVERY_TOOLS, MUTATION_TOOLS, compact, compactWithModel, runAgent } from './chunk-SOAEPTSW.js';
|
|
2
|
+
import './chunk-543E6WDJ.js';
|
|
3
|
+
import './chunk-3SOJZ3VV.js';
|
|
4
|
+
import './chunk-HB3SONYP.js';
|
|
5
|
+
import './chunk-SHD5TCZ5.js';
|
|
6
|
+
import './chunk-3HNPVXUK.js';
|
|
7
|
+
import './chunk-5HYCB55P.js';
|
|
8
|
+
import './chunk-VIWZ4QT7.js';
|
|
9
|
+
import './chunk-HRYF4PWE.js';
|
|
10
|
+
export { summarizeCapsule } from './chunk-UAPA5AHX.js';
|
|
11
|
+
import './chunk-EZ7UC5Y5.js';
|
|
12
|
+
import './chunk-6BEBJCK4.js';
|
|
13
|
+
import './chunk-J7LKEB2R.js';
|
|
14
|
+
import './chunk-VEQA2FSM.js';
|
|
15
|
+
import './chunk-VHRSG6CF.js';
|
|
16
|
+
import './chunk-6H2QV5DR.js';
|
|
17
|
+
import './chunk-WI66PODG.js';
|
|
18
|
+
import './chunk-T7RSQ5WD.js';
|
|
19
|
+
import './chunk-6WRG7VDO.js';
|
|
20
|
+
import './chunk-DMI4BMUL.js';
|
|
21
|
+
import './chunk-C5AOLTQS.js';
|
|
22
|
+
import './chunk-MVPRPSXU.js';
|
|
23
|
+
import './chunk-O3LABX6I.js';
|
|
24
|
+
import './chunk-MQJY4EQV.js';
|
|
25
|
+
import './chunk-XP6UUCZZ.js';
|
|
26
|
+
import './chunk-JFGYT6BI.js';
|
|
27
|
+
import './chunk-XQNKCA2J.js';
|
|
28
|
+
import './chunk-Z6ZWNWWR.js';
|
|
29
|
+
//# sourceMappingURL=agent-AFMDB4GM.js.map
|
|
30
|
+
//# sourceMappingURL=agent-AFMDB4GM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"agent-AFMDB4GM.js"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { addApprovalRule, approvalsPath, findMatchingRule, globMatch, loadApprovalRules, normalizeCommandPrefix, removeApprovalRule, ruleForAction, ruleKey, ruleLabel, saveApprovalRules } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
export { addApprovalRule, approvalsPath, findMatchingRule, globMatch, loadApprovalRules, normalizeCommandPrefix, removeApprovalRule, ruleForAction, ruleKey, ruleLabel, saveApprovalRules } from './chunk-3SOJZ3VV.js';
|
|
2
|
+
import './chunk-C5AOLTQS.js';
|
|
3
3
|
import './chunk-O3LABX6I.js';
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
4
|
+
import './chunk-MQJY4EQV.js';
|
|
5
|
+
import './chunk-XP6UUCZZ.js';
|
|
6
6
|
import './chunk-JFGYT6BI.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-XQNKCA2J.js';
|
|
8
8
|
import './chunk-Z6ZWNWWR.js';
|
|
9
|
-
//# sourceMappingURL=approvals-
|
|
10
|
-
//# sourceMappingURL=approvals-
|
|
9
|
+
//# sourceMappingURL=approvals-F2DJGPU7.js.map
|
|
10
|
+
//# sourceMappingURL=approvals-F2DJGPU7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"approvals-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"approvals-F2DJGPU7.js"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { attachVgd, daemonDisabledReason } from './chunk-UEXDSWKN.js';
|
|
2
|
+
import './chunk-A3WWRW7U.js';
|
|
3
|
+
import './chunk-VHRSG6CF.js';
|
|
4
|
+
import './chunk-6H2QV5DR.js';
|
|
5
|
+
import './chunk-XP6UUCZZ.js';
|
|
6
|
+
import './chunk-JFGYT6BI.js';
|
|
7
|
+
import './chunk-XQNKCA2J.js';
|
|
8
|
+
import './chunk-Z6ZWNWWR.js';
|
|
9
|
+
//# sourceMappingURL=attach-XTX2Q3AD.js.map
|
|
10
|
+
//# sourceMappingURL=attach-XTX2Q3AD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"attach-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"attach-XTX2Q3AD.js"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { baselineCommand, runBaseline } from './chunk-QLNJ3VWO.js';
|
|
2
|
+
import './chunk-5UG4UHKU.js';
|
|
3
|
+
import './chunk-PVNALGTG.js';
|
|
4
|
+
import './chunk-CRAMOEBE.js';
|
|
5
|
+
import './chunk-T7RSQ5WD.js';
|
|
6
|
+
import './chunk-MQJY4EQV.js';
|
|
7
|
+
import './chunk-Z6ZWNWWR.js';
|
|
8
|
+
//# sourceMappingURL=baseline-KTE2C3LW.js.map
|
|
9
|
+
//# sourceMappingURL=baseline-KTE2C3LW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"baseline-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"baseline-KTE2C3LW.js"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ensureVibgrateGitignore } from './chunk-
|
|
1
|
+
import { ensureVibgrateGitignore } from './chunk-C5AOLTQS.js';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
|
|
@@ -170,5 +170,5 @@ function findMatchingRule(action, rules) {
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
export { addApprovalRule, approvalsPath, findMatchingRule, globMatch, loadApprovalRules, normalizeCommandPrefix, removeApprovalRule, ruleForAction, ruleKey, ruleLabel, saveApprovalRules };
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
174
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-3SOJZ3VV.js.map
|
|
174
|
+
//# sourceMappingURL=chunk-3SOJZ3VV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/code/approvals.ts"],"names":[],"mappings":"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","file":"chunk-D33M2ARL.js","sourcesContent":["/**\n * Allow-always approval rules (P2 — permission parity).\n *\n * The approval gate exists to review state changes, but reviewing the *same*\n * change shape every time (`pnpm test`, edits to a scratch dir) is friction\n * without safety. A user can promote an approval to a standing rule\n * (\"Always allow\"); rules live in `.vibgrate/code-approvals.json` at the repo\n * root so the CLI and VS Code honour the same set, and are re-read on every\n * approval so a revocation (from the VG Code manage UI or by editing the\n * file) takes effect immediately — no session restart, no stale cache.\n *\n * Rules never widen safety: {@link dangerousCommand} still screens every rule\n * match, plan mode still denies everything engine-side before rules are\n * consulted, and a rule-approved action is still announced (notice event) and\n * checkpointed like any human-approved change.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { ensureVibgrateGitignore } from '../engine/artifacts.js';\nimport type { MutatingAction, PatchFileAction } from './tools.js';\n\n/** One standing approval. Discriminated by `kind`, mirroring MutatingAction. */\nexport type ApprovalRule =\n /** Matches `run` actions whose normalized command starts with these tokens. */\n | { kind: 'run'; prefix: string }\n /** Matches a single-file action of that op when the path matches the glob. */\n | { kind: 'edit' | 'create' | 'delete'; glob: string }\n /** Matches external `tool` calls by tool name. */\n | { kind: 'tool'; tool: string };\n\nexport function approvalsPath(root: string): string {\n return path.join(root, '.vibgrate', 'code-approvals.json');\n}\n\n/**\n * The stable identity of a rule — used for dedupe and for revocation from\n * hosts that only carry the display string.\n */\nexport function ruleKey(rule: ApprovalRule): string {\n if (rule.kind === 'run') return `run:${rule.prefix}`;\n if (rule.kind === 'tool') return `tool:${rule.tool}`;\n return `${rule.kind}:${rule.glob}`;\n}\n\n/** Human-readable label for notices and manage UIs. */\nexport function ruleLabel(rule: ApprovalRule): string {\n if (rule.kind === 'run') return `run \\`${rule.prefix} …\\``;\n if (rule.kind === 'tool') return `call ${rule.tool}`;\n return `${rule.kind} ${rule.glob}`;\n}\n\n/**\n * Load the rule set, tolerating absence and malformed JSON (an unreadable file\n * means \"no rules\", never a crash — same posture as `.vibgrate/code.json`).\n * Unknown shapes are dropped so an untrusted file cannot inject junk.\n */\nexport function loadApprovalRules(root: string): ApprovalRule[] {\n let raw: unknown;\n try {\n raw = JSON.parse(fs.readFileSync(approvalsPath(root), 'utf8'));\n } catch {\n return [];\n }\n const list = Array.isArray(raw)\n ? raw\n : raw && typeof raw === 'object' && Array.isArray((raw as { rules?: unknown }).rules)\n ? ((raw as { rules: unknown[] }).rules)\n : [];\n const out: ApprovalRule[] = [];\n for (const item of list) {\n const rule = sanitizeRule(item);\n if (rule) out.push(rule);\n }\n return dedupe(out);\n}\n\nfunction sanitizeRule(item: unknown): ApprovalRule | null {\n if (!item || typeof item !== 'object') return null;\n const o = item as Record<string, unknown>;\n if (o.kind === 'run' && typeof o.prefix === 'string' && o.prefix.trim()) {\n return { kind: 'run', prefix: normalizeCommandPrefix(o.prefix) };\n }\n if (o.kind === 'tool' && typeof o.tool === 'string' && o.tool.trim()) {\n return { kind: 'tool', tool: o.tool.trim() };\n }\n if ((o.kind === 'edit' || o.kind === 'create' || o.kind === 'delete') && typeof o.glob === 'string' && o.glob.trim()) {\n return { kind: o.kind, glob: o.glob.trim() };\n }\n return null;\n}\n\nfunction dedupe(rules: ApprovalRule[]): ApprovalRule[] {\n const seen = new Set<string>();\n const out: ApprovalRule[] = [];\n for (const r of rules) {\n const key = ruleKey(r);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(r);\n }\n return out;\n}\n\n/**\n * Persist the rule set, deterministically sorted so identical sets produce an\n * identical file. Best-effort like other `.vibgrate/` writers — a read-only\n * checkout means no standing rules, never a thrown error mid-approval.\n */\nexport function saveApprovalRules(root: string, rules: ApprovalRule[]): boolean {\n try {\n const dir = path.join(root, '.vibgrate');\n fs.mkdirSync(dir, { recursive: true });\n // First writer into .vibgrate/ creates its .gitignore (create-once): one\n // developer's standing consents must not ride into the team's repo.\n ensureVibgrateGitignore(root);\n const sorted = dedupe(rules).slice().sort((a, b) => ruleKey(a).localeCompare(ruleKey(b)));\n fs.writeFileSync(approvalsPath(root), `${JSON.stringify({ rules: sorted }, null, 2)}\\n`);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Add one rule (deduped). Returns the saved rule, or null when nothing was written. */\nexport function addApprovalRule(root: string, rule: ApprovalRule): ApprovalRule | null {\n const rules = loadApprovalRules(root);\n if (rules.some((r) => ruleKey(r) === ruleKey(rule))) return rule;\n rules.push(rule);\n return saveApprovalRules(root, rules) ? rule : null;\n}\n\n/** Remove the rule with this {@link ruleKey}. Returns true when one was removed and saved. */\nexport function removeApprovalRule(root: string, key: string): boolean {\n const rules = loadApprovalRules(root);\n const kept = rules.filter((r) => ruleKey(r) !== key);\n if (kept.length === rules.length) return false;\n return saveApprovalRules(root, kept);\n}\n\n/**\n * Normalize a shell command to its rule prefix: the first two tokens for the\n * `cmd subcommand [flags…]` shape (`git status`, `pnpm test --watch`), the\n * single token for a one-word command, and the *whole* command\n * (whitespace-normalized) in every other case. Collapsing `rm -f temp.log` to\n * bare `rm` — or `rm foo.log secrets.env` to `rm foo.log` — would turn one\n * blessed invocation into a standing grant covering paths the user never saw\n * (2026-08 audit, D2), so a command with a flag second-token or positional\n * arguments beyond the subcommand keeps its exact form.\n */\nexport function normalizeCommandPrefix(command: string): string {\n const tokens = command.trim().split(/\\s+/).filter(Boolean);\n const head = tokens[0] ?? '';\n const second = tokens[1];\n if (!second) return head;\n if (second.startsWith('-')) return tokens.join(' ');\n // Extra positionals after `cmd subcommand` make the rule exact; trailing\n // flags still collapse to the extensible two-token prefix.\n if (tokens.slice(2).some((t) => !t.startsWith('-'))) return tokens.join(' ');\n return `${head} ${second}`;\n}\n\n/** True when a rule prefix is the extensible `cmd [subcommand]` shape (no flags). */\nfunction extensiblePrefix(prefix: string): boolean {\n return !prefix.split(' ').some((t) => t.startsWith('-'));\n}\n\n/**\n * Shell constructs that can smuggle a second command into what looks like a\n * flag: command substitution, redirects, sequencing, backgrounding, subshells.\n * A `pnpm test` rule must not bless `pnpm test --reporter=$(curl … | sh)` —\n * the appended token is flag-shaped, but its *value* is another program the\n * user never saw. Same screen {@link readOnlyCommand} applies; kept local so\n * safety and approvals stay independent modules.\n */\nconst SHELL_METACHARS = /[><;&|`\\n(){}$]/;\n\n/**\n * Derive the standing rule an \"Always allow\" on this action should create.\n * Patch actions return null — an atomic multi-file transaction has no single\n * honest generalisation, so hosts do not offer Always on patch cards.\n */\nexport function ruleForAction(action: MutatingAction): ApprovalRule | null {\n switch (action.kind) {\n case 'run':\n return { kind: 'run', prefix: normalizeCommandPrefix(action.command) };\n case 'tool':\n return { kind: 'tool', tool: action.name };\n case 'edit':\n case 'create':\n case 'delete':\n return { kind: action.kind, glob: action.file };\n case 'patch':\n return null;\n }\n}\n\n/**\n * Minimal glob match for rule paths: `*` matches within a segment, `**`\n * across segments, `?` one character. Deterministic, no dependency, and\n * conservative — a malformed pattern simply never matches.\n */\nexport function globMatch(glob: string, file: string): boolean {\n let re = '';\n for (let i = 0; i < glob.length; i++) {\n const c = glob[i];\n if (c === '*') {\n if (glob[i + 1] === '*') {\n // `**/` or trailing `**` — match across segments.\n re += '.*';\n i += glob[i + 2] === '/' ? 2 : 1;\n } else {\n re += '[^/]*';\n }\n } else if (c === '?') {\n re += '[^/]';\n } else if ('\\\\^$.|+()[]{}'.includes(c)) {\n re += `\\\\${c}`;\n } else {\n re += c;\n }\n }\n try {\n return new RegExp(`^${re}$`).test(file);\n } catch {\n return false;\n }\n}\n\nfunction fileRuleMatches(rules: ApprovalRule[], op: 'edit' | 'create' | 'delete', file: string): ApprovalRule | null {\n for (const r of rules) {\n if (r.kind === op && globMatch(r.glob, file)) return r;\n }\n return null;\n}\n\n/**\n * The first rule matching this action, or null. A `patch` matches only when\n * *every* file in the transaction is covered by a matching file rule — an\n * atomic approval must never be half-earned.\n */\nexport function findMatchingRule(action: MutatingAction, rules: ApprovalRule[]): ApprovalRule | null {\n if (!rules.length) return null;\n switch (action.kind) {\n case 'run': {\n // Match the FULL whitespace-normalized command, never a truncated form:\n // collapsing `rm foo.log secrets.env` to its first two tokens before\n // comparing would silently discard the appended argument and let a rule\n // saved for `rm foo.log` bless it (2026-08 audit, D2).\n const full = action.command.trim().split(/\\s+/).filter(Boolean).join(' ');\n for (const r of rules) {\n if (r.kind !== 'run') continue;\n if (full === r.prefix) return r;\n // A `cmd [subcommand]` prefix extends to longer commands only when\n // every appended token is a flag (`git status --short`). Appended\n // positionals (extra paths, script arguments) are new state the user\n // never blessed — they re-prompt, and can be Always-allowed exactly.\n if (extensiblePrefix(r.prefix) && full.startsWith(`${r.prefix} `)) {\n const tail = full.slice(r.prefix.length + 1);\n // A flag whose value is a subshell is not an extension of the blessed\n // command, it is a different one — screen the appended text before\n // the flag-shape check, never after.\n if (SHELL_METACHARS.test(tail)) continue;\n const extension = tail.split(' ');\n if (extension.every((t) => t.startsWith('-'))) return r;\n }\n }\n return null;\n }\n case 'tool':\n return rules.find((r) => r.kind === 'tool' && r.tool === action.name) ?? null;\n case 'edit':\n case 'create':\n case 'delete':\n return fileRuleMatches(rules, action.kind, action.file);\n case 'patch': {\n const covered = action.files.every((f: PatchFileAction) => fileRuleMatches(rules, f.op, f.file));\n if (!covered) return null;\n return fileRuleMatches(rules, action.files[0]!.op, action.files[0]!.file);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/code/approvals.ts"],"names":[],"mappings":"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","file":"chunk-3SOJZ3VV.js","sourcesContent":["/**\n * Allow-always approval rules (P2 — permission parity).\n *\n * The approval gate exists to review state changes, but reviewing the *same*\n * change shape every time (`pnpm test`, edits to a scratch dir) is friction\n * without safety. A user can promote an approval to a standing rule\n * (\"Always allow\"); rules live in `.vibgrate/code-approvals.json` at the repo\n * root so the CLI and VS Code honour the same set, and are re-read on every\n * approval so a revocation (from the VG Code manage UI or by editing the\n * file) takes effect immediately — no session restart, no stale cache.\n *\n * Rules never widen safety: {@link dangerousCommand} still screens every rule\n * match, plan mode still denies everything engine-side before rules are\n * consulted, and a rule-approved action is still announced (notice event) and\n * checkpointed like any human-approved change.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { ensureVibgrateGitignore } from '../engine/artifacts.js';\nimport type { MutatingAction, PatchFileAction } from './tools.js';\n\n/** One standing approval. Discriminated by `kind`, mirroring MutatingAction. */\nexport type ApprovalRule =\n /** Matches `run` actions whose normalized command starts with these tokens. */\n | { kind: 'run'; prefix: string }\n /** Matches a single-file action of that op when the path matches the glob. */\n | { kind: 'edit' | 'create' | 'delete'; glob: string }\n /** Matches external `tool` calls by tool name. */\n | { kind: 'tool'; tool: string };\n\nexport function approvalsPath(root: string): string {\n return path.join(root, '.vibgrate', 'code-approvals.json');\n}\n\n/**\n * The stable identity of a rule — used for dedupe and for revocation from\n * hosts that only carry the display string.\n */\nexport function ruleKey(rule: ApprovalRule): string {\n if (rule.kind === 'run') return `run:${rule.prefix}`;\n if (rule.kind === 'tool') return `tool:${rule.tool}`;\n return `${rule.kind}:${rule.glob}`;\n}\n\n/** Human-readable label for notices and manage UIs. */\nexport function ruleLabel(rule: ApprovalRule): string {\n if (rule.kind === 'run') return `run \\`${rule.prefix} …\\``;\n if (rule.kind === 'tool') return `call ${rule.tool}`;\n return `${rule.kind} ${rule.glob}`;\n}\n\n/**\n * Load the rule set, tolerating absence and malformed JSON (an unreadable file\n * means \"no rules\", never a crash — same posture as `.vibgrate/code.json`).\n * Unknown shapes are dropped so an untrusted file cannot inject junk.\n */\nexport function loadApprovalRules(root: string): ApprovalRule[] {\n let raw: unknown;\n try {\n raw = JSON.parse(fs.readFileSync(approvalsPath(root), 'utf8'));\n } catch {\n return [];\n }\n const list = Array.isArray(raw)\n ? raw\n : raw && typeof raw === 'object' && Array.isArray((raw as { rules?: unknown }).rules)\n ? ((raw as { rules: unknown[] }).rules)\n : [];\n const out: ApprovalRule[] = [];\n for (const item of list) {\n const rule = sanitizeRule(item);\n if (rule) out.push(rule);\n }\n return dedupe(out);\n}\n\nfunction sanitizeRule(item: unknown): ApprovalRule | null {\n if (!item || typeof item !== 'object') return null;\n const o = item as Record<string, unknown>;\n if (o.kind === 'run' && typeof o.prefix === 'string' && o.prefix.trim()) {\n return { kind: 'run', prefix: normalizeCommandPrefix(o.prefix) };\n }\n if (o.kind === 'tool' && typeof o.tool === 'string' && o.tool.trim()) {\n return { kind: 'tool', tool: o.tool.trim() };\n }\n if ((o.kind === 'edit' || o.kind === 'create' || o.kind === 'delete') && typeof o.glob === 'string' && o.glob.trim()) {\n return { kind: o.kind, glob: o.glob.trim() };\n }\n return null;\n}\n\nfunction dedupe(rules: ApprovalRule[]): ApprovalRule[] {\n const seen = new Set<string>();\n const out: ApprovalRule[] = [];\n for (const r of rules) {\n const key = ruleKey(r);\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(r);\n }\n return out;\n}\n\n/**\n * Persist the rule set, deterministically sorted so identical sets produce an\n * identical file. Best-effort like other `.vibgrate/` writers — a read-only\n * checkout means no standing rules, never a thrown error mid-approval.\n */\nexport function saveApprovalRules(root: string, rules: ApprovalRule[]): boolean {\n try {\n const dir = path.join(root, '.vibgrate');\n fs.mkdirSync(dir, { recursive: true });\n // First writer into .vibgrate/ creates its .gitignore (create-once): one\n // developer's standing consents must not ride into the team's repo.\n ensureVibgrateGitignore(root);\n const sorted = dedupe(rules).slice().sort((a, b) => ruleKey(a).localeCompare(ruleKey(b)));\n fs.writeFileSync(approvalsPath(root), `${JSON.stringify({ rules: sorted }, null, 2)}\\n`);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Add one rule (deduped). Returns the saved rule, or null when nothing was written. */\nexport function addApprovalRule(root: string, rule: ApprovalRule): ApprovalRule | null {\n const rules = loadApprovalRules(root);\n if (rules.some((r) => ruleKey(r) === ruleKey(rule))) return rule;\n rules.push(rule);\n return saveApprovalRules(root, rules) ? rule : null;\n}\n\n/** Remove the rule with this {@link ruleKey}. Returns true when one was removed and saved. */\nexport function removeApprovalRule(root: string, key: string): boolean {\n const rules = loadApprovalRules(root);\n const kept = rules.filter((r) => ruleKey(r) !== key);\n if (kept.length === rules.length) return false;\n return saveApprovalRules(root, kept);\n}\n\n/**\n * Normalize a shell command to its rule prefix: the first two tokens for the\n * `cmd subcommand [flags…]` shape (`git status`, `pnpm test --watch`), the\n * single token for a one-word command, and the *whole* command\n * (whitespace-normalized) in every other case. Collapsing `rm -f temp.log` to\n * bare `rm` — or `rm foo.log secrets.env` to `rm foo.log` — would turn one\n * blessed invocation into a standing grant covering paths the user never saw\n * (2026-08 audit, D2), so a command with a flag second-token or positional\n * arguments beyond the subcommand keeps its exact form.\n */\nexport function normalizeCommandPrefix(command: string): string {\n const tokens = command.trim().split(/\\s+/).filter(Boolean);\n const head = tokens[0] ?? '';\n const second = tokens[1];\n if (!second) return head;\n if (second.startsWith('-')) return tokens.join(' ');\n // Extra positionals after `cmd subcommand` make the rule exact; trailing\n // flags still collapse to the extensible two-token prefix.\n if (tokens.slice(2).some((t) => !t.startsWith('-'))) return tokens.join(' ');\n return `${head} ${second}`;\n}\n\n/** True when a rule prefix is the extensible `cmd [subcommand]` shape (no flags). */\nfunction extensiblePrefix(prefix: string): boolean {\n return !prefix.split(' ').some((t) => t.startsWith('-'));\n}\n\n/**\n * Shell constructs that can smuggle a second command into what looks like a\n * flag: command substitution, redirects, sequencing, backgrounding, subshells.\n * A `pnpm test` rule must not bless `pnpm test --reporter=$(curl … | sh)` —\n * the appended token is flag-shaped, but its *value* is another program the\n * user never saw. Same screen {@link readOnlyCommand} applies; kept local so\n * safety and approvals stay independent modules.\n */\nconst SHELL_METACHARS = /[><;&|`\\n(){}$]/;\n\n/**\n * Derive the standing rule an \"Always allow\" on this action should create.\n * Patch actions return null — an atomic multi-file transaction has no single\n * honest generalisation, so hosts do not offer Always on patch cards.\n */\nexport function ruleForAction(action: MutatingAction): ApprovalRule | null {\n switch (action.kind) {\n case 'run':\n return { kind: 'run', prefix: normalizeCommandPrefix(action.command) };\n case 'tool':\n return { kind: 'tool', tool: action.name };\n case 'edit':\n case 'create':\n case 'delete':\n return { kind: action.kind, glob: action.file };\n case 'patch':\n return null;\n }\n}\n\n/**\n * Minimal glob match for rule paths: `*` matches within a segment, `**`\n * across segments, `?` one character. Deterministic, no dependency, and\n * conservative — a malformed pattern simply never matches.\n */\nexport function globMatch(glob: string, file: string): boolean {\n let re = '';\n for (let i = 0; i < glob.length; i++) {\n const c = glob[i];\n if (c === '*') {\n if (glob[i + 1] === '*') {\n // `**/` or trailing `**` — match across segments.\n re += '.*';\n i += glob[i + 2] === '/' ? 2 : 1;\n } else {\n re += '[^/]*';\n }\n } else if (c === '?') {\n re += '[^/]';\n } else if ('\\\\^$.|+()[]{}'.includes(c)) {\n re += `\\\\${c}`;\n } else {\n re += c;\n }\n }\n try {\n return new RegExp(`^${re}$`).test(file);\n } catch {\n return false;\n }\n}\n\nfunction fileRuleMatches(rules: ApprovalRule[], op: 'edit' | 'create' | 'delete', file: string): ApprovalRule | null {\n for (const r of rules) {\n if (r.kind === op && globMatch(r.glob, file)) return r;\n }\n return null;\n}\n\n/**\n * The first rule matching this action, or null. A `patch` matches only when\n * *every* file in the transaction is covered by a matching file rule — an\n * atomic approval must never be half-earned.\n */\nexport function findMatchingRule(action: MutatingAction, rules: ApprovalRule[]): ApprovalRule | null {\n if (!rules.length) return null;\n switch (action.kind) {\n case 'run': {\n // Match the FULL whitespace-normalized command, never a truncated form:\n // collapsing `rm foo.log secrets.env` to its first two tokens before\n // comparing would silently discard the appended argument and let a rule\n // saved for `rm foo.log` bless it (2026-08 audit, D2).\n const full = action.command.trim().split(/\\s+/).filter(Boolean).join(' ');\n for (const r of rules) {\n if (r.kind !== 'run') continue;\n if (full === r.prefix) return r;\n // A `cmd [subcommand]` prefix extends to longer commands only when\n // every appended token is a flag (`git status --short`). Appended\n // positionals (extra paths, script arguments) are new state the user\n // never blessed — they re-prompt, and can be Always-allowed exactly.\n if (extensiblePrefix(r.prefix) && full.startsWith(`${r.prefix} `)) {\n const tail = full.slice(r.prefix.length + 1);\n // A flag whose value is a subshell is not an extension of the blessed\n // command, it is a different one — screen the appended text before\n // the flag-shape check, never after.\n if (SHELL_METACHARS.test(tail)) continue;\n const extension = tail.split(' ');\n if (extension.every((t) => t.startsWith('-'))) return r;\n }\n }\n return null;\n }\n case 'tool':\n return rules.find((r) => r.kind === 'tool' && r.tool === action.name) ?? null;\n case 'edit':\n case 'create':\n case 'delete':\n return fileRuleMatches(rules, action.kind, action.file);\n case 'patch': {\n const covered = action.files.every((f: PatchFileAction) => fileRuleMatches(rules, f.op, f.file));\n if (!covered) return null;\n return fileRuleMatches(rules, action.files[0]!.op, action.files[0]!.file);\n }\n }\n}\n"]}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { readGlobal, applyGlobalOptions } from './chunk-YENM3HT7.js';
|
|
2
2
|
import { json, info, c } from './chunk-CT5BS56U.js';
|
|
3
|
-
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-
|
|
3
|
+
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-CEJIX3O7.js';
|
|
4
4
|
import { CliError, ExitCode } from './chunk-MS6V5XKB.js';
|
|
5
5
|
import { init_cli_invocation, reinvokeCli } from './chunk-EZ7UC5Y5.js';
|
|
6
|
-
import { loadGraph } from './chunk-
|
|
7
|
-
import { vgdIsRunning, vgdRequest } from './chunk-
|
|
8
|
-
import { vgdSocketPath, vgdPidPath } from './chunk-
|
|
9
|
-
import { VERSION } from './chunk-
|
|
6
|
+
import { loadGraph } from './chunk-ARGYMFST.js';
|
|
7
|
+
import { vgdIsRunning, vgdRequest } from './chunk-VHRSG6CF.js';
|
|
8
|
+
import { vgdSocketPath, vgdPidPath } from './chunk-6H2QV5DR.js';
|
|
9
|
+
import { VERSION } from './chunk-MQJY4EQV.js';
|
|
10
10
|
import * as fs from 'fs';
|
|
11
|
+
import * as net from 'net';
|
|
11
12
|
import * as path2 from 'path';
|
|
12
13
|
import { spawn } from 'child_process';
|
|
13
14
|
import * as semver from 'semver';
|
|
@@ -105,13 +106,33 @@ function registerDaemon(program) {
|
|
|
105
106
|
}
|
|
106
107
|
let requestShutdown = () => {
|
|
107
108
|
};
|
|
108
|
-
const
|
|
109
|
+
const serverOptions = {
|
|
109
110
|
socketPath,
|
|
110
111
|
onShutdownRequest: () => requestShutdown(),
|
|
111
112
|
// Show the daemon working: graph publishes, branch switches, new repos,
|
|
112
113
|
// and every semantic index build. Silent under --quiet/--json.
|
|
113
114
|
log: global.quiet || global.json ? void 0 : (message) => info(c.dim(`vgd \xB7 ${message}`))
|
|
114
|
-
}
|
|
115
|
+
};
|
|
116
|
+
let server;
|
|
117
|
+
try {
|
|
118
|
+
server = await startVgdServer(serverOptions);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
if (e?.code !== "EADDRINUSE") throw e;
|
|
121
|
+
const takeover = await retireWedgedVgd(socketPath);
|
|
122
|
+
if (!takeover.ok) {
|
|
123
|
+
if (takeover.live) {
|
|
124
|
+
throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);
|
|
125
|
+
}
|
|
126
|
+
throw new CliError(
|
|
127
|
+
`${socketPath} is held by a process that does not answer vgd requests (${takeover.reason}). End the stale daemon (a node/vg process running "daemon start"), then re-run \`vg daemon start\`.`,
|
|
128
|
+
ExitCode.ERROR
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (!global.quiet && !global.json) {
|
|
132
|
+
info(c.dim(`vgd \xB7 retired a stale daemon (pid ${takeover.pid}) that was holding ${socketPath}`));
|
|
133
|
+
}
|
|
134
|
+
server = await startVgdServer(serverOptions);
|
|
135
|
+
}
|
|
115
136
|
if (!global.quiet) {
|
|
116
137
|
info(`vgd \xB7 listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);
|
|
117
138
|
info(c.dim(" register a workspace: vg daemon register"));
|
|
@@ -252,7 +273,7 @@ function registerDaemon(program) {
|
|
|
252
273
|
if (!await vgdIsRunning({ socketPath })) {
|
|
253
274
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
254
275
|
}
|
|
255
|
-
const { loadFederation } = await import('./federation-
|
|
276
|
+
const { loadFederation } = await import('./federation-M4ZNXOPX.js');
|
|
256
277
|
const fed = loadFederation(primary);
|
|
257
278
|
if (!fed) throw new CliError(`could not load federation for ${primary}`, ExitCode.ERROR);
|
|
258
279
|
const res = await vgdRequest(
|
|
@@ -290,9 +311,9 @@ function registerDaemon(program) {
|
|
|
290
311
|
throw new CliError(loaded.error, ExitCode.NOT_FOUND);
|
|
291
312
|
}
|
|
292
313
|
if (!loaded.ok) {
|
|
293
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
294
|
-
const { detectGitRef } = await import('./git-ref-
|
|
295
|
-
const { repositoryIdFromRoot } = await import('./paths-
|
|
314
|
+
const { loadGraph: loadGraph2 } = await import('./load-4EY64JJO.js');
|
|
315
|
+
const { detectGitRef } = await import('./git-ref-LMT3EXYY.js');
|
|
316
|
+
const { repositoryIdFromRoot } = await import('./paths-RVK6FKRN.js');
|
|
296
317
|
const graph = loadGraph2(root, global.graph);
|
|
297
318
|
if (!graph) {
|
|
298
319
|
throw new CliError(
|
|
@@ -413,7 +434,7 @@ function socketOf(cmd) {
|
|
|
413
434
|
}
|
|
414
435
|
function spawnDetachedDaemonStart(socketPath) {
|
|
415
436
|
const opts = {
|
|
416
|
-
detached:
|
|
437
|
+
detached: process.platform !== "win32",
|
|
417
438
|
stdio: "ignore",
|
|
418
439
|
env: process.env,
|
|
419
440
|
windowsHide: true
|
|
@@ -440,7 +461,25 @@ async function ensureVgdSoft(socketPath = vgdSocketPath(), readyBudgetMs = 1500)
|
|
|
440
461
|
return { running: false, started: false };
|
|
441
462
|
}
|
|
442
463
|
}
|
|
443
|
-
|
|
464
|
+
var START_BIND_ATTEMPTS = 3;
|
|
465
|
+
async function startDetachedVgd(socketPath, deps = {}) {
|
|
466
|
+
const startOnce = deps.startOnce ?? startDetachedVgdOnce;
|
|
467
|
+
const skewOf = deps.skew ?? vgdVersionSkew;
|
|
468
|
+
const stop = deps.stop ?? stopVgd;
|
|
469
|
+
let pid;
|
|
470
|
+
for (let attempt = 1; attempt <= START_BIND_ATTEMPTS; attempt++) {
|
|
471
|
+
pid = await startOnce(socketPath);
|
|
472
|
+
const skew = await skewOf(socketPath);
|
|
473
|
+
if (skew.running && skew.state !== "older") return pid;
|
|
474
|
+
if (!skew.running) continue;
|
|
475
|
+
await stop(socketPath, { force: true });
|
|
476
|
+
}
|
|
477
|
+
throw new CliError(
|
|
478
|
+
`an older vgd keeps re-binding ${socketPath} \u2014 another running client is starting it (commonly a VS Code extension bundling an older engine, or a long-lived \`vg serve\`). Update or restart that client, then run "vg daemon restart --force".`,
|
|
479
|
+
ExitCode.ERROR
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
async function startDetachedVgdOnce(socketPath) {
|
|
444
483
|
const child = spawnDetachedDaemonStart(socketPath);
|
|
445
484
|
child.unref();
|
|
446
485
|
const readyMs = 3e4;
|
|
@@ -491,6 +530,47 @@ async function ensureVgd(socketPath = vgdSocketPath(), opts = {}) {
|
|
|
491
530
|
await stopVgd(socketPath, { force: true });
|
|
492
531
|
return { started: true, pid: await startDetachedVgd(socketPath), replaced: { version: skew.version } };
|
|
493
532
|
}
|
|
533
|
+
async function retireWedgedVgd(socketPath, deps = {}) {
|
|
534
|
+
const isRunning = deps.isRunning ?? ((s) => vgdIsRunning({ socketPath: s }));
|
|
535
|
+
const readPid = deps.readPid ?? readVgdPid;
|
|
536
|
+
const signal = deps.signal ?? signalPid;
|
|
537
|
+
const held = deps.held ?? vgdSocketHeld;
|
|
538
|
+
const waitBudgetMs = deps.waitBudgetMs ?? 3e3;
|
|
539
|
+
const selfPid = deps.selfPid ?? process.pid;
|
|
540
|
+
if (await isRunning(socketPath)) return { ok: false, live: true };
|
|
541
|
+
const pid = readPid();
|
|
542
|
+
if (pid == null) return { ok: false, reason: "no pid file identifies the holder" };
|
|
543
|
+
if (pid === selfPid) return { ok: false, reason: "the pid file points at this process" };
|
|
544
|
+
if (!signal(pid, "SIGTERM")) return { ok: false, reason: `pid ${pid} from the pid file is not signalable` };
|
|
545
|
+
if (await waitForSocketFree(socketPath, waitBudgetMs, held)) return { ok: true, pid };
|
|
546
|
+
signal(pid, "SIGKILL");
|
|
547
|
+
if (await waitForSocketFree(socketPath, waitBudgetMs, held)) return { ok: true, pid };
|
|
548
|
+
return { ok: false, reason: `pid ${pid} was signalled but ${socketPath} is still held` };
|
|
549
|
+
}
|
|
550
|
+
async function waitForSocketFree(socketPath, budgetMs, held) {
|
|
551
|
+
const deadline = Date.now() + budgetMs;
|
|
552
|
+
for (; ; ) {
|
|
553
|
+
if (!await held(socketPath)) return true;
|
|
554
|
+
if (Date.now() >= deadline) return false;
|
|
555
|
+
await sleep(100);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function vgdSocketHeld(socketPath, timeoutMs = 1e3) {
|
|
559
|
+
return new Promise((resolve3) => {
|
|
560
|
+
const socket = net.createConnection(socketPath);
|
|
561
|
+
let settled = false;
|
|
562
|
+
const done = (heldNow) => {
|
|
563
|
+
if (settled) return;
|
|
564
|
+
settled = true;
|
|
565
|
+
clearTimeout(timer);
|
|
566
|
+
socket.destroy();
|
|
567
|
+
resolve3(heldNow);
|
|
568
|
+
};
|
|
569
|
+
const timer = setTimeout(() => done(true), timeoutMs);
|
|
570
|
+
socket.once("connect", () => done(true));
|
|
571
|
+
socket.once("error", () => done(false));
|
|
572
|
+
});
|
|
573
|
+
}
|
|
494
574
|
async function stopVgd(socketPath, opts = {}) {
|
|
495
575
|
if (!await vgdIsRunning({ socketPath })) return "not-running";
|
|
496
576
|
const livePid = opts.force ? await vgdReportedPid(socketPath) : null;
|
|
@@ -546,11 +626,11 @@ async function vgdReportedPid(socketPath) {
|
|
|
546
626
|
async function restartVgdIfRunning(socketPath = vgdSocketPath(), opts = {}) {
|
|
547
627
|
try {
|
|
548
628
|
const stopResult = await stopVgd(socketPath, opts);
|
|
549
|
-
if (stopResult === "not-running") return "not-running";
|
|
629
|
+
if (stopResult === "not-running" && !opts.startIfNotRunning) return "not-running";
|
|
550
630
|
if (stopResult === "refused") return "refused";
|
|
551
631
|
if (stopResult === "failed") return "failed";
|
|
552
632
|
await startDetachedVgd(socketPath);
|
|
553
|
-
return "restarted";
|
|
633
|
+
return stopResult === "not-running" ? "started" : "restarted";
|
|
554
634
|
} catch {
|
|
555
635
|
return "failed";
|
|
556
636
|
}
|
|
@@ -565,12 +645,12 @@ function readVgdPid() {
|
|
|
565
645
|
}
|
|
566
646
|
}
|
|
567
647
|
async function repositoryIdForCwd(socketPath, root) {
|
|
568
|
-
const { repositoryIdFromRoot } = await import('./paths-
|
|
648
|
+
const { repositoryIdFromRoot } = await import('./paths-RVK6FKRN.js');
|
|
569
649
|
const reg = await vgdRequest({ op: "register", root }, { socketPath });
|
|
570
650
|
if (reg.ok && "workspace" in reg) return reg.workspace.id;
|
|
571
651
|
return repositoryIdFromRoot(root);
|
|
572
652
|
}
|
|
573
653
|
|
|
574
|
-
export { compareDaemonVersion, ensureVgd, ensureVgdSoft, registerDaemon, requireGraph, restartVgdIfRunning, rootOf, stopVgd, vgdCliVersion, vgdVersionSkew };
|
|
575
|
-
//# sourceMappingURL=chunk-
|
|
576
|
-
//# sourceMappingURL=chunk-
|
|
654
|
+
export { compareDaemonVersion, ensureVgd, ensureVgdSoft, registerDaemon, requireGraph, restartVgdIfRunning, retireWedgedVgd, rootOf, startDetachedVgd, stopVgd, vgdCliVersion, vgdVersionSkew };
|
|
655
|
+
//# sourceMappingURL=chunk-3XMTRK24.js.map
|
|
656
|
+
//# sourceMappingURL=chunk-3XMTRK24.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/util.ts","../src/commands/daemon.ts"],"names":["path","loadGraph","c","resolve","pid"],"mappings":"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","file":"chunk-3XMTRK24.js","sourcesContent":["import * as path from 'node:path';\nimport { loadGraph } from '../engine/load.js';\nimport { CliError, ExitCode } from '../util/exit.js';\nimport type { GlobalOpts } from '../cli-options.js';\nimport type { VgGraph } from '../schema.js';\n\nexport function rootOf(global: GlobalOpts): string {\n return path.resolve(global.cwd ?? '.');\n}\n\n/** Load the committed graph, or fail with an actionable NOT_FOUND error. */\nexport function requireGraph(global: GlobalOpts): { root: string; graph: VgGraph } {\n const root = rootOf(global);\n const graph = loadGraph(root, global.graph);\n if (!graph) {\n throw new CliError(\n `no map found — run \\`vg\\` to build one first` +\n (global.graph ? ` (looked at ${global.graph})` : ''),\n ExitCode.NOT_FOUND,\n );\n }\n return { root, graph };\n}\n","import * as fs from 'node:fs';\nimport * as net from 'node:net';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport { Command } from 'commander';\nimport * as semver from 'semver';\nimport { applyGlobalOptions, readGlobal } from '../cli-options.js';\nimport { VERSION } from '../version.js';\nimport { startVgdServer, vgdIsRunning, vgdPidPath, vgdRequest, vgdSocketPath, VGD_PROTOCOL_VERSION } from '../runtime/vgd/index.js';\nimport { rootOf } from './util.js';\nimport { CliError, ExitCode } from '../util/exit.js';\nimport { reinvokeCli } from '../util/cli-invocation.js';\nimport { c, info, json } from '../util/output.js';\n\n/**\n * `vg daemon` — lightweight local Fusion Runtime daemon (`vgd`) prototype.\n *\n * Phase 2 slice: local socket + workspace registry. Interactive `vg code`\n * attaches via `startCodeRuntimeSession` (ensures this standalone daemon).\n * No overlays yet. Safe to start/stop; does not mutate repos.\n */\nexport function registerDaemon(program: Command): void {\n const cmd = program\n .command('daemon')\n .description('local Fusion Runtime daemon (vgd) — workspace registry prototype')\n .option('--socket <path>', 'override the daemon socket path');\n\n const status = cmd\n .command('status')\n .description('show whether vgd is running and how many workspaces it tracks')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const running = await vgdIsRunning({ socketPath });\n if (!running) {\n if (global.json) {\n json({ running: false, socketPath, version: VGD_PROTOCOL_VERSION });\n } else {\n info(c.dim(`vgd · not running (${socketPath})`));\n }\n process.exitCode = ExitCode.NOT_FOUND;\n return;\n }\n const res = await vgdRequest({ op: 'status' }, { socketPath });\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n // \"Warm\" used to mean the code map only, while every client still loaded\n // its own embedder — so the semantic state is reported next to the graph\n // slots rather than left to be inferred.\n const semantic = await vgdRequest({ op: 'embed-status' }, { socketPath }).catch(() => null);\n const semanticPayload = semantic && semantic.ok && 'semantic' in semantic ? semantic.semantic : undefined;\n const skew = await vgdVersionSkew(socketPath);\n if (global.json) json({ running: true, ...res, semantic: semanticPayload, skew });\n else if ('pid' in res) {\n const slots = typeof res.graphSlots === 'number' ? ` · ${res.graphSlots} graph slot(s)` : '';\n // Always print the build, even when the daemon is too old to report one\n // — a blank where the version should be is what made this skew\n // invisible in the first place.\n const cli = ` · cli ${describeVersion(res.cliVersion ?? null)}`;\n info(\n `vgd · running pid ${res.pid}${cli} · ${res.workspaces} workspace(s)${slots} · ${res.uptimeMs}ms up · ${c.dim(res.socketPath)}`,\n );\n if (skew.running && skew.state !== 'match') {\n const verb = skew.state === 'older' ? 'older than' : 'newer than';\n info(\n c.dim(\n ` ⚠ this daemon is ${verb} the CLI you just ran (${VERSION})` +\n (skew.state === 'older' ? ' — run \"vg daemon restart --force\" to bring it up to date' : ''),\n ),\n );\n }\n const fresh = 'freshness' in res && Array.isArray(res.freshness) ? res.freshness : [];\n if (fresh.length) {\n const watching = fresh.filter((f) => f.watching).length;\n const building = fresh.filter((f) => f.building);\n const pending = fresh.reduce((n, f) => n + f.pending, 0);\n const detail = [\n `${watching}/${fresh.length} watched`,\n building.length ? `${building.length} rebuilding` : '',\n pending ? `${pending} change(s) pending` : '',\n ]\n .filter(Boolean)\n .join(' · ');\n info(` freshness · ${detail}`);\n for (const f of fresh) {\n if (f.watching && !f.building && !f.pending) continue;\n const state = f.building ? 'rebuilding' : f.watching ? `${f.pending} pending` : 'not watched (no recursive fs.watch here)';\n info(c.dim(` ${f.repositoryId}@${f.gitRef} · ${state}`));\n }\n }\n if (semanticPayload) {\n const ready = semanticPayload.slots.filter((sl) => sl.state === 'ready');\n const vectors = ready.reduce((n, sl) => n + sl.vectors, 0);\n // \"worker stopped · 0/0 index(es)\" reads like a broken daemon when\n // it usually means nobody has published a map yet — the index is\n // slot-scoped, so no graph slot means there is nothing to index.\n const detail =\n semanticPayload.worker === 'unavailable'\n ? c.dim(semanticPayload.reason ?? 'semantic off — lexical only')\n : semanticPayload.slots.length === 0\n ? c.dim('no map published yet — run `vg build` in a repo (the index follows the graph slot)')\n : `${ready.length}/${semanticPayload.slots.length} index(es) ready · ${vectors} vector(s)` +\n (semanticPayload.model ? ` · ${semanticPayload.model}` : '');\n info(` semantic · worker ${semanticPayload.worker} · ${detail}`);\n for (const sl of semanticPayload.slots) {\n if (sl.state === 'ready') continue;\n const pending = typeof sl.pending === 'number' && sl.pending > 0 ? ` · ${sl.pending} pending` : '';\n info(\n c.dim(` ${sl.repositoryId}@${sl.gitRef} · ${sl.state}${pending}${sl.error ? ` — ${sl.error}` : ''}`),\n );\n }\n }\n }\n });\n applyGlobalOptions(status);\n\n const start = cmd\n .command('start')\n .description('run vgd in the foreground (Ctrl-C to stop)')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n if (await vgdIsRunning({ socketPath })) {\n throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);\n }\n // The shutdown closure needs the server; the server needs the hook.\n // Bridge with a mutable ref so `vg daemon stop` can reach us.\n let requestShutdown: () => void = () => {};\n const serverOptions = {\n socketPath,\n onShutdownRequest: () => requestShutdown(),\n // Show the daemon working: graph publishes, branch switches, new repos,\n // and every semantic index build. Silent under --quiet/--json.\n log: global.quiet || global.json ? undefined : (message: string) => info(c.dim(`vgd · ${message}`)),\n };\n let server;\n try {\n server = await startVgdServer(serverOptions);\n } catch (e) {\n if ((e as NodeJS.ErrnoException)?.code !== 'EADDRINUSE') throw e;\n // The address is held, yet nothing answered the liveness check above:\n // a wedged or stale daemon (typically one left behind by an editor\n // extension update) is squatting on the socket. Every `stopVgd` and\n // `ensureVgd` sees \"not running\" for such a holder, so without a\n // takeover here each `daemon ensure` becomes an infinite\n // start → EADDRINUSE → exit-1 loop. Retire the holder via its pid\n // file and bind again rather than surfacing the raw bind error.\n const takeover = await retireWedgedVgd(socketPath);\n if (!takeover.ok) {\n if (takeover.live) {\n // Lost a start race to a healthy daemon — that is the ordinary\n // already-running case, not a wedge.\n throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);\n }\n throw new CliError(\n `${socketPath} is held by a process that does not answer vgd requests (${takeover.reason}). ` +\n 'End the stale daemon (a node/vg process running \"daemon start\"), then re-run `vg daemon start`.',\n ExitCode.ERROR,\n );\n }\n if (!global.quiet && !global.json) {\n info(c.dim(`vgd · retired a stale daemon (pid ${takeover.pid}) that was holding ${socketPath}`));\n }\n server = await startVgdServer(serverOptions);\n }\n if (!global.quiet) {\n info(`vgd · listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);\n info(c.dim(' register a workspace: vg daemon register'));\n info(c.dim(' status: vg daemon status'));\n }\n\n const shutdown = async (): Promise<void> => {\n await server.close();\n if (!global.quiet) info(c.dim('vgd · stopped'));\n process.exit(0);\n };\n requestShutdown = () => void shutdown();\n process.on('SIGINT', () => void shutdown());\n process.on('SIGTERM', () => void shutdown());\n // Keep the event loop alive until signal.\n await new Promise(() => {});\n });\n applyGlobalOptions(start);\n\n /**\n * Idempotent start for host UIs (VS Code) and agents: if vgd is already\n * listening, exit 0; otherwise spawn a detached background `daemon start`.\n */\n const ensure = cmd\n .command('ensure')\n .description('ensure vgd is running on this build (start or replace in background if needed)')\n .option('--allow-version-mismatch', 'attach to an older running vgd instead of replacing it')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const opts = this.opts() as { allowVersionMismatch?: boolean };\n const ensured = await ensureVgd(socketPath, { allowVersionMismatch: opts.allowVersionMismatch });\n const res = await vgdRequest({ op: 'status' }, { socketPath });\n if (!res.ok) {\n throw new CliError(\n ensured.started\n ? `vgd started (pid ${ensured.pid ?? '?'}) but status failed: ${res.error} (${socketPath})`\n : `vgd is running but status failed: ${res.error} (${socketPath})`,\n ExitCode.ERROR,\n );\n }\n if (global.json) {\n json({ running: true, ensured: ensured.started, replaced: ensured.replaced ?? null, ...res });\n } else if (!global.quiet) {\n const pid = 'pid' in res ? res.pid : ensured.pid;\n if (ensured.replaced) {\n info(\n `vgd · replaced ${describeVersion(ensured.replaced.version)} daemon with ${VERSION} · pid ${pid} · ${c.dim(socketPath)}`,\n );\n } else {\n info(\n ensured.started\n ? `vgd · started in background pid ${pid} · ${c.dim(socketPath)}`\n : `vgd · already running pid ${pid} · ${c.dim(socketPath)}`,\n );\n }\n }\n });\n applyGlobalOptions(ensure);\n\n const stop = cmd\n .command('stop')\n .description('stop the running vgd (idempotent — succeeds if none is running)')\n .option('--force', 'escalate to SIGTERM/SIGKILL if it will not stop politely')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const force = Boolean((this.opts() as { force?: boolean }).force);\n const result = await stopVgd(socketPath, { force });\n if (global.json) {\n json({ stopped: result === 'stopped', result, socketPath });\n } else if (!global.quiet) {\n if (result === 'stopped') info(`vgd · stopped ${c.dim(socketPath)}`);\n else if (result === 'not-running') info(c.dim(`vgd · not running (${socketPath})`));\n }\n if (result === 'refused') {\n throw new CliError(\n 'this vgd cannot be stopped remotely — it is running inside another process; stop that process instead',\n ExitCode.ERROR,\n );\n }\n if (result === 'failed') {\n throw new CliError(\n `vgd did not stop within 5s (${socketPath}) — retry with \\`vg daemon stop --force\\` to escalate to a signal`,\n ExitCode.ERROR,\n );\n }\n });\n applyGlobalOptions(stop);\n\n const restart = cmd\n .command('restart')\n .description('restart vgd (stop if running, then start in the background)')\n .option('--force', 'escalate to SIGTERM/SIGKILL if it will not stop politely')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const force = Boolean((this.opts() as { force?: boolean }).force);\n const stopResult = await stopVgd(socketPath, { force });\n if (stopResult === 'refused') {\n throw new CliError(\n 'this vgd cannot be stopped remotely — it is running inside another process; stop that process instead',\n ExitCode.ERROR,\n );\n }\n if (stopResult === 'failed') {\n throw new CliError(\n `vgd did not stop within 5s (${socketPath}) — retry with \\`vg daemon restart --force\\` to escalate to a signal`,\n ExitCode.ERROR,\n );\n }\n await startDetachedVgd(socketPath);\n const res = await vgdRequest({ op: 'status' }, { socketPath });\n if (global.json) {\n json({ running: true, restarted: true, ...(res.ok ? res : { socketPath }) });\n } else if (!global.quiet) {\n const pid = res.ok && 'pid' in res ? res.pid : '?';\n info(`vgd · restarted pid ${pid} · ${c.dim(socketPath)}`);\n }\n });\n applyGlobalOptions(restart);\n\n const register = cmd\n .command('register')\n .description('register the current repository with a running vgd')\n .argument('[root]', 'repository root (default: cwd)')\n .action(async function (this: Command, rootArg?: string) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const root = path.resolve(rootArg ?? rootOf(global));\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running — start it with \\`vg daemon start\\` (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const res = await vgdRequest({ op: 'register', root }, { socketPath });\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n if (global.json) json(res);\n else if ('workspace' in res) {\n info(`vgd · registered ${res.workspace.root}`);\n info(c.dim(` id ${res.workspace.id}`));\n info(c.dim(` graph ${res.workspace.graphPath}`));\n }\n });\n applyGlobalOptions(register);\n\n const list = cmd\n .command('list')\n .description('list workspaces registered with the running vgd')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const res = await vgdRequest({ op: 'list' }, { socketPath });\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n if (global.json) json(res);\n else if ('workspaces' in res && Array.isArray(res.workspaces)) {\n if (res.workspaces.length === 0) info(c.dim('vgd · no workspaces registered'));\n for (const w of res.workspaces) {\n const tag = w.label ? ` (${w.label}${w.role ? `/${w.role}` : ''})` : '';\n info(`${w.root}${tag}`);\n info(c.dim(` id ${w.id} · graph ${w.graphPath}`));\n }\n }\n });\n applyGlobalOptions(list);\n\n const federation = cmd\n .command('federation')\n .description('register a multi-root federation from .vibgrate/federation.json (or primary cwd)')\n .argument('[root]', 'primary repository root (default: cwd)')\n .action(async function (this: Command, rootArg?: string) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const primary = path.resolve(rootArg ?? rootOf(global));\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running — start it with \\`vg daemon start\\` (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const { loadFederation } = await import('../runtime/federation.js');\n const fed = loadFederation(primary);\n if (!fed) throw new CliError(`could not load federation for ${primary}`, ExitCode.ERROR);\n const res = await vgdRequest(\n {\n op: 'register-federation',\n primaryRoot: fed.primaryRoot,\n members: fed.members.map((m) => ({ root: m.root, label: m.label, role: m.role })),\n },\n { socketPath },\n );\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n if (global.json) json(res);\n else if ('workspaces' in res && Array.isArray(res.workspaces)) {\n info(`vgd · federation registered (${res.workspaces.length} workspace(s))`);\n for (const w of res.workspaces) {\n info(c.dim(` ${w.label ?? w.root}${w.role ? ` [${w.role}]` : ''}`));\n }\n }\n });\n applyGlobalOptions(federation);\n\n /**\n * Load the on-disk code map for a workspace into vgd's ActiveGraph cache so\n * query/impact work without an agent put-graph first (VS Code / IDE path).\n */\n const publish = cmd\n .command('publish')\n .description('load the workspace code map into vgd ActiveGraph (from global/legacy store)')\n .argument('[root]', 'repository root (default: cwd)')\n .option('--git-ref <ref>', 'branch or SHA (default: detect HEAD)')\n .action(async function (this: Command, rootArg?: string) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const root = path.resolve(rootArg ?? rootOf(global));\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running — start it with \\`vg daemon ensure\\` (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const opts = this.opts() as { gitRef?: string };\n // Fast path: the daemon loads the map from disk itself (binary snapshot\n // first) — nothing heavy crosses the socket.\n const loaded = await vgdRequest(\n { op: 'load-graph', root, gitRef: opts.gitRef?.trim() || undefined, graphPath: global.graph },\n { socketPath },\n );\n let put = loaded;\n if (!loaded.ok && loaded.code === 'no_map') {\n throw new CliError(loaded.error, ExitCode.NOT_FOUND);\n }\n if (!loaded.ok) {\n // Older daemon without load-graph — legacy path: load locally and ship\n // the graph over the socket with put-graph.\n const { loadGraph } = await import('../engine/load.js');\n const { detectGitRef } = await import('../runtime/git-ref.js');\n const { repositoryIdFromRoot } = await import('../runtime/paths.js');\n const graph = loadGraph(root, global.graph);\n if (!graph) {\n throw new CliError(\n `no code map found for ${root} — run \\`vg build\\` (or bare \\`vg\\`) first`,\n ExitCode.NOT_FOUND,\n );\n }\n // Ensure workspace is registered so list shows the root.\n const reg = await vgdRequest({ op: 'register', root }, { socketPath });\n if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);\n const git = opts.gitRef?.trim() || detectGitRef(root).ref || 'HEAD';\n const repositoryId =\n reg.ok && 'workspace' in reg ? reg.workspace.id : repositoryIdFromRoot(root);\n put = await vgdRequest(\n { op: 'put-graph', repositoryId, gitRef: git, graph },\n { socketPath },\n );\n if (!put.ok) throw new CliError(put.error, ExitCode.ERROR);\n }\n if (global.json) json(put);\n else if (put.ok && 'stored' in put) {\n info(`vgd · published graph · ${put.nodeCount} node(s) · ref ${put.gitRef}`);\n info(c.dim(` repositoryId ${put.repositoryId}`));\n }\n });\n applyGlobalOptions(publish);\n\n const query = cmd\n .command('query')\n .description('query the ActiveGraph held by vgd (lexical/structural)')\n .option('--repository-id <id>', 'repository id from `vg daemon list` (default: cwd workspace)')\n .argument('<query...>', 'what to find')\n .option('--limit <n>', 'max matches', '12')\n .option('--git-ref <ref>', 'branch or SHA (default: current slot)')\n .action(async function (this: Command, queryParts: string[]) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const opts = this.opts() as { repositoryId?: string; limit?: string; gitRef?: string };\n const q = (queryParts ?? []).join(' ').trim();\n if (!q) throw new CliError('say what to find', ExitCode.USAGE_ERROR);\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const repositoryId = opts.repositoryId?.trim() || (await repositoryIdForCwd(socketPath, rootOf(global)));\n const res = await vgdRequest(\n {\n op: 'query-graph',\n repositoryId,\n query: q,\n limit: opts.limit ? Number(opts.limit) : 12,\n gitRef: opts.gitRef,\n },\n { socketPath },\n );\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n if (global.json) json(res);\n else if ('matches' in res) {\n info(`vgd query · ${res.matches.length} match(es) · ref ${res.gitRef}`);\n for (const m of res.matches) {\n info(`${m.qualifiedName} (${m.kind}) ${m.file}:${m.line}`);\n info(c.dim(` score ${m.score} · ${m.why}`));\n }\n }\n });\n applyGlobalOptions(query);\n\n const impact = cmd\n .command('impact')\n .description('blast radius for a symbol in the vgd ActiveGraph')\n .option('--repository-id <id>', 'repository id (default: cwd workspace)')\n .argument('<symbol>', 'symbol id or qualified name')\n .option('--depth <n>', 'max dependency depth', '4')\n .option('--git-ref <ref>', 'branch or SHA')\n .action(async function (this: Command, symbol: string) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const opts = this.opts() as { repositoryId?: string; depth?: string; gitRef?: string };\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const repositoryId = opts.repositoryId?.trim() || (await repositoryIdForCwd(socketPath, rootOf(global)));\n const res = await vgdRequest(\n {\n op: 'impact-of',\n repositoryId,\n symbol: symbol.trim(),\n depth: opts.depth ? Number(opts.depth) : 4,\n gitRef: opts.gitRef,\n },\n { socketPath },\n );\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n if (global.json) json(res);\n else if ('affected' in res) {\n info(`vgd impact · ${res.root.name} · depth ${res.depth} · ${res.affected.length} affected`);\n for (const a of res.affected.slice(0, 30)) {\n info(`- ${a.name} (${a.file}:${a.line}) d=${a.depth}`);\n }\n }\n });\n applyGlobalOptions(impact);\n\n const graphs = cmd\n .command('graphs')\n .description('list multi-branch ActiveGraph slots resident in the running vgd (Fusion §4.1.1)')\n .option('--repository-id <id>', 'filter slots to one repository id')\n .action(async function (this: Command) {\n const global = readGlobal(this);\n const socketPath = socketOf(this);\n const opts = this.opts() as { repositoryId?: string };\n if (!(await vgdIsRunning({ socketPath }))) {\n throw new CliError(`vgd is not running (${socketPath})`, ExitCode.NOT_FOUND);\n }\n const res = await vgdRequest(\n { op: 'list-graph-slots', repositoryId: opts.repositoryId },\n { socketPath },\n );\n if (!res.ok) throw new CliError(res.error, ExitCode.ERROR);\n if (global.json) json(res);\n else if ('slots' in res) {\n if (!res.slots.length) info(c.dim('vgd · no graph slots resident'));\n for (const s of res.slots) {\n const cur = s.current ? c.green(' current') : '';\n const idle = s.evictable ? c.yellow(' idle') : '';\n info(`${s.repositoryId.slice(0, 8)}… ${s.gitRef}${cur}${idle}`);\n info(c.dim(` nodes ${s.nodeCount} · idle ${Math.round(s.idleMs / 1000)}s · loaded ${new Date(s.loadedAt).toISOString()}`));\n }\n }\n });\n applyGlobalOptions(graphs);\n\n applyGlobalOptions(cmd);\n}\n\nfunction socketOf(cmd: Command): string {\n // Walk parents for --socket on the daemon parent or the leaf.\n let c: Command | null = cmd;\n while (c) {\n const opts = c.opts() as { socket?: string };\n if (opts.socket) return path.resolve(opts.socket);\n c = c.parent;\n }\n return vgdSocketPath();\n}\n\n/**\n * Re-invoke this CLI as a detached background `daemon start`.\n * Handles `node dist/cli.js …`, a global `vg` symlink (npm bin), and a\n * packaged `vg` binary. The symlink case must realpath to cli.js — see\n * {@link reinvokeCli}.\n */\nfunction spawnDetachedDaemonStart(socketPath: string): ReturnType<typeof spawn> {\n // On Windows, `detached` (DETACHED_PROCESS) is the wrong tool for a daemon\n // with descendants: it leaves the process with NO console, so every\n // console-subsystem child it later spawns (embed worker, rebuild `vg build`,\n // git) allocates a brand-new VISIBLE console window on the desktop — and a\n // user closing that stray window kills the child with STATUS_CONTROL_C_EXIT.\n // windowsHide (CREATE_NO_WINDOW, ignored when combined with detached) gives\n // the daemon a windowless console its whole subtree inherits instead.\n // Lifetime is unaffected: Windows never kills children on parent exit, and\n // the separate console keeps the terminal's Ctrl-C/close away from it. On\n // POSIX, detached (its own process group) is still what lets the daemon\n // outlive the terminal.\n const opts = {\n detached: process.platform !== 'win32',\n stdio: 'ignore' as const,\n env: process.env,\n windowsHide: true,\n };\n const { command, argv } = reinvokeCli(['daemon', 'start', '--socket', socketPath]);\n return spawn(command, argv, opts);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\n/**\n * Start vgd in the background without making the caller wait for it.\n *\n * `ensureVgd` waits up to 30s and throws — right for `vg daemon ensure` and for\n * `vg code`, which cannot proceed without a runtime, and wrong for every\n * ordinary command. An auto-start must never put a cold-start on the front of\n * `vg ask`: we spawn, give the socket a short window in case it binds quickly,\n * and otherwise leave the child coming up on its own. The command runs its\n * in-process path this time and finds a warm daemon the next.\n *\n * Never throws — the caller has a working fallback by construction.\n */\nexport async function ensureVgdSoft(\n socketPath: string = vgdSocketPath(),\n readyBudgetMs = 1500,\n): Promise<{ running: boolean; started: boolean }> {\n try {\n if (await vgdIsRunning({ socketPath })) return { running: true, started: false };\n const child = spawnDetachedDaemonStart(socketPath);\n child.unref();\n const deadline = Date.now() + Math.max(0, readyBudgetMs);\n while (Date.now() < deadline) {\n await sleep(100);\n if (await vgdIsRunning({ socketPath })) return { running: true, started: true };\n if (child.exitCode != null && child.exitCode !== 0) break;\n }\n return { running: false, started: true };\n } catch {\n return { running: false, started: false };\n }\n}\n\n/** Injectable internals of {@link startDetachedVgd} (tests). */\nexport interface StartVgdDeps {\n startOnce: (socketPath: string) => Promise<number | undefined>;\n skew: (socketPath: string) => Promise<VgdSkew>;\n stop: (socketPath: string, opts?: StopVgdOptions) => ReturnType<typeof stopVgd>;\n}\n\n/**\n * How many times a start will retire an older daemon that re-binds the socket\n * before conceding. Each round both stops the interloper and gives our own\n * child another chance to win the bind; a client that keeps spawning an old\n * build faster than we can retire it is a fight to report, not to keep having.\n */\nconst START_BIND_ATTEMPTS = 3;\n\n/**\n * Start vgd in the background and hand back a daemon that is genuinely on this\n * build (or newer). Throws when it cannot.\n *\n * A socket that answers ping is NOT proof the start worked: while the socket\n * is free (mid-update, mid-restart) any other client's `daemon ensure` — a VS\n * Code extension bundling an older engine, a long-lived `vg serve` on an old\n * build — can bind ITS daemon first, and our child then exits \"already\n * running\". Reporting success against that daemon is exactly the \"updated,\n * but the daemon is still stale\" state `vg update` exists to end, so after\n * every ready signal the build on the socket is verified and an older\n * squatter is force-stopped and replaced, a bounded number of times. A newer\n * daemon is left alone (newest wins — see {@link compareDaemonVersion}).\n */\nexport async function startDetachedVgd(\n socketPath: string,\n deps: Partial<StartVgdDeps> = {},\n): Promise<number | undefined> {\n const startOnce = deps.startOnce ?? startDetachedVgdOnce;\n const skewOf = deps.skew ?? vgdVersionSkew;\n const stop = deps.stop ?? stopVgd;\n let pid: number | undefined;\n for (let attempt = 1; attempt <= START_BIND_ATTEMPTS; attempt++) {\n pid = await startOnce(socketPath);\n const skew = await skewOf(socketPath);\n if (skew.running && skew.state !== 'older') return pid;\n if (!skew.running) continue; // gone between ready and the check — spawn again\n await stop(socketPath, { force: true });\n }\n throw new CliError(\n `an older vgd keeps re-binding ${socketPath} — another running client is starting it ` +\n '(commonly a VS Code extension bundling an older engine, or a long-lived `vg serve`). ' +\n 'Update or restart that client, then run \"vg daemon restart --force\".',\n ExitCode.ERROR,\n );\n}\n\n/**\n * Spawn a detached background `daemon start` and wait for the socket to answer\n * ping. Returns the child pid; throws when the socket never becomes ready.\n * The listener is not necessarily our child — {@link startDetachedVgd} owns\n * that verification.\n *\n * Ready budget is long because the detached child pays a full Node + CLI cold\n * start of its own (often >8s under Windows AV). The previous 8s window made\n * `vg daemon ensure` report success only when ping raced ahead of the child\n * exiting, or fail right as the child was about to listen.\n */\nasync function startDetachedVgdOnce(socketPath: string): Promise<number | undefined> {\n const child = spawnDetachedDaemonStart(socketPath);\n child.unref();\n const readyMs = 30_000;\n const deadline = Date.now() + readyMs;\n while (Date.now() < deadline) {\n await sleep(150);\n if (await vgdIsRunning({ socketPath })) return child.pid;\n // If the child already exited without ever answering, fail fast rather\n // than waiting out the full budget for a dead process. Another client\n // (the VS Code extension's `daemon ensure`) may have bound in this\n // tick — treat that as ready rather than reporting a false failure.\n if (child.exitCode != null && child.exitCode !== 0) {\n if (await vgdIsRunning({ socketPath })) return child.pid;\n throw new CliError(\n `vgd child exited ${child.exitCode} before becoming ready at ${socketPath} — run \"vg daemon start\" in the foreground to see the error`,\n ExitCode.ERROR,\n );\n }\n }\n throw new CliError(\n `vgd failed to become ready within ${Math.round(readyMs / 1000)}s at ${socketPath}`,\n ExitCode.ERROR,\n );\n}\n\n/**\n * The build version of the daemon currently on the socket, or `null` when it\n * does not report one.\n *\n * `null` is not \"unknown, leave it alone\": `cliVersion` landed in the status\n * response in 2026.817.x, so its absence dates the process to a build older\n * than that just as surely as a version string would.\n */\nexport async function vgdCliVersion(socketPath: string = vgdSocketPath()): Promise<string | null> {\n try {\n const res = await vgdRequest({ op: 'status' }, { socketPath });\n if (!res.ok || !('cliVersion' in res)) return null;\n return typeof res.cliVersion === 'string' && res.cliVersion ? res.cliVersion : null;\n } catch {\n return null;\n }\n}\n\nexport type VgdSkew =\n | { running: false }\n | { running: true; version: string | null; state: 'match' | 'older' | 'newer' };\n\n/**\n * Compare the daemon holding the socket against this build.\n *\n * vgd owns one machine-wide socket, so whichever process binds it first serves\n * every client — the CLI, `vg serve`, and a VS Code extension running its own\n * bundled engine. Version skew is therefore the normal case, not an edge case,\n * and it is invisible: an old daemon answers every request happily, just with\n * old code.\n */\nexport async function vgdVersionSkew(socketPath: string = vgdSocketPath(), self: string = VERSION): Promise<VgdSkew> {\n if (!(await vgdIsRunning({ socketPath }))) return { running: false };\n const version = await vgdCliVersion(socketPath);\n return { running: true, version, state: compareDaemonVersion(version, self) };\n}\n\n/**\n * Resolution is deliberately monotonic — only a strictly newer daemon survives\n * a mismatch. Two clients on different builds both ensuring the socket would\n * otherwise restart each other forever; with \"newest wins\" they converge on the\n * highest version present and stay there.\n */\nexport function compareDaemonVersion(version: string | null, self: string): 'match' | 'older' | 'newer' {\n if (version === self) return 'match';\n // We cannot judge from an unparseable version of our own — never pick a fight\n // we have no way to win.\n if (!semver.valid(self)) return 'match';\n if (version === null || !semver.valid(version)) return 'older';\n return semver.gt(version, self) ? 'newer' : 'older';\n}\n\n/** Human label for a daemon build, including the pre-2026.817 \"no version\" case. */\nfunction describeVersion(version: string | null): string {\n return version ?? 'unknown (pre-2026.817)';\n}\n\nexport interface EnsureVgdResult {\n started: boolean;\n pid?: number;\n /** Set when an older daemon was retired to make room for this build. */\n replaced?: { version: string | null };\n}\n\nexport interface EnsureVgdOptions {\n /** Attach to whatever is on the socket, even on an older build. */\n allowVersionMismatch?: boolean;\n}\n\n/**\n * Idempotent start used by `vg daemon ensure` and `vg code`: if vgd is already\n * listening on this build, do nothing; otherwise spawn a detached standalone\n * `daemon start`.\n *\n * An older daemon is replaced rather than attached to. Attaching is the quiet\n * failure this exists to prevent: the client reports success, then serves stale\n * answers from a process nobody remembers starting.\n */\nexport async function ensureVgd(\n socketPath: string = vgdSocketPath(),\n opts: EnsureVgdOptions = {},\n): Promise<EnsureVgdResult> {\n const skew = await vgdVersionSkew(socketPath);\n if (!skew.running) return { started: true, pid: await startDetachedVgd(socketPath) };\n if (opts.allowVersionMismatch || skew.state !== 'older') return { started: false };\n await stopVgd(socketPath, { force: true });\n return { started: true, pid: await startDetachedVgd(socketPath), replaced: { version: skew.version } };\n}\n\n/** Injectable internals of {@link retireWedgedVgd} (tests). */\nexport interface RetireWedgedDeps {\n isRunning: (socketPath: string) => Promise<boolean>;\n readPid: () => number | null;\n signal: (pid: number, signal: NodeJS.Signals) => boolean;\n held: (socketPath: string) => Promise<boolean>;\n /** How long to wait for the address to free after each signal. */\n waitBudgetMs: number;\n selfPid: number;\n}\n\nexport type RetireWedgedResult =\n | { ok: true; pid: number }\n | { ok: false; live: true }\n | { ok: false; live?: false; reason: string };\n\n/**\n * Free a vgd socket held by a process that no longer answers vgd requests.\n *\n * The wedge this exists for: a daemon (often from an older extension install)\n * keeps the pipe/socket bound but its event loop is stuck, so `ping` times out\n * everywhere — `vg daemon status` says \"not running\", `stopVgd` returns\n * `not-running` without touching it, `ensureVgd` goes straight to a start that\n * dies on EADDRINUSE, and every client retries that forever. This retires the\n * holder identified by vgd's own pid file (only a successful `startVgdServer`\n * bind ever writes it, so it names the current holder), escalating SIGTERM →\n * SIGKILL, and confirms the address actually freed.\n *\n * Refuses to act when a live daemon answers ping (an ordinary lost start race,\n * not a wedge) or when the pid file is missing or points at this process.\n */\nexport async function retireWedgedVgd(\n socketPath: string,\n deps: Partial<RetireWedgedDeps> = {},\n): Promise<RetireWedgedResult> {\n const isRunning = deps.isRunning ?? ((s: string) => vgdIsRunning({ socketPath: s }));\n const readPid = deps.readPid ?? readVgdPid;\n const signal = deps.signal ?? signalPid;\n const held = deps.held ?? vgdSocketHeld;\n const waitBudgetMs = deps.waitBudgetMs ?? 3_000;\n const selfPid = deps.selfPid ?? process.pid;\n\n if (await isRunning(socketPath)) return { ok: false, live: true };\n const pid = readPid();\n if (pid == null) return { ok: false, reason: 'no pid file identifies the holder' };\n if (pid === selfPid) return { ok: false, reason: 'the pid file points at this process' };\n if (!signal(pid, 'SIGTERM')) return { ok: false, reason: `pid ${pid} from the pid file is not signalable` };\n if (await waitForSocketFree(socketPath, waitBudgetMs, held)) return { ok: true, pid };\n signal(pid, 'SIGKILL');\n if (await waitForSocketFree(socketPath, waitBudgetMs, held)) return { ok: true, pid };\n return { ok: false, reason: `pid ${pid} was signalled but ${socketPath} is still held` };\n}\n\nasync function waitForSocketFree(\n socketPath: string,\n budgetMs: number,\n held: (socketPath: string) => Promise<boolean>,\n): Promise<boolean> {\n const deadline = Date.now() + budgetMs;\n for (;;) {\n if (!(await held(socketPath))) return true;\n if (Date.now() >= deadline) return false;\n await sleep(100);\n }\n}\n\n/**\n * True when something still accepts connections on the address. Distinct from\n * {@link vgdIsRunning}: a wedged daemon accepts the connection but never\n * answers ping. A connect left hanging counts as held — limbo is never \"free\".\n */\nfunction vgdSocketHeld(socketPath: string, timeoutMs = 1_000): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = net.createConnection(socketPath);\n let settled = false;\n const done = (heldNow: boolean): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n socket.destroy();\n resolve(heldNow);\n };\n const timer = setTimeout(() => done(true), timeoutMs);\n socket.once('connect', () => done(true));\n socket.once('error', () => done(false));\n });\n}\n\nexport interface StopVgdOptions {\n /**\n * Escalate past a daemon that will not leave politely: SIGTERM, then SIGKILL.\n *\n * Used wherever a surviving daemon is worse than a killed one — `vg update`\n * above all, where every client on the socket would otherwise keep being\n * served by the build that was just replaced. Safe to escalate because\n * `daemon start` is the only thing that ever hosts a vgd listener, so the pid\n * belongs to a daemon process and not to somebody's editor.\n */\n force?: boolean;\n}\n\n/**\n * Stop a running vgd: polite `shutdown` op first, SIGTERM via the pid for\n * daemons that predate the op, then wait (≤5s) for the socket to go quiet.\n *\n * `refused` means the daemon declined remote shutdown (a listener started\n * without a shutdown hook). Without `force` that is where it ends — the pid\n * file belongs to the owning process and is not ours to kill.\n */\nexport async function stopVgd(\n socketPath: string,\n opts: StopVgdOptions = {},\n): Promise<'stopped' | 'not-running' | 'refused' | 'failed'> {\n if (!(await vgdIsRunning({ socketPath }))) return 'not-running';\n // Ask who is on the socket before shutting it down. The pid the daemon\n // reports is authoritative; the pid file can be left over from an earlier\n // process, and signalling that would kill a stranger.\n const livePid = opts.force ? await vgdReportedPid(socketPath) : null;\n let acknowledged = false;\n try {\n const res = await vgdRequest({ op: 'shutdown' }, { socketPath });\n if (res.ok) acknowledged = true;\n else if (res.code === 'shutdown_unsupported' && !opts.force) return 'refused';\n // Any other refusal (an older daemon answers `unknown op`) → pid fallback.\n } catch {\n /* connection dropped mid-shutdown or slow daemon — fall through to pid */\n }\n if (!acknowledged) {\n const pid = signalTarget(livePid);\n if (pid == null) return 'failed';\n if (!signalPid(pid, 'SIGTERM')) return 'failed';\n }\n if (await waitForVgdStop(socketPath, 5_000)) return 'stopped';\n if (!opts.force) return 'failed';\n\n // Wedged: it acknowledged, or took SIGTERM, and is still holding the socket.\n const pid = signalTarget(livePid);\n if (pid == null) return 'failed';\n if (!signalPid(pid, 'SIGKILL')) return 'failed';\n // A SIGKILLed daemon cannot unlink its own socket, but the next `daemon\n // start` clears a stale path before binding, so nothing is left to clean up.\n return (await waitForVgdStop(socketPath, 3_000)) ? 'stopped' : 'failed';\n}\n\n/**\n * The pid to signal, or null when there is nothing safe to signal.\n *\n * Never our own: a daemon hosted in *this* process (an in-process test server,\n * a future embedded listener) would otherwise be \"stopped\" by killing the\n * caller. Such a daemon has to be shut down through its own handle, so report\n * failure and let the caller say so.\n */\nfunction signalTarget(livePid: number | null): number | null {\n const pid = livePid ?? readVgdPid();\n if (pid == null || pid === process.pid) return null;\n return pid;\n}\n\nfunction signalPid(pid: number, signal: NodeJS.Signals): boolean {\n try {\n process.kill(pid, signal);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function waitForVgdStop(socketPath: string, budgetMs: number): Promise<boolean> {\n const deadline = Date.now() + budgetMs;\n while (Date.now() < deadline) {\n await sleep(100);\n if (!(await vgdIsRunning({ socketPath }))) return true;\n }\n return false;\n}\n\n/** The pid the live daemon reports for itself — trusted over the pid file. */\nasync function vgdReportedPid(socketPath: string): Promise<number | null> {\n try {\n const res = await vgdRequest({ op: 'status' }, { socketPath });\n if (!res.ok || !('pid' in res)) return null;\n return Number.isInteger(res.pid) && res.pid > 0 ? res.pid : null;\n } catch {\n return null;\n }\n}\n\nexport interface RestartVgdOptions extends StopVgdOptions {\n /**\n * Start a daemon even when none is running. `vg update` on Windows stops\n * vgd *before* the install so its files can be replaced; afterwards there is\n * nothing to \"re\"-start, but leaving the socket empty both makes the rewarm\n * a no-op and leaves a window for another client to bind an old build.\n */\n startIfNotRunning?: boolean;\n}\n\n/**\n * Restart the local vgd if one is running — used by `vg update` so a freshly\n * installed CLI does not keep serving from a daemon still running the old\n * build. `restarted`/`started` mean a daemon on this build (or newer) was\n * verified on the socket, not merely that something answered ping.\n * Best-effort: never throws.\n */\nexport async function restartVgdIfRunning(\n socketPath: string = vgdSocketPath(),\n opts: RestartVgdOptions = {},\n): Promise<'restarted' | 'started' | 'not-running' | 'refused' | 'failed'> {\n try {\n const stopResult = await stopVgd(socketPath, opts);\n if (stopResult === 'not-running' && !opts.startIfNotRunning) return 'not-running';\n if (stopResult === 'refused') return 'refused';\n if (stopResult === 'failed') return 'failed';\n await startDetachedVgd(socketPath);\n return stopResult === 'not-running' ? 'started' : 'restarted';\n } catch {\n return 'failed';\n }\n}\n\nfunction readVgdPid(): number | null {\n try {\n const raw = fs.readFileSync(vgdPidPath(), 'utf8').trim();\n const pid = Number.parseInt(raw, 10);\n return Number.isInteger(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\n/** Resolve repository id for cwd: register if needed, return workspace id. */\nasync function repositoryIdForCwd(socketPath: string, root: string): Promise<string> {\n const { repositoryIdFromRoot } = await import('../runtime/paths.js');\n const reg = await vgdRequest({ op: 'register', root }, { socketPath });\n if (reg.ok && 'workspace' in reg) return reg.workspace.id;\n return repositoryIdFromRoot(root);\n}\n"]}
|