vigthoria-cli 1.13.20 → 1.13.23

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.
Files changed (187) hide show
  1. package/completions/_vigthoria +49 -0
  2. package/completions/vigthoria.bash +6 -0
  3. package/completions/vigthoria.fish +41 -0
  4. package/dist/commands/auth.d.ts +1 -0
  5. package/dist/commands/auth.js +63 -128
  6. package/dist/commands/background.d.ts +0 -2
  7. package/dist/commands/background.js +26 -34
  8. package/dist/commands/bridge.js +45 -41
  9. package/dist/commands/cancel.d.ts +1 -0
  10. package/dist/commands/cancel.js +22 -16
  11. package/dist/commands/chat.d.ts +3 -42
  12. package/dist/commands/chat.js +378 -1123
  13. package/dist/commands/coding-registration.d.ts +4 -0
  14. package/dist/commands/coding-registration.js +24 -0
  15. package/dist/commands/config.js +23 -29
  16. package/dist/commands/conversation-registration.d.ts +4 -0
  17. package/dist/commands/conversation-registration.js +122 -0
  18. package/dist/commands/deploy.d.ts +8 -2
  19. package/dist/commands/deploy.js +92 -90
  20. package/dist/commands/device.d.ts +1 -2
  21. package/dist/commands/device.js +37 -21
  22. package/dist/commands/doctor-registration.d.ts +4 -0
  23. package/dist/commands/doctor-registration.js +207 -0
  24. package/dist/commands/edit.js +22 -33
  25. package/dist/commands/explain.js +7 -10
  26. package/dist/commands/fork.d.ts +1 -2
  27. package/dist/commands/fork.js +72 -22
  28. package/dist/commands/game.d.ts +1 -1
  29. package/dist/commands/game.js +17 -6
  30. package/dist/commands/generate.js +7 -9
  31. package/dist/commands/history.js +11 -7
  32. package/dist/commands/hub.d.ts +2 -2
  33. package/dist/commands/hub.js +34 -35
  34. package/dist/commands/legion.d.ts +0 -1
  35. package/dist/commands/legion.js +62 -79
  36. package/dist/commands/music.d.ts +1 -2
  37. package/dist/commands/music.js +62 -27
  38. package/dist/commands/platform-registration.d.ts +4 -0
  39. package/dist/commands/platform-registration.js +45 -0
  40. package/dist/commands/preview.d.ts +0 -1
  41. package/dist/commands/preview.js +82 -35
  42. package/dist/commands/product-run-registration.d.ts +4 -0
  43. package/dist/commands/product-run-registration.js +490 -0
  44. package/dist/commands/replay.d.ts +1 -2
  45. package/dist/commands/replay.js +15 -11
  46. package/dist/commands/repo.d.ts +14 -7
  47. package/dist/commands/repo.js +244 -198
  48. package/dist/commands/review.js +9 -12
  49. package/dist/commands/security.d.ts +1 -2
  50. package/dist/commands/security.js +12 -6
  51. package/dist/commands/update-registration.d.ts +3 -0
  52. package/dist/commands/update-registration.js +368 -0
  53. package/dist/commands/v4-registration.d.ts +4 -0
  54. package/dist/commands/v4-registration.js +24 -0
  55. package/dist/commands/v4.d.ts +1 -1
  56. package/dist/commands/v4.js +46 -8
  57. package/dist/commands/wallet.d.ts +1 -3
  58. package/dist/commands/wallet.js +18 -45
  59. package/dist/commands/workflow.d.ts +2 -0
  60. package/dist/commands/workflow.js +52 -39
  61. package/dist/index.js +124 -1589
  62. package/dist/utils/agent-stream-state.d.ts +27 -0
  63. package/dist/utils/agent-stream-state.js +93 -0
  64. package/dist/utils/agentRoute.d.ts +2 -1
  65. package/dist/utils/agentRoute.js +22 -9
  66. package/dist/utils/agentRunOutcome.d.ts +16 -0
  67. package/dist/utils/agentRunOutcome.js +37 -2
  68. package/dist/utils/api-client-factory.d.ts +8 -0
  69. package/dist/utils/api-client-factory.js +8 -0
  70. package/dist/utils/api.d.ts +44 -266
  71. package/dist/utils/api.js +647 -3180
  72. package/dist/utils/auth-session.d.ts +41 -0
  73. package/dist/utils/auth-session.js +224 -0
  74. package/dist/utils/brain-hub-client.d.ts +0 -4
  75. package/dist/utils/brain-hub-client.js +6 -3
  76. package/dist/utils/bridge-client.js +2 -0
  77. package/dist/utils/capability-health-service.d.ts +48 -0
  78. package/dist/utils/capability-health-service.js +64 -0
  79. package/dist/utils/chat-prompt-policy.d.ts +18 -0
  80. package/dist/utils/chat-prompt-policy.js +61 -0
  81. package/dist/utils/chat-tool-call-parser.d.ts +11 -0
  82. package/dist/utils/chat-tool-call-parser.js +71 -0
  83. package/dist/utils/cli-state.d.ts +22 -4
  84. package/dist/utils/cli-state.js +105 -47
  85. package/dist/utils/code-operations-service.d.ts +104 -0
  86. package/dist/utils/code-operations-service.js +837 -0
  87. package/dist/utils/codebase-indexer.d.ts +1 -0
  88. package/dist/utils/codebase-indexer.js +28 -8
  89. package/dist/utils/command-contract.d.ts +61 -0
  90. package/dist/utils/command-contract.js +149 -0
  91. package/dist/utils/command-policy.d.ts +10 -0
  92. package/dist/utils/command-policy.js +54 -0
  93. package/dist/utils/config.d.ts +13 -5
  94. package/dist/utils/config.js +220 -94
  95. package/dist/utils/context-ranker.js +11 -2
  96. package/dist/utils/context-state.d.ts +39 -0
  97. package/dist/utils/context-state.js +52 -0
  98. package/dist/utils/deckEvents.d.ts +0 -5
  99. package/dist/utils/deckEvents.js +3 -2
  100. package/dist/utils/desktop-bridge-client.js +2 -0
  101. package/dist/utils/direct-output-policy.d.ts +3 -0
  102. package/dist/utils/direct-output-policy.js +76 -0
  103. package/dist/utils/durable-json.d.ts +57 -0
  104. package/dist/utils/durable-json.js +319 -0
  105. package/dist/utils/fastAgentRouter.d.ts +5 -6
  106. package/dist/utils/fastAgentRouter.js +17 -25
  107. package/dist/utils/files.js +21 -13
  108. package/dist/utils/frontend-preview-service.d.ts +76 -0
  109. package/dist/utils/frontend-preview-service.js +482 -0
  110. package/dist/utils/goaEvents.d.ts +0 -4
  111. package/dist/utils/goaEvents.js +5 -2
  112. package/dist/utils/logger.d.ts +2 -1
  113. package/dist/utils/logger.js +27 -20
  114. package/dist/utils/mcp-context-client.d.ts +24 -0
  115. package/dist/utils/mcp-context-client.js +58 -0
  116. package/dist/utils/model-governance.d.ts +18 -0
  117. package/dist/utils/model-governance.js +75 -0
  118. package/dist/utils/model-transport-service.d.ts +44 -0
  119. package/dist/utils/model-transport-service.js +111 -0
  120. package/dist/utils/mutation-journal.d.ts +42 -0
  121. package/dist/utils/mutation-journal.js +387 -0
  122. package/dist/utils/network-policy.d.ts +24 -0
  123. package/dist/utils/network-policy.js +202 -0
  124. package/dist/utils/operator-client.d.ts +45 -0
  125. package/dist/utils/operator-client.js +159 -0
  126. package/dist/utils/post-write-validator.js +7 -9
  127. package/dist/utils/preview-screenshot-adapter.d.ts +15 -0
  128. package/dist/utils/preview-screenshot-adapter.js +51 -0
  129. package/dist/utils/process-policy.d.ts +23 -0
  130. package/dist/utils/process-policy.js +284 -0
  131. package/dist/utils/project-memory.d.ts +13 -3
  132. package/dist/utils/project-memory.js +70 -17
  133. package/dist/utils/prompt-workspace-resolver.d.ts +14 -0
  134. package/dist/utils/prompt-workspace-resolver.js +64 -0
  135. package/dist/utils/release-install.d.ts +11 -0
  136. package/dist/utils/release-install.js +155 -0
  137. package/dist/utils/release-policy.d.ts +64 -0
  138. package/dist/utils/release-policy.js +293 -0
  139. package/dist/utils/requestIntent.js +22 -3
  140. package/dist/utils/runtime-capability.d.ts +8 -0
  141. package/dist/utils/runtime-capability.js +16 -0
  142. package/dist/utils/runtime-temp.d.ts +76 -0
  143. package/dist/utils/runtime-temp.js +492 -0
  144. package/dist/utils/secret-policy.d.ts +20 -0
  145. package/dist/utils/secret-policy.js +160 -0
  146. package/dist/utils/session.d.ts +17 -3
  147. package/dist/utils/session.js +354 -110
  148. package/dist/utils/tool-approval-service.d.ts +17 -0
  149. package/dist/utils/tool-approval-service.js +78 -0
  150. package/dist/utils/tool-capability-providers.d.ts +57 -0
  151. package/dist/utils/tool-capability-providers.js +57 -0
  152. package/dist/utils/tools.d.ts +2 -23
  153. package/dist/utils/tools.js +226 -512
  154. package/dist/utils/update-policy.d.ts +18 -0
  155. package/dist/utils/update-policy.js +137 -0
  156. package/dist/utils/v3-agent-client.d.ts +40 -0
  157. package/dist/utils/v3-agent-client.js +165 -0
  158. package/dist/utils/v3-workspace-service.d.ts +28 -0
  159. package/dist/utils/v3-workspace-service.js +279 -0
  160. package/dist/utils/vigflow-client.d.ts +95 -0
  161. package/dist/utils/vigflow-client.js +105 -0
  162. package/dist/utils/workspace-boundary.d.ts +45 -0
  163. package/dist/utils/workspace-boundary.js +377 -0
  164. package/dist/utils/workspace-brain-service.d.ts +2 -0
  165. package/dist/utils/workspace-brain-service.js +11 -1
  166. package/dist/utils/workspace-cache.js +37 -15
  167. package/dist/utils/workspace-stream.js +35 -10
  168. package/install.ps1 +115 -142
  169. package/install.sh +112 -81
  170. package/package.json +43 -9
  171. package/release-policy.json +43 -0
  172. package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
  173. package/scripts/release/generate-completions.mjs +24 -0
  174. package/scripts/release/install-release.mjs +10 -0
  175. package/scripts/release/publish-cli-release.mjs +116 -0
  176. package/scripts/release/publish-cli-release.sh +2 -70
  177. package/scripts/release/resolve-release-manifest.mjs +26 -0
  178. package/scripts/release/test-balanced-model-live.sh +45 -0
  179. package/scripts/release/validate-live-service-gates.sh +93 -0
  180. package/scripts/release/validate-no-go-gates.sh +145 -174
  181. package/scripts/release/verify-runtime-consistency.mjs +4 -1
  182. package/dist/commands/index.d.ts +0 -12
  183. package/dist/commands/index.js +0 -194
  184. package/dist/commands/update.d.ts +0 -9
  185. package/dist/commands/update.js +0 -301
  186. package/dist/utils/templateInstantPath.d.ts +0 -18
  187. package/dist/utils/templateInstantPath.js +0 -228
package/install.sh CHANGED
@@ -28,32 +28,57 @@ fi
28
28
  # Configuration
29
29
  CLI_VERSION="1.13.20"
30
30
  INSTALL_DIR="$HOME/.vigthoria"
31
- REPO_URL="https://market.vigthoria.io/vigthoria/vigthoria-cli"
32
- GIT_PACKAGE_URL="git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
33
31
  MANIFEST_URL="${VIGTHORIA_UPDATE_MANIFEST_URL:-https://extension.vigthoria.io/downloads/manifest.json}"
34
32
  HOSTED_TARBALL_URL="https://extension.vigthoria.io/downloads/vigthoria-cli-${CLI_VERSION}.tgz"
35
33
  HOSTED_TARBALL_SHA256=""
34
+ INSTALLER_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd || true)"
35
+ RELEASE_RESOLVER="$INSTALLER_ROOT/scripts/release/resolve-release-manifest.mjs"
36
+ RELEASE_INSTALLER="$INSTALLER_ROOT/scripts/release/install-release.mjs"
37
+
38
+ validate_release_url() {
39
+ python3 - "$1" <<'PY'
40
+ import sys
41
+ from urllib.parse import urlsplit
42
+ allowed = {
43
+ 'extension.vigthoria.io', 'landing.vigthoria.io', 'cli.vigthoria.io',
44
+ 'coder.vigthoria.io', 'market.vigthoria.io', 'registry.npmjs.org',
45
+ }
46
+ try:
47
+ parsed = urlsplit(sys.argv[1])
48
+ valid = parsed.scheme == 'https' and parsed.hostname in allowed and parsed.port in (None, 443) and not parsed.username and not parsed.password and '\\' not in sys.argv[1]
49
+ except Exception:
50
+ valid = False
51
+ raise SystemExit(0 if valid else 1)
52
+ PY
53
+ }
36
54
 
37
55
  resolve_release_manifest() {
38
- if ! command -v curl >/dev/null 2>&1 || ! command -v python3 >/dev/null 2>&1; then
56
+ # Direct artifacts are accepted only when the packaged shared verifier is
57
+ # present and validates the strict manifest plus detached Ed25519 signature.
58
+ # A curl-piped legacy installer therefore falls back to the exact pinned npm
59
+ # version instead of trusting an unsigned manifest.
60
+ if [[ ! -f "$RELEASE_RESOLVER" ]] || ! command -v node >/dev/null 2>&1 || ! command -v python3 >/dev/null 2>&1; then
39
61
  return 0
40
62
  fi
41
63
 
42
- local manifest_json
43
- manifest_json="$(curl -fsSL "$MANIFEST_URL" 2>/dev/null || true)"
44
- if [[ -z "$manifest_json" ]]; then
64
+ if ! validate_release_url "$MANIFEST_URL"; then
65
+ echo "Refusing untrusted release manifest URL" >&2
66
+ exit 1
67
+ fi
68
+ local resolved_json
69
+ resolved_json="$(node "$RELEASE_RESOLVER" "$MANIFEST_URL" stable 2>/dev/null || true)"
70
+ if [[ -z "$resolved_json" ]]; then
45
71
  return 0
46
72
  fi
47
73
 
48
74
  local resolved
49
- resolved="$(printf '%s' "$manifest_json" | python3 -c "
75
+ resolved="$(printf '%s' "$resolved_json" | python3 -c "
50
76
  import json, sys
51
77
  try:
52
78
  data = json.load(sys.stdin)
53
- stable = (data.get('channels') or {}).get('stable') or {}
54
- version = str(stable.get('version') or '').strip()
55
- url = str(stable.get('url') or '').strip()
56
- sha256 = str(stable.get('sha256') or '').strip().lower()
79
+ version = str(data.get('version') or '').strip()
80
+ url = str(data.get('url') or '').strip()
81
+ sha256 = str(data.get('sha256') or '').strip().lower()
57
82
  if version:
58
83
  print(version)
59
84
  if url:
@@ -74,6 +99,10 @@ except Exception:
74
99
  CLI_VERSION="$manifest_version"
75
100
  fi
76
101
  if [[ -n "$manifest_url" ]]; then
102
+ if ! validate_release_url "$manifest_url"; then
103
+ echo "Refusing untrusted release artifact URL" >&2
104
+ exit 1
105
+ fi
77
106
  HOSTED_TARBALL_URL="$manifest_url"
78
107
  elif [[ -n "$manifest_version" ]]; then
79
108
  HOSTED_TARBALL_URL="https://extension.vigthoria.io/downloads/vigthoria-cli-${CLI_VERSION}.tgz"
@@ -182,6 +211,41 @@ check_requirements() {
182
211
  }
183
212
 
184
213
  # Install CLI
214
+ prepare_temp_root() {
215
+ local requested_root="${VIGTHORIA_TEMP_DIR:-$HOME/.vigthoria/tmp}"
216
+ case "$requested_root" in
217
+ /*) ;;
218
+ *) echo -e "${RED}VIGTHORIA_TEMP_DIR must be an absolute local path${NC}" >&2; return 1 ;;
219
+ esac
220
+ if [[ "$requested_root" == "/" || "$requested_root" == "${TMPDIR:-/tmp}" ]]; then
221
+ echo -e "${RED}Refusing shared or filesystem-root temporary storage${NC}" >&2
222
+ return 1
223
+ fi
224
+ mkdir -p "$requested_root"
225
+ local path_cursor="$requested_root"
226
+ while [[ "$path_cursor" != "/" ]]; do
227
+ if [[ -L "$path_cursor" ]]; then
228
+ echo -e "${RED}Refusing a symbolic-link temporary storage path${NC}" >&2
229
+ return 1
230
+ fi
231
+ path_cursor="$(dirname -- "$path_cursor")"
232
+ done
233
+ local resolved_root resolved_home
234
+ resolved_root="$(cd "$requested_root" && pwd -P)"
235
+ resolved_home="$(cd "$HOME" && pwd -P)"
236
+ case "$resolved_root" in
237
+ /tmp|/var/tmp|/usr/tmp) echo -e "${RED}Refusing shared temporary storage${NC}" >&2; return 1 ;;
238
+ esac
239
+ if [[ -z "${VIGTHORIA_TEMP_DIR:-}" ]]; then
240
+ case "$resolved_root/" in
241
+ "$resolved_home/"*) ;;
242
+ *) echo -e "${RED}Default temporary storage escaped the user home${NC}" >&2; return 1 ;;
243
+ esac
244
+ fi
245
+ chmod 700 "$resolved_root"
246
+ printf '%s\n' "$resolved_root"
247
+ }
248
+
185
249
  install_cli() {
186
250
  echo -e "${CYAN}Installing Vigthoria CLI...${NC}"
187
251
 
@@ -191,9 +255,14 @@ install_cli() {
191
255
  # Option 1: Download and verify the exact hosted release package.
192
256
  if [[ -n "$HOSTED_TARBALL_SHA256" ]]; then
193
257
  echo "Downloading checksum-verified hosted release package..."
194
- RELEASE_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/vigthoria-cli-install.XXXXXX")"
258
+ VIGTHORIA_INSTALL_TEMP_ROOT="$(prepare_temp_root)" || return 1
259
+ RELEASE_TMP_DIR="$(mktemp -d "$VIGTHORIA_INSTALL_TEMP_ROOT/install.XXXXXX")"
195
260
  RELEASE_ARCHIVE="$RELEASE_TMP_DIR/vigthoria-cli-${CLI_VERSION}.tgz"
196
- if ! curl -fsSL "$HOSTED_TARBALL_URL" -o "$RELEASE_ARCHIVE"; then
261
+ if ! validate_release_url "$HOSTED_TARBALL_URL"; then
262
+ echo -e "${RED}Refusing untrusted release artifact URL${NC}"
263
+ return 1
264
+ fi
265
+ if ! curl -fsS --proto '=https' --max-redirs 0 "$HOSTED_TARBALL_URL" -o "$RELEASE_ARCHIVE"; then
197
266
  rm -rf "$RELEASE_TMP_DIR"
198
267
  echo -e "${RED}✗ Failed to download verified release package${NC}"
199
268
  exit 1
@@ -212,42 +281,23 @@ install_cli() {
212
281
  echo -e "${RED}✗ Release checksum verification failed${NC}"
213
282
  exit 1
214
283
  fi
215
- npm install -g --force "$RELEASE_ARCHIVE"
284
+ if [[ -f "$RELEASE_INSTALLER" ]]; then
285
+ node "$RELEASE_INSTALLER" "$RELEASE_ARCHIVE" "$CLI_VERSION"
286
+ else
287
+ echo -e "${RED}✗ Transactional release installer is unavailable${NC}"
288
+ exit 1
289
+ fi
216
290
  rm -rf "$RELEASE_TMP_DIR"
217
- elif npm view vigthoria-cli version &> /dev/null; then
218
- echo "Installing from npm registry..."
219
- npm install -g --force vigthoria-cli
220
- elif npm install -g --force "$GIT_PACKAGE_URL"; then
221
- echo "Installed from git package fallback."
222
- else
223
- # Option 2: Install from local or git
224
- echo "Installing from source..."
225
-
226
- # Check if we're in the CLI directory
227
- if [ -f "package.json" ] && grep -q '"name": "vigthoria-cli"' package.json; then
228
- echo "Installing from current directory..."
229
- npm install
230
- npm run build
231
- npm link
291
+ elif npm view --registry=https://registry.npmjs.org/ "vigthoria-cli@${CLI_VERSION}" version &> /dev/null; then
292
+ echo "Installing exact version ${CLI_VERSION} from npm registry..."
293
+ if [[ -f "$RELEASE_INSTALLER" ]]; then
294
+ node "$RELEASE_INSTALLER" "vigthoria-cli@${CLI_VERSION}" "$CLI_VERSION"
232
295
  else
233
- # Clone from repo
234
- echo "Cloning from repository..."
235
- git clone "$REPO_URL" "$INSTALL_DIR/cli" 2>/dev/null || {
236
- echo -e "${YELLOW}Repository not available, using local install${NC}"
237
- # Copy local files for development
238
- SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
239
- if [ -d "$SCRIPT_DIR/../src" ]; then
240
- cp -r "$SCRIPT_DIR/.." "$INSTALL_DIR/cli"
241
- fi
242
- }
243
-
244
- if [ -d "$INSTALL_DIR/cli" ]; then
245
- cd "$INSTALL_DIR/cli"
246
- npm install
247
- npm run build
248
- npm link
249
- fi
296
+ npm install -g --force --registry=https://registry.npmjs.org/ "vigthoria-cli@${CLI_VERSION}"
250
297
  fi
298
+ else
299
+ echo -e "${RED}✗ No checksum-verified artifact or exact npm release ${CLI_VERSION} is available${NC}"
300
+ return 1
251
301
  fi
252
302
 
253
303
  echo -e "${GREEN}✓ Installation complete${NC}"
@@ -280,55 +330,36 @@ create_symlinks() {
280
330
  # Setup shell completion
281
331
  setup_completion() {
282
332
  echo -e "${CYAN}Setting up shell completion...${NC}"
283
-
284
- # Detect shell
333
+ COMPLETION_ROOT="$INSTALLER_ROOT/completions"
334
+ if [[ ! -d "$COMPLETION_ROOT" ]] && [[ -d "$HOME/.vigthoria/cli/current/node_modules/vigthoria-cli/completions" ]]; then
335
+ COMPLETION_ROOT="$HOME/.vigthoria/cli/current/node_modules/vigthoria-cli/completions"
336
+ fi
337
+ if [[ ! -d "$COMPLETION_ROOT" ]]; then
338
+ echo -e "${YELLOW}⚠ Generated completions are unavailable; no stale static list was installed.${NC}"
339
+ return 0
340
+ fi
285
341
  SHELL_NAME=$(basename "$SHELL")
286
-
287
342
  case "$SHELL_NAME" in
288
343
  bash)
289
344
  COMPLETION_FILE="$HOME/.bash_completion.d/vigthoria"
290
345
  mkdir -p "$HOME/.bash_completion.d"
291
- cat > "$COMPLETION_FILE" << 'EOF'
292
- _vigthoria_completions() {
293
- local cur="${COMP_WORDS[COMP_CWORD]}"
294
- local commands="chat edit generate explain fix review login logout status config init"
295
- COMPREPLY=($(compgen -W "$commands" -- "$cur"))
296
- }
297
- complete -F _vigthoria_completions vigthoria
298
- complete -F _vigthoria_completions vig
299
- EOF
346
+ install -m 0644 "$COMPLETION_ROOT/vigthoria.bash" "$COMPLETION_FILE"
300
347
  echo -e "${GREEN}✓ Bash completion installed${NC}"
301
348
  echo " Run: source ~/.bash_completion.d/vigthoria"
302
349
  ;;
303
350
  zsh)
304
351
  COMPLETION_FILE="$HOME/.zsh/completion/_vigthoria"
305
352
  mkdir -p "$HOME/.zsh/completion"
306
- cat > "$COMPLETION_FILE" << 'EOF'
307
- #compdef vigthoria vig
308
-
309
- _vigthoria() {
310
- local -a commands
311
- commands=(
312
- 'chat:Start interactive chat with AI'
313
- 'edit:Edit a file with AI assistance'
314
- 'generate:Generate code from description'
315
- 'explain:Explain code in a file'
316
- 'fix:Fix issues in a file'
317
- 'review:Review code quality'
318
- 'login:Login to Vigthoria'
319
- 'logout:Logout from Vigthoria'
320
- 'status:Show account status'
321
- 'config:Configure settings'
322
- 'init:Initialize project'
323
- )
324
- _describe 'command' commands
325
- }
326
-
327
- _vigthoria "$@"
328
- EOF
353
+ install -m 0644 "$COMPLETION_ROOT/_vigthoria" "$COMPLETION_FILE"
329
354
  echo -e "${GREEN}✓ Zsh completion installed${NC}"
330
355
  echo " Add to ~/.zshrc: fpath=(~/.zsh/completion \$fpath)"
331
356
  ;;
357
+ fish)
358
+ COMPLETION_FILE="$HOME/.config/fish/completions/vigthoria.fish"
359
+ mkdir -p "$HOME/.config/fish/completions"
360
+ install -m 0644 "$COMPLETION_ROOT/vigthoria.fish" "$COMPLETION_FILE"
361
+ echo -e "${GREEN}✓ Fish completion installed${NC}"
362
+ ;;
332
363
  *)
333
364
  echo -e "${YELLOW}⚠ Shell completion not available for $SHELL_NAME${NC}"
334
365
  ;;
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.13.20",
3
+ "version": "1.13.23",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "files": [
8
8
  "dist",
9
+ "completions",
10
+ "release-policy.json",
9
11
  "scripts/release",
10
12
  "README.md",
11
13
  "SECURITY_HARDENING.md",
@@ -16,6 +18,8 @@
16
18
  "publishConfig": {
17
19
  "files": [
18
20
  "dist/",
21
+ "completions/",
22
+ "release-policy.json",
19
23
  "scripts/release/",
20
24
  "README.md",
21
25
  "SECURITY_HARDENING.md",
@@ -32,10 +36,14 @@
32
36
  },
33
37
  "scripts": {
34
38
  "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
35
- "build": "npm run clean && tsc && node -e \"const fs=require('fs'); try { fs.chmodSync('dist/index.js', 0o755); } catch (error) { if (!error || error.code !== 'ENOENT') throw error; }\"",
39
+ "build": "npm run clean && tsc && node scripts/release/generate-completions.mjs && node -e \"const fs=require('fs'); try { fs.chmodSync('dist/index.js', 0o755); } catch (error) { if (!error || error.code !== 'ENOENT') throw error; }\"",
36
40
  "start": "node dist/index.js",
37
41
  "dev": "ts-node src/index.ts",
38
- "test": "npm run test:cli",
42
+ "test": "npm run test:hermetic",
43
+ "test:hermetic": "npm run validate:no-go",
44
+ "test:integration:local": "npm run build && node scripts/run-test-suite.mjs local",
45
+ "test:live:all": "npm run build && node scripts/run-test-suite.mjs live",
46
+ "test:suite:policy": "node scripts/run-test-suite.mjs check",
39
47
  "test:agent:outcome": "npm run build && node scripts/test-agent-run-outcome.js",
40
48
  "test:cli": "npm run build && npm run precheck:services && node scripts/test-cli-suite.js && npm run test:agent:outcome && npm run test:v3-stream-mutation",
41
49
  "test:regression": "npm run build && node scripts/test-regression-1.6.22.js",
@@ -62,6 +70,8 @@
62
70
  "test:repo:live": "npm run build && node scripts/test-live-repo-e2e.js",
63
71
  "test:repo:auth-fallback": "node scripts/test-community-repo-auth-fallback.mjs",
64
72
  "test:repo:payload-fallback": "node scripts/test-repo-payload-fallback.mjs",
73
+ "test:repo:public-clone": "npm run build && node scripts/test-public-repo-clone.mjs",
74
+ "test:command:timeouts": "npm run build && node scripts/test-timeout-cancellation.mjs",
65
75
  "test:game:live": "npm run build && node scripts/test-live-game-push.js",
66
76
  "proof:agent": "npm run build && node scripts/proof-agent-mode.js",
67
77
  "test:fresh-install": "node scripts/test-fresh-install.js",
@@ -69,6 +79,8 @@
69
79
  "precheck:services": "node scripts/precheck-local-services.js",
70
80
  "test:model:governance": "npm run build && node scripts/test-model-governance-no-agent.js",
71
81
  "validate:no-go": "bash scripts/release/validate-no-go-gates.sh",
82
+ "test:model:balanced-live": "bash scripts/release/test-balanced-model-live.sh",
83
+ "test:release:live-services": "bash scripts/release/validate-live-service-gates.sh",
72
84
  "test:legion:billing:e2e": "npm run build && node scripts/test-legion-godmode-billing-e2e.js",
73
85
  "test:windows:v3-sync": "npm run build && node scripts/test-windows-v3-sync-recovery.js",
74
86
  "test:v3-workspace-path": "npm run build && node scripts/test-v3-workspace-path.js",
@@ -79,7 +91,22 @@
79
91
  "test:context:budget": "npm run build && node scripts/test-context-budget.js",
80
92
  "test:v3-client-tool-quality": "npm run build && node scripts/test-v3-client-tool-quality.mjs",
81
93
  "test:pitfall:context": "npm run build && node scripts/test-pitfall-context-smoke.js",
82
- "test:game:command": "node scripts/test-game-command.mjs"
94
+ "test:game:command": "node scripts/test-game-command.mjs",
95
+ "test:security:dependencies": "node scripts/test-dependency-security.mjs",
96
+ "test:security:network": "npm run build && node scripts/test-network-policy.mjs && node scripts/test-installer-trust-policy.mjs",
97
+ "test:security:workspace": "npm run build && node scripts/test-workspace-archive-containment.mjs",
98
+ "test:security:process": "npm run build && node scripts/test-process-approval-safety.mjs",
99
+ "test:security:mutation-preview": "npm run build && node scripts/test-mutation-preview-transaction.mjs",
100
+ "test:security:context-secrets": "npm run build && node scripts/test-context-secret-hygiene.mjs",
101
+ "test:architecture:vigflow": "npm run build && node scripts/test-vigflow-client.mjs",
102
+ "test:state:durable": "npm run build && node scripts/test-durable-json-state.mjs",
103
+ "test:state:auth": "npm run build && node scripts/test-auth-state.mjs",
104
+ "test:state:sessions": "npm run build && node scripts/test-session-durable-lifecycle.mjs && node scripts/test-session-project-match.mjs && node scripts/test-external-client-resume.mjs",
105
+ "test:state:context": "npm run build && node scripts/test-context-state-ownership.mjs && node scripts/test-context-secret-hygiene.mjs",
106
+ "test:phase3:command-contract": "npm run build && node scripts/test-command-contract.mjs",
107
+ "test:phase3:update-policy": "npm run build && node scripts/test-update-policy.mjs",
108
+ "test:phase6:delivery": "npm run build && node scripts/test-release-delivery.mjs",
109
+ "architecture:graph": "node scripts/architecture/verify-import-graph.mjs"
83
110
  },
84
111
  "keywords": [
85
112
  "ai",
@@ -93,7 +120,6 @@
93
120
  "author": "Vigthoria Technologies",
94
121
  "license": "MIT",
95
122
  "dependencies": {
96
- "archiver": "^8.0.0",
97
123
  "axios": "^1.6.0",
98
124
  "chalk": "^5.3.0",
99
125
  "chokidar": "^5.0.0",
@@ -105,12 +131,9 @@
105
131
  "marked": "^11.0.0",
106
132
  "marked-terminal": "^6.2.0",
107
133
  "ora": "^7.0.1",
108
- "rxjs": "^7.8.2",
109
- "simple-git": "^3.21.0",
110
134
  "ws": "^8.14.2"
111
135
  },
112
136
  "devDependencies": {
113
- "@types/archiver": "^6.0.2",
114
137
  "@types/diff": "^5.0.8",
115
138
  "@types/inquirer": "^9.0.7",
116
139
  "@types/node": "^20.10.0",
@@ -119,11 +142,22 @@
119
142
  "ts-node": "^10.9.2",
120
143
  "typescript": "^5.3.2"
121
144
  },
145
+ "peerDependencies": {
146
+ "puppeteer": "^24.40.0"
147
+ },
148
+ "peerDependenciesMeta": {
149
+ "puppeteer": {
150
+ "optional": true
151
+ }
152
+ },
122
153
  "engines": {
123
154
  "node": ">=20.19.0"
124
155
  },
125
156
  "overrides": {
126
157
  "glob": "^13.0.6",
127
- "brace-expansion": "^5.0.8"
158
+ "brace-expansion": "5.0.9",
159
+ "fast-uri": "3.1.5",
160
+ "ip-address": "10.3.1",
161
+ "js-yaml": "4.3.1"
128
162
  }
129
163
  }
@@ -0,0 +1,43 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "packageName": "vigthoria-cli",
4
+ "manifest": {
5
+ "schemaVersion": 1,
6
+ "maximumBytes": 262144,
7
+ "requiredChannels": ["stable"],
8
+ "allowedChannels": ["stable", "candidate"]
9
+ },
10
+ "origins": {
11
+ "manifest": "https://extension.vigthoria.io/downloads/manifest.json",
12
+ "artifacts": "https://extension.vigthoria.io/downloads/",
13
+ "allowedHosts": [
14
+ "extension.vigthoria.io",
15
+ "cli.vigthoria.io",
16
+ "coder.vigthoria.io",
17
+ "landing.vigthoria.io",
18
+ "market.vigthoria.io"
19
+ ],
20
+ "port": 443,
21
+ "maximumRedirects": 0
22
+ },
23
+ "artifact": {
24
+ "maximumBytes": 104857600,
25
+ "filenamePattern": "^vigthoria-cli-(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?\\.tgz$"
26
+ },
27
+ "signature": {
28
+ "algorithm": "Ed25519",
29
+ "trustedKeys": {
30
+ "vigthoria-release-2026-01": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAotTXdcHwZ+D1z5lJMdgAAeMU99BRdMCaCZ465DN2aug=\n-----END PUBLIC KEY-----\n"
31
+ }
32
+ },
33
+ "channels": {
34
+ "stable": { "allowPrerelease": false, "allowDowngrade": false },
35
+ "candidate": { "allowPrerelease": true, "allowDowngrade": false }
36
+ },
37
+ "installation": {
38
+ "versionsDirectory": ".vigthoria/cli/versions",
39
+ "currentLink": ".vigthoria/cli/current",
40
+ "binDirectory": ".local/bin",
41
+ "preservePrevious": 1
42
+ }
43
+ }
@@ -85,7 +85,7 @@ Commands:
85
85
 
86
86
  ```bash
87
87
  vigthoria hyper-loop status
88
- vigthoria devtools connect
88
+ vigthoria devtools status
89
89
  vigthoria bridge status
90
90
  vigthoria operator --prompt "status check" --json
91
91
  ```
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
7
+ const manifest = JSON.parse(fs.readFileSync(path.join(root, 'contracts/phase-0/command-manifest.json'), 'utf8'));
8
+ const commands = manifest.commands
9
+ .filter((command) => !command.path.includes(' '))
10
+ .map((command) => command.path)
11
+ .sort();
12
+ const descriptions = new Map(manifest.commands.filter((command) => !command.path.includes(' ')).map((command) => [command.path, command.description || 'Vigthoria command']));
13
+ if (commands.length !== new Set(commands).size || commands.length === 0) throw new Error('Authoritative command manifest has duplicate or missing top-level commands.');
14
+
15
+ const bash = `# Generated from contracts/phase-0/command-manifest.json; do not edit.\n_vigthoria_completions() {\n local cur="\${COMP_WORDS[COMP_CWORD]}"\n COMPREPLY=( $(compgen -W '${commands.join(' ')}' -- "$cur") )\n}\ncomplete -F _vigthoria_completions vigthoria vig vigthoria-chat\n`;
16
+ const zshRows = commands.map((command) => ` '${command.replaceAll("'", "''")}:${String(descriptions.get(command)).replaceAll("'", "''")}'`).join('\n');
17
+ const zsh = `#compdef vigthoria vig vigthoria-chat\n# Generated from contracts/phase-0/command-manifest.json; do not edit.\n_vigthoria() {\n local -a commands\n commands=(\n${zshRows}\n )\n _describe 'command' commands\n}\n_vigthoria "$@"\n`;
18
+ const fish = `# Generated from contracts/phase-0/command-manifest.json; do not edit.\n${commands.map((command) => `complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a '${command}' -d '${String(descriptions.get(command)).replaceAll("'", "\\'")}'`).join('\n')}\n`;
19
+ const output = path.join(root, 'completions');
20
+ fs.mkdirSync(output, { recursive: true });
21
+ fs.writeFileSync(path.join(output, 'vigthoria.bash'), bash);
22
+ fs.writeFileSync(path.join(output, '_vigthoria'), zsh);
23
+ fs.writeFileSync(path.join(output, 'vigthoria.fish'), fish);
24
+ console.log(`Generated bash, zsh, and fish completion definitions for ${commands.length} commands.`);
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import { installReleaseTransaction } from '../../dist/utils/release-install.js';
3
+
4
+ const packageSpec = String(process.argv[2] || '');
5
+ const expectedVersion = String(process.argv[3] || '');
6
+ if (!packageSpec || !expectedVersion) throw new Error('Usage: install-release.mjs <package-spec> <expected-version>');
7
+ const result = installReleaseTransaction(packageSpec, expectedVersion, {
8
+ ...(packageSpec.startsWith('vigthoria-cli@') ? { npmRegistry: 'https://registry.npmjs.org/' } : {}),
9
+ });
10
+ process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { createHash, createPrivateKey, createPublicKey, sign } from 'node:crypto';
5
+ import { spawnSync } from 'node:child_process';
6
+ import { fileURLToPath } from 'node:url';
7
+ import {
8
+ getReleasePolicy,
9
+ parseReleaseManifest,
10
+ releaseSignaturePayload,
11
+ verifyReleaseSignature,
12
+ } from '../../dist/utils/release-policy.js';
13
+
14
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
15
+ const version = String(process.argv[2] || '').trim();
16
+ const channel = String(process.env.CHANNEL || 'stable').trim();
17
+ const downloadsDirectory = String(process.env.HOST_DOWNLOADS_DIR || '');
18
+ const manifestFile = String(process.env.HOST_MANIFEST_FILE || '');
19
+ const privateKeyFile = String(process.env.RELEASE_SIGNING_PRIVATE_KEY_FILE || '');
20
+ const keyId = String(process.env.RELEASE_SIGNING_KEY_ID || '');
21
+ const sbomFile = String(process.env.RELEASE_SBOM_FILE || '');
22
+ const provenanceFile = String(process.env.RELEASE_PROVENANCE_FILE || '');
23
+ const policy = getReleasePolicy();
24
+
25
+ function stop(message) { throw new Error(message); }
26
+ function digest(file) { return createHash('sha256').update(fs.readFileSync(file)).digest('hex'); }
27
+ function requiredFile(file, label) { if (!file || !fs.statSync(file, { throwIfNoEntry: false })?.isFile()) stop(`${label} is required: ${file || '(unset)'}`); }
28
+ function exactPackageMetadata(archive) {
29
+ const result = spawnSync('tar', ['-xOf', archive, 'package/package.json'], {
30
+ cwd: root, encoding: 'utf8', timeout: 15_000, maxBuffer: 1024 * 1024,
31
+ });
32
+ if (result.status !== 0) stop(`Unable to inspect archive metadata: ${result.stderr || result.stdout}`);
33
+ const metadata = JSON.parse(result.stdout);
34
+ return { name: String(metadata.name || ''), version: String(metadata.version || '') };
35
+ }
36
+
37
+ if (!version) stop('Usage: publish-cli-release.sh <version>');
38
+ if (!downloadsDirectory || !manifestFile) stop('HOST_DOWNLOADS_DIR and HOST_MANIFEST_FILE are required.');
39
+ requiredFile(privateKeyFile, 'RELEASE_SIGNING_PRIVATE_KEY_FILE');
40
+ requiredFile(sbomFile, 'RELEASE_SBOM_FILE');
41
+ requiredFile(provenanceFile, 'RELEASE_PROVENANCE_FILE');
42
+ if (!Object.hasOwn(policy.signature.trustedKeys, keyId)) stop(`RELEASE_SIGNING_KEY_ID is not trusted by release-policy.json: ${keyId || '(unset)'}`);
43
+
44
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
45
+ const lock = JSON.parse(fs.readFileSync(path.join(root, 'package-lock.json'), 'utf8'));
46
+ if ([pkg.version, lock.version, lock.packages?.['']?.version].some((identity) => identity !== version)) stop('Requested version conflicts with package.json or package-lock.json.');
47
+ const runtime = spawnSync(process.execPath, ['dist/index.js', '--version'], { cwd: root, encoding: 'utf8', env: { ...process.env, VIGTHORIA_OFFLINE: '1', VIGTHORIA_NO_BANNER: '1' } });
48
+ if (runtime.status !== 0 || runtime.stdout.trim() !== version) stop('Requested version conflicts with the built CLI banner.');
49
+
50
+ const archiveFilename = `${policy.packageName}-${version}.tgz`;
51
+ const archive = path.join(root, archiveFilename);
52
+ requiredFile(archive, 'Release archive');
53
+ const metadata = exactPackageMetadata(archive);
54
+ if (metadata.name !== policy.packageName || metadata.version !== version) stop('Requested version conflicts with archive metadata.');
55
+
56
+ fs.mkdirSync(downloadsDirectory, { recursive: true });
57
+ fs.mkdirSync(path.dirname(manifestFile), { recursive: true });
58
+ const lockPath = `${manifestFile}.lock`;
59
+ let lockHandle;
60
+ const published = [];
61
+ try {
62
+ lockHandle = fs.openSync(lockPath, 'wx', 0o600);
63
+ const suffix = `${process.pid}-${Date.now()}`;
64
+ const publicBase = new URL(policy.origins.artifacts);
65
+ const signatureFilename = `${archiveFilename}.sig`;
66
+ const sbomFilename = `${archiveFilename}.sbom.json`;
67
+ const provenanceFilename = `${archiveFilename}.provenance.json`;
68
+ const entry = {
69
+ version,
70
+ url: new URL(archiveFilename, publicBase).toString(),
71
+ sha256: digest(archive),
72
+ size: fs.statSync(archive).size,
73
+ archiveFilename,
74
+ packageName: policy.packageName,
75
+ packageVersion: version,
76
+ publishedAt: new Date().toISOString(),
77
+ signature: { algorithm: policy.signature.algorithm, keyId, url: new URL(signatureFilename, publicBase).toString() },
78
+ sbom: { url: new URL(sbomFilename, publicBase).toString(), sha256: digest(sbomFile) },
79
+ provenance: { url: new URL(provenanceFilename, publicBase).toString(), sha256: digest(provenanceFile) },
80
+ notes: String(process.env.RELEASE_NOTES || 'Vigthoria CLI release'),
81
+ };
82
+ const privateKey = createPrivateKey(fs.readFileSync(privateKeyFile));
83
+ const configuredPublic = createPublicKey(policy.signature.trustedKeys[keyId]).export({ type: 'spki', format: 'der' });
84
+ const signingPublic = createPublicKey(privateKey).export({ type: 'spki', format: 'der' });
85
+ if (!configuredPublic.equals(signingPublic)) stop('Signing private key does not match the configured verification key.');
86
+ const detached = sign(null, releaseSignaturePayload(channel, entry), privateKey).toString('base64');
87
+ verifyReleaseSignature(channel, entry, detached);
88
+
89
+ let manifest = { schemaVersion: policy.manifest.schemaVersion, channels: {} };
90
+ if (fs.existsSync(manifestFile)) manifest = JSON.parse(fs.readFileSync(manifestFile, 'utf8'));
91
+ manifest.channels = { ...manifest.channels, [channel]: entry };
92
+ parseReleaseManifest(manifest, channel);
93
+
94
+ const inputs = [[archive, archiveFilename], [sbomFile, sbomFilename], [provenanceFile, provenanceFilename]];
95
+ const staged = [];
96
+ for (const [source, filename] of inputs) {
97
+ const temporary = path.join(downloadsDirectory, `.${filename}.${suffix}.tmp`);
98
+ fs.copyFileSync(source, temporary, fs.constants.COPYFILE_EXCL);
99
+ staged.push([temporary, path.join(downloadsDirectory, filename)]);
100
+ }
101
+ const signatureTemporary = path.join(downloadsDirectory, `.${signatureFilename}.${suffix}.tmp`);
102
+ fs.writeFileSync(signatureTemporary, `${detached}\n`, { flag: 'wx', mode: 0o644 });
103
+ staged.push([signatureTemporary, path.join(downloadsDirectory, signatureFilename)]);
104
+ for (const [, destination] of staged) if (fs.existsSync(destination)) stop(`Refusing to overwrite published release component: ${destination}`);
105
+ for (const [temporary, destination] of staged) { fs.renameSync(temporary, destination); published.push(destination); }
106
+ const manifestTemporary = `${manifestFile}.${suffix}.tmp`;
107
+ fs.writeFileSync(manifestTemporary, `${JSON.stringify(manifest, null, 2)}\n`, { flag: 'wx', mode: 0o644 });
108
+ fs.renameSync(manifestTemporary, manifestFile);
109
+ console.log(JSON.stringify({ status: 'published', channel, version, sha256: entry.sha256, size: entry.size, manifestFile }, null, 2));
110
+ } catch (error) {
111
+ for (const file of published.reverse()) { try { fs.unlinkSync(file); } catch {} }
112
+ throw error;
113
+ } finally {
114
+ if (lockHandle !== undefined) fs.closeSync(lockHandle);
115
+ try { fs.unlinkSync(lockPath); } catch {}
116
+ }