gipity 1.1.3 → 1.1.5

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 (47) hide show
  1. package/dist/adopt-cwd.js +1 -1
  2. package/dist/banner.js +3 -5
  3. package/dist/catalog.js +1 -3
  4. package/dist/commands/add.js +1 -1
  5. package/dist/commands/build.js +111 -40
  6. package/dist/commands/chat.js +1 -1
  7. package/dist/commands/deploy.js +7 -3
  8. package/dist/commands/file.js +18 -0
  9. package/dist/commands/fn.js +6 -6
  10. package/dist/commands/generate.js +80 -16
  11. package/dist/commands/gmail.js +1 -1
  12. package/dist/commands/job.js +132 -10
  13. package/dist/commands/load.js +2 -2
  14. package/dist/commands/login.js +7 -2
  15. package/dist/commands/page-eval.js +82 -13
  16. package/dist/commands/page-fetch.js +14 -10
  17. package/dist/commands/page-inspect.js +28 -3
  18. package/dist/commands/page-screenshot.js +36 -7
  19. package/dist/commands/page-test.js +1 -1
  20. package/dist/commands/records.js +14 -1
  21. package/dist/commands/remove.js +1 -1
  22. package/dist/commands/sandbox.js +182 -10
  23. package/dist/commands/save.js +1 -1
  24. package/dist/commands/secrets.js +1 -1
  25. package/dist/commands/service.js +7 -2
  26. package/dist/commands/setup.js +4 -6
  27. package/dist/commands/status.js +41 -12
  28. package/dist/commands/storage.js +2 -2
  29. package/dist/commands/sync.js +15 -0
  30. package/dist/commands/test.js +33 -1
  31. package/dist/commands/update.js +4 -0
  32. package/dist/commands/upload.js +69 -121
  33. package/dist/commands/workflow.js +1 -1
  34. package/dist/helpers/body.js +117 -0
  35. package/dist/helpers/duration.js +34 -0
  36. package/dist/helpers/index.js +2 -0
  37. package/dist/index.js +1173 -620
  38. package/dist/knowledge.js +7 -7
  39. package/dist/login-flow.js +44 -2
  40. package/dist/relay/onboarding.js +26 -44
  41. package/dist/sync.js +6 -6
  42. package/dist/updater/bootstrap.js +27 -16
  43. package/dist/updater/check.js +86 -10
  44. package/dist/updater/install.js +82 -0
  45. package/dist/updater/shim.js +90 -27
  46. package/dist/utils.js +60 -3
  47. package/package.json +2 -2
@@ -38,9 +38,9 @@ function spawnSyncCommand(cmd, args = [], options = {}) {
38
38
  }
39
39
 
40
40
  // src/updater/shim.ts
41
- import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
41
+ import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
42
42
  import { fileURLToPath, pathToFileURL } from "url";
43
- import { dirname, resolve, join as join4 } from "path";
43
+ import { dirname as dirname2, resolve, join as join5 } from "path";
44
44
 
45
45
  // src/updater/state.ts
46
46
  import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
@@ -76,33 +76,96 @@ function writeState(state) {
76
76
  }
77
77
 
78
78
  // src/updater/bootstrap.ts
79
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
80
- import { join as join2 } from "path";
79
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
80
+ import { join as join3 } from "path";
81
+
82
+ // src/updater/install.ts
83
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, rmSync, statSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
84
+ import { dirname, join as join2 } from "path";
85
+ var UPDATE_LOCK = join2(GIPITY_DIR, "update.lock");
86
+ var LOCK_STALE_MS = 10 * 60 * 1e3;
87
+ function npmInstallGipity(version) {
88
+ const res = spawnSyncCommand(resolveCommand("npm"), ["install", "--no-audit", "--no-fund", "--ignore-scripts", `gipity@${version}`], {
89
+ cwd: LOCAL_DIR,
90
+ stdio: ["ignore", "ignore", "pipe"],
91
+ encoding: "utf-8"
92
+ });
93
+ return {
94
+ ok: res.status === 0 && existsSync2(LOCAL_ENTRY),
95
+ status: res.status,
96
+ stderr: (res.stderr || "").toString(),
97
+ spawnError: res.error
98
+ };
99
+ }
100
+ var WEDGE_CODES = /\b(ENOTEMPTY|EEXIST|ENOTDIR|EISDIR|EJSONPARSE)\b/;
101
+ function isWedged(stderr) {
102
+ return WEDGE_CODES.test(stderr);
103
+ }
104
+ function resetLocalTree(dir = LOCAL_DIR) {
105
+ mkdirSync2(dir, { recursive: true });
106
+ rmSync(join2(dir, "node_modules"), { recursive: true, force: true });
107
+ rmSync(join2(dir, "package-lock.json"), { force: true });
108
+ writeFileSync2(join2(dir, "package.json"), JSON.stringify({ name: "gipity-local", private: true, version: "0.0.0" }, null, 2));
109
+ }
110
+ function acquireUpdateLock(lockPath = UPDATE_LOCK) {
111
+ mkdirSync2(dirname(lockPath), { recursive: true });
112
+ try {
113
+ writeFileSync2(lockPath, String(process.pid), { flag: "wx" });
114
+ return true;
115
+ } catch {
116
+ try {
117
+ if (Date.now() - statSync(lockPath).mtimeMs > LOCK_STALE_MS) {
118
+ unlinkSync(lockPath);
119
+ writeFileSync2(lockPath, String(process.pid), { flag: "wx" });
120
+ return true;
121
+ }
122
+ } catch {
123
+ }
124
+ return false;
125
+ }
126
+ }
127
+ function releaseUpdateLock(lockPath = UPDATE_LOCK) {
128
+ try {
129
+ unlinkSync(lockPath);
130
+ } catch {
131
+ }
132
+ }
133
+
134
+ // src/updater/bootstrap.ts
81
135
  function isBootstrapped() {
82
- return existsSync2(LOCAL_ENTRY);
136
+ return existsSync3(LOCAL_ENTRY);
83
137
  }
84
138
  function bootstrap(version, quiet = false) {
85
- mkdirSync2(LOCAL_DIR, { recursive: true });
86
- const pkgJsonPath = join2(LOCAL_DIR, "package.json");
87
- if (!existsSync2(pkgJsonPath)) {
88
- writeFileSync2(pkgJsonPath, JSON.stringify({ name: "gipity-local", private: true, version: "0.0.0" }, null, 2));
139
+ mkdirSync3(LOCAL_DIR, { recursive: true });
140
+ const pkgJsonPath = join3(LOCAL_DIR, "package.json");
141
+ if (!existsSync3(pkgJsonPath)) {
142
+ writeFileSync3(pkgJsonPath, JSON.stringify({ name: "gipity-local", private: true, version: "0.0.0" }, null, 2));
143
+ }
144
+ if (!acquireUpdateLock()) {
145
+ if (!quiet) process.stderr.write(`gipity: another update is in progress - using the currently installed build.
146
+ `);
147
+ return false;
89
148
  }
90
149
  if (!quiet) process.stderr.write(`Setting up gipity local install at ~/.gipity/local (one-time)...
91
150
  `);
92
- const res = spawnSyncCommand(resolveCommand("npm"), ["install", "--no-audit", "--no-fund", "--ignore-scripts", `gipity@${version}`], {
93
- cwd: LOCAL_DIR,
94
- stdio: ["ignore", "pipe", "pipe"],
95
- encoding: "utf-8"
96
- });
97
- if (res.status !== 0 || !existsSync2(LOCAL_ENTRY)) {
151
+ let res;
152
+ try {
153
+ res = npmInstallGipity(version);
154
+ if (!res.ok && !res.spawnError && isWedged(res.stderr)) {
155
+ resetLocalTree();
156
+ res = npmInstallGipity(version);
157
+ }
158
+ } finally {
159
+ releaseUpdateLock();
160
+ }
161
+ if (!res.ok) {
98
162
  if (!quiet) {
99
- const stderr = (res.stderr || "").toString();
100
- const notPublished = /E404|No matching version|notarget/i.test(stderr);
163
+ const notPublished = /E404|No matching version|notarget/i.test(res.stderr);
101
164
  if (notPublished) {
102
165
  process.stderr.write(`gipity v${version} is not yet published to npm - using the currently installed build.
103
166
  `);
104
167
  } else {
105
- const firstLine = stderr.split("\n").map((l) => l.trim()).find((l) => l.length > 0) || (res.error ? res.error.message : `npm exit ${res.status}`);
168
+ const firstLine = res.stderr.split("\n").map((l) => l.trim()).find((l) => l.length > 0) || (res.spawnError ? res.spawnError.message : `npm exit ${res.status}`);
106
169
  const reason = firstLine.length > 160 ? firstLine.slice(0, 157) + "..." : firstLine;
107
170
  process.stderr.write(`gipity: could not set up local install (${reason}). Using the currently installed build.
108
171
  `);
@@ -119,8 +182,8 @@ function bootstrap(version, quiet = false) {
119
182
  }
120
183
 
121
184
  // src/trace.ts
122
- import { openSync, writeSync, mkdirSync as mkdirSync3 } from "fs";
123
- import { join as join3 } from "path";
185
+ import { openSync, writeSync, mkdirSync as mkdirSync4 } from "fs";
186
+ import { join as join4 } from "path";
124
187
  import { homedir as homedir2 } from "os";
125
188
  var TRACE_KEY = /* @__PURE__ */ Symbol.for("gipity.traceOutput");
126
189
  function installOutputTrace(label) {
@@ -132,10 +195,10 @@ function installOutputTrace(label) {
132
195
  existing.emit({ event: "reenter", label });
133
196
  return;
134
197
  }
135
- const dir = join3(process.env.GIPITY_DIR || join3(homedir2(), ".gipity"), "trace");
136
- mkdirSync3(dir, { recursive: true });
198
+ const dir = join4(process.env.GIPITY_DIR || join4(homedir2(), ".gipity"), "trace");
199
+ mkdirSync4(dir, { recursive: true });
137
200
  const stamp = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", "_").replace(/:/g, "-");
138
- const fd = openSync(join3(dir, `${stamp}-pid${process.pid}.jsonl`), "a");
201
+ const fd = openSync(join4(dir, `${stamp}-pid${process.pid}.jsonl`), "a");
139
202
  const emit = (rec) => {
140
203
  try {
141
204
  writeSync(fd, JSON.stringify({ t: (/* @__PURE__ */ new Date()).toISOString(), ...rec }) + "\n");
@@ -170,12 +233,12 @@ function installOutputTrace(label) {
170
233
 
171
234
  // src/updater/shim.ts
172
235
  installOutputTrace("shim");
173
- var __dirname = dirname(fileURLToPath(import.meta.url));
236
+ var __dirname = dirname2(fileURLToPath(import.meta.url));
174
237
  var pkgRoot = resolve(__dirname, "..", "..");
175
- var shimPkg = JSON.parse(readFileSync2(join4(pkgRoot, "package.json"), "utf-8"));
176
- var isDevLink = existsSync3(join4(pkgRoot, "src"));
238
+ var shimPkg = JSON.parse(readFileSync2(join5(pkgRoot, "package.json"), "utf-8"));
239
+ var isDevLink = existsSync4(join5(pkgRoot, "src"));
177
240
  function startBackgroundUpdater() {
178
- const checkScript = join4(__dirname, "check.js");
241
+ const checkScript = join5(__dirname, "check.js");
179
242
  try {
180
243
  const child = spawnCommand(process.execPath, [checkScript], {
181
244
  detached: true,
package/dist/utils.js CHANGED
@@ -1,5 +1,62 @@
1
1
  import { createInterface } from 'readline';
2
+ import { readFileSync, readdirSync, realpathSync, statSync } from 'node:fs';
3
+ import { basename, join } from 'node:path';
2
4
  import { bold, dim } from './colors.js';
5
+ /** True inside Windows Subsystem for Linux (either env marker or kernel
6
+ * string). WSL ships without a systemd user session unless the user opts in
7
+ * via /etc/wsl.conf, and Windows-side paths live under /mnt/c. */
8
+ export function isWsl() {
9
+ if (process.platform !== 'linux')
10
+ return false;
11
+ if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP)
12
+ return true;
13
+ try {
14
+ return /microsoft/i.test(readFileSync('/proc/version', 'utf-8'));
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ const WINDOWS_PSEUDO_USERS = new Set(['All Users', 'Default', 'Default User', 'Public', 'desktop.ini']);
21
+ /** Under WSL, find a same-named project folder on the Windows side
22
+ * (C:\Users\<name>\GipityProjects\<dir>) that is NOT the linked project.
23
+ * From Windows Explorer that folder looks like "the project", so users drop
24
+ * new files there - but nothing syncs from it. Returns the twin's WSL path,
25
+ * or null when there is no twin (or no Windows mount at all). */
26
+ export function findWindowsTwinProject(projectRoot, usersBase = '/mnt/c/Users') {
27
+ try {
28
+ const name = basename(projectRoot);
29
+ if (!name)
30
+ return null;
31
+ const realRoot = realpathSync(projectRoot);
32
+ for (const user of readdirSync(usersBase)) {
33
+ if (WINDOWS_PSEUDO_USERS.has(user))
34
+ continue;
35
+ const candidate = join(usersBase, user, 'GipityProjects', name);
36
+ try {
37
+ if (!statSync(candidate).isDirectory())
38
+ continue;
39
+ if (realpathSync(candidate) === realRoot)
40
+ continue; // the linked project itself lives on /mnt/c
41
+ return candidate;
42
+ }
43
+ catch {
44
+ // this user has no such folder - keep scanning
45
+ }
46
+ }
47
+ }
48
+ catch {
49
+ // usersBase unreadable: not WSL, or no C: mount
50
+ }
51
+ return null;
52
+ }
53
+ /** /mnt/c/Users/steve/... -> C:\Users\steve\... for display to a Windows user. */
54
+ export function wslPathToWindows(p) {
55
+ const m = p.match(/^\/mnt\/([a-z])\/(.*)$/);
56
+ if (!m)
57
+ return p;
58
+ return `${m[1].toUpperCase()}:\\${m[2].replace(/\//g, '\\')}`;
59
+ }
3
60
  /** Safely decode a JWT payload without signature validation */
4
61
  export function decodeJwtExp(token) {
5
62
  try {
@@ -60,8 +117,8 @@ function rerunWithYes() {
60
117
  *
61
118
  * - `opts.default` controls which answer Enter / unknown-key selects. Defaults to `'no'`.
62
119
  * - `opts.skip` (or the global `--yes` flag) auto-returns `true`.
63
- * - Renders a `[Y/n]` or `[y/N]` hint automatically - callers should NOT append
64
- * their own y/N suffix to `question`.
120
+ * - Renders a `[Y/n]:` or `[y/N]:` hint automatically - callers should NOT
121
+ * append their own y/N suffix (or a trailing `?`/`:`) to `question`.
65
122
  * - In non-TTY environments without `--yes`, returns `false` and prints a hint. */
66
123
  export async function confirm(question, opts = {}) {
67
124
  const defaultYes = opts.default === 'yes';
@@ -75,7 +132,7 @@ export async function confirm(question, opts = {}) {
75
132
  return false;
76
133
  }
77
134
  const hint = defaultYes ? dim('[Y/n]') : dim('[y/N]');
78
- process.stdout.write(`${question} ${hint} `);
135
+ process.stdout.write(`${question} ${hint}: `);
79
136
  const { stdin } = process;
80
137
  const wasRaw = stdin.isRaw ?? false;
81
138
  stdin.setRawMode(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gipity",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "The full-stack platform tuned for AI agents. Database, storage, auth, functions, deploy, and drop-in kits - all agent-tuned. Pair with Claude Code or use standalone.",
5
5
  "bin": {
6
6
  "gipity": "dist/updater/shim.js",
@@ -14,7 +14,7 @@
14
14
  "prepack": "npm run build",
15
15
  "dev": "tsc --watch",
16
16
  "test": "npm run test:smoke",
17
- "test:smoke": "npm run build && node --test dist/__tests__/utils.test.js dist/__tests__/platform.test.js dist/__tests__/colors.test.js dist/__tests__/config.test.js dist/__tests__/sync.test.js dist/__tests__/sync-apply.test.js dist/__tests__/sync-unretrievable.test.js dist/__tests__/sync-clean-check.test.js dist/__tests__/sync-lock.test.js dist/__tests__/auth-lock.test.js dist/__tests__/api-401-retry.test.js dist/__tests__/push-cas.test.js dist/__tests__/upload.test.js dist/__tests__/progress.test.js dist/__tests__/updater.test.js dist/__tests__/cli-smoke.test.js dist/__tests__/claude-noninteractive.test.js dist/__tests__/claude-trust.test.js dist/__tests__/relay-state.test.js dist/__tests__/relay-daemon.test.js dist/__tests__/session-pool.test.js dist/__tests__/relay-diagnostics.test.js dist/__tests__/relay-installers.test.js dist/__tests__/relay-bridge-abort.test.js dist/__tests__/relay-redact.test.js dist/__tests__/relay-machine-id.test.js dist/__tests__/stream-json.test.js dist/__tests__/ingest-queue.test.js dist/__tests__/media-upload.test.js dist/__tests__/stream-delta.test.js dist/__tests__/phase-tracker.test.js dist/__tests__/relay-ingest-contract.test.js dist/__tests__/prompts.test.js dist/__tests__/capture-transcript.test.js dist/__tests__/capture-parsers.test.js dist/__tests__/agents.test.js dist/__tests__/capture-lock.test.js dist/__tests__/capture-resolve.test.js dist/__tests__/flag-aliases.test.js dist/__tests__/client-context.test.js dist/__tests__/adopt-cwd.test.js dist/__tests__/cli-cmd-agent.test.js dist/__tests__/cli-cmd-approval.test.js dist/__tests__/cli-cmd-audit.test.js dist/__tests__/cli-cmd-bug.test.js dist/__tests__/cli-cmd-bug-queue.test.js dist/__tests__/cli-cmd-chat.test.js dist/__tests__/cli-cmd-credits.test.js dist/__tests__/cli-cmd-db.test.js dist/__tests__/cli-cmd-deploy.test.js dist/__tests__/cli-cmd-domain.test.js dist/__tests__/cli-cmd-email.test.js dist/__tests__/cli-cmd-file.test.js dist/__tests__/cli-cmd-storage.test.js dist/__tests__/cli-cmd-fn.test.js dist/__tests__/cli-cmd-service.test.js dist/__tests__/cli-cmd-job.test.js dist/__tests__/cli-cmd-generate.test.js dist/__tests__/cli-cmd-gmail.test.js dist/__tests__/cli-cmd-info.test.js dist/__tests__/cli-cmd-init.test.js dist/__tests__/cli-cmd-location.test.js dist/__tests__/cli-cmd-text.test.js dist/__tests__/cli-cmd-login.test.js dist/__tests__/cli-cmd-logout.test.js dist/__tests__/cli-cmd-token.test.js dist/__tests__/cli-cmd-logs.test.js dist/__tests__/cli-cmd-memory.test.js dist/__tests__/cli-cmd-page.test.js dist/__tests__/cli-cmd-plan.test.js dist/__tests__/cli-cmd-project.test.js dist/__tests__/cli-cmd-rbac.test.js dist/__tests__/cli-cmd-realtime.test.js dist/__tests__/cli-cmd-records.test.js dist/__tests__/cli-cmd-relay.test.js dist/__tests__/cli-cmd-setup.test.js dist/__tests__/cli-cmd-doctor.test.js dist/__tests__/claude-setup.test.js dist/__tests__/cli-cmd-sandbox.test.js dist/__tests__/cli-cmd-add.test.js dist/__tests__/cli-cmd-remove.test.js dist/__tests__/cli-cmd-skill.test.js dist/__tests__/cli-cmd-test.test.js dist/__tests__/cli-cmd-workflow.test.js dist/__tests__/setup-skills-block.test.js dist/__tests__/setup-hooks.test.js dist/__tests__/setup-codex-hooks.test.js dist/__tests__/trace.test.js",
17
+ "test:smoke": "npm run build && node --test dist/__tests__/utils.test.js dist/__tests__/platform.test.js dist/__tests__/colors.test.js dist/__tests__/config.test.js dist/__tests__/sync.test.js dist/__tests__/sync-apply.test.js dist/__tests__/sync-unretrievable.test.js dist/__tests__/sync-clean-check.test.js dist/__tests__/sync-lock.test.js dist/__tests__/auth-lock.test.js dist/__tests__/api-401-retry.test.js dist/__tests__/push-cas.test.js dist/__tests__/upload.test.js dist/__tests__/progress.test.js dist/__tests__/updater.test.js dist/__tests__/cli-smoke.test.js dist/__tests__/claude-noninteractive.test.js dist/__tests__/claude-trust.test.js dist/__tests__/build-picker.test.js dist/__tests__/relay-state.test.js dist/__tests__/relay-daemon.test.js dist/__tests__/session-pool.test.js dist/__tests__/relay-diagnostics.test.js dist/__tests__/relay-installers.test.js dist/__tests__/relay-bridge-abort.test.js dist/__tests__/relay-redact.test.js dist/__tests__/relay-machine-id.test.js dist/__tests__/stream-json.test.js dist/__tests__/ingest-queue.test.js dist/__tests__/media-upload.test.js dist/__tests__/stream-delta.test.js dist/__tests__/phase-tracker.test.js dist/__tests__/relay-ingest-contract.test.js dist/__tests__/prompts.test.js dist/__tests__/capture-transcript.test.js dist/__tests__/capture-parsers.test.js dist/__tests__/agents.test.js dist/__tests__/capture-lock.test.js dist/__tests__/capture-resolve.test.js dist/__tests__/flag-aliases.test.js dist/__tests__/client-context.test.js dist/__tests__/adopt-cwd.test.js dist/__tests__/cli-cmd-agent.test.js dist/__tests__/cli-cmd-approval.test.js dist/__tests__/cli-cmd-audit.test.js dist/__tests__/cli-cmd-bug.test.js dist/__tests__/cli-cmd-bug-queue.test.js dist/__tests__/cli-cmd-chat.test.js dist/__tests__/cli-cmd-credits.test.js dist/__tests__/cli-cmd-db.test.js dist/__tests__/cli-cmd-deploy.test.js dist/__tests__/cli-cmd-domain.test.js dist/__tests__/cli-cmd-email.test.js dist/__tests__/cli-cmd-file.test.js dist/__tests__/cli-cmd-storage.test.js dist/__tests__/cli-cmd-fn.test.js dist/__tests__/cli-cmd-service.test.js dist/__tests__/cli-cmd-job.test.js dist/__tests__/cli-cmd-generate.test.js dist/__tests__/cli-cmd-gmail.test.js dist/__tests__/cli-cmd-info.test.js dist/__tests__/cli-cmd-init.test.js dist/__tests__/cli-cmd-location.test.js dist/__tests__/cli-cmd-text.test.js dist/__tests__/cli-cmd-login.test.js dist/__tests__/cli-cmd-status.test.js dist/__tests__/cli-cmd-logout.test.js dist/__tests__/cli-cmd-token.test.js dist/__tests__/cli-cmd-logs.test.js dist/__tests__/cli-cmd-memory.test.js dist/__tests__/cli-cmd-page.test.js dist/__tests__/cli-cmd-plan.test.js dist/__tests__/cli-cmd-project.test.js dist/__tests__/cli-cmd-rbac.test.js dist/__tests__/cli-cmd-realtime.test.js dist/__tests__/cli-cmd-records.test.js dist/__tests__/cli-cmd-relay.test.js dist/__tests__/cli-cmd-setup.test.js dist/__tests__/cli-cmd-doctor.test.js dist/__tests__/claude-setup.test.js dist/__tests__/cli-cmd-sandbox.test.js dist/__tests__/cli-cmd-add.test.js dist/__tests__/cli-cmd-remove.test.js dist/__tests__/cli-cmd-skill.test.js dist/__tests__/cli-cmd-test.test.js dist/__tests__/cli-cmd-workflow.test.js dist/__tests__/setup-skills-block.test.js dist/__tests__/setup-hooks.test.js dist/__tests__/setup-codex-hooks.test.js dist/__tests__/trace.test.js",
18
18
  "test:smoke:quick": "node scripts/smoke-quick.mjs",
19
19
  "test:e2e": "tsc && GIPITY_E2E=1 node --test --test-timeout=180000 dist/__tests__/cli-e2e-live.test.js dist/__tests__/cli-e2e-sync-live.test.js dist/__tests__/cli-e2e-sync-stress-live.test.js dist/__tests__/cli-e2e-rollback-live.test.js dist/__tests__/cli-e2e-services-media-live.test.js dist/__tests__/cli-e2e-workflow-live.test.js dist/__tests__/cli-e2e-sandbox-live.test.js dist/__tests__/cli-e2e-page-fetch-live.test.js dist/__tests__/cli-e2e-page-test-live.test.js",
20
20
  "test:e2e:sync": "tsc && GIPITY_E2E=1 node --test --test-timeout=180000 dist/__tests__/cli-e2e-sync-live.test.js",