heyspex 0.2.0 → 0.2.2
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/.claude-plugin/marketplace.json +14 -0
- package/bin/hs.mjs +181 -15
- package/dist/cli/hs-check.mjs +88 -46
- package/dist/cli/hs-claim.mjs +84 -39
- package/dist/cli/hs-connect.mjs +583 -129
- package/dist/cli/hs-defer.mjs +251 -30
- package/dist/cli/hs-dev.mjs +20 -8
- package/dist/cli/hs-env.mjs +62 -34
- package/dist/cli/hs-index-rebuild.mjs +288 -83
- package/dist/cli/hs-index-reconcile.mjs +397 -111
- package/dist/cli/hs-init.mjs +2143 -91
- package/dist/cli/hs-install.mjs +628 -106
- package/dist/cli/hs-join.mjs +686 -236
- package/dist/cli/hs-vault-pull.mjs +3189 -179
- package/dist/cli/hs-vault-push.mjs +6433 -0
- package/dist/cli/hs-vault.mjs +396 -178
- package/dist/cli/hs-workspace.mjs +289 -151
- package/dist/cli-templates/harness-commands/claude/hs-backfill.md +28 -28
- package/dist/cli-templates/harness-commands/claude/hs-capture.md +62 -62
- package/dist/cli-templates/harness-commands/claude/hs-defer.md +29 -29
- package/dist/cli-templates/harness-commands/claude/hs-ground.md +30 -28
- package/dist/cli-templates/harness-commands/claude/hs-next.md +29 -29
- package/dist/cli-templates/harness-commands/claude/hs-promote.md +70 -70
- package/dist/cli-templates/harness-commands/claude/hs-push.md +35 -35
- package/dist/cli-templates/harness-commands/claude/hs-qc.md +27 -27
- package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -23
- package/dist/cli-templates/harness-commands/claude/hs-review.md +23 -23
- package/dist/cli-templates/harness-commands/claude/hs-view.md +28 -26
- package/dist/cli-templates/harness-commands/claude/kill-ports.md +32 -32
- package/dist/cli-templates/harness-commands/claude/prototype.md +91 -91
- package/dist/cli-templates/harness-commands/cursor/hs-backfill.md +22 -22
- package/dist/cli-templates/harness-commands/cursor/hs-capture.md +56 -56
- package/dist/cli-templates/harness-commands/cursor/hs-defer.md +23 -23
- package/dist/cli-templates/harness-commands/cursor/hs-ground.md +24 -22
- package/dist/cli-templates/harness-commands/cursor/hs-next.md +23 -23
- package/dist/cli-templates/harness-commands/cursor/hs-promote.md +64 -64
- package/dist/cli-templates/harness-commands/cursor/hs-push.md +29 -29
- package/dist/cli-templates/harness-commands/cursor/hs-qc.md +21 -21
- package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +17 -17
- package/dist/cli-templates/harness-commands/cursor/hs-review.md +17 -17
- package/dist/cli-templates/harness-commands/cursor/hs-view.md +24 -22
- package/dist/cli-templates/harness-commands/cursor/kill-ports.md +26 -26
- package/dist/cli-templates/harness-commands/cursor/prototype.md +86 -86
- package/docs/copilot-plugin-install.md +177 -0
- package/docs/driving-heyspex-from-copilot.md +165 -0
- package/package.json +21 -2
- package/plugins/heyspex/.claude-plugin/plugin.json +12 -12
- package/plugins/heyspex/.cursor-plugin/plugin.json +15 -15
- package/plugins/heyspex/README.md +312 -0
- package/plugins/heyspex/bin/run-hook.mjs +20 -2
- package/plugins/heyspex/hooks/cursor-hooks.json +81 -0
- package/plugins/heyspex/hooks/hooks.json +94 -37
- package/scripts/claude-hooks/_intent-classifier-router.mjs +456 -410
- package/scripts/claude-hooks/_intent-classifier-semantic.mjs +5 -0
- package/scripts/claude-hooks/_run.mjs +316 -23
- package/scripts/claude-hooks/capture-execution-gate.mjs +51 -0
- package/scripts/claude-hooks/claim-liveness-shared.mjs +2 -0
- package/scripts/claude-hooks/diagnose-capture-reminder.mjs +11 -0
- package/scripts/claude-hooks/directive-obligation-gate.mjs +11 -0
- package/scripts/claude-hooks/inject-communication-style.mjs +20 -0
- package/scripts/claude-hooks/intent-classifier-trigger.mjs +279 -247
- package/scripts/claude-hooks/session-end.mjs +2 -0
- package/scripts/claude-hooks/vault-mirror-catchup.mjs +11 -0
- package/scripts/claude-hooks/vault-write-tier-guard.mjs +11 -0
- package/scripts/claude-hooks/wip-checkpoint.mjs +5 -1
- package/scripts/cursor-hooks/manifest.mjs +46 -0
- package/scripts/heyspex-mode.mjs +20 -0
- package/scripts/hs-mode.mjs +1 -1
- package/scripts/hs-view.mjs +180 -17
- package/scripts/install-claude-code-hooks.mjs +3 -1
- package/scripts/install-copilot-hooks.mjs +288 -0
- package/scripts/lib/console-url-resolver.mjs +3 -2
- package/scripts/lib/customer-kit.mjs +327 -10
- package/scripts/lib/dev-mode.mjs +7 -6
- package/scripts/lib/directive-obligations.mjs +349 -0
- package/scripts/lib/hook-dispositions.mjs +210 -0
- package/scripts/lib/hook-vault-header.mjs +30 -0
- package/scripts/lib/hs-source-branch.mjs +196 -0
- package/scripts/lib/hs-source-log.mjs +2 -1
- package/scripts/lib/hs-source-preflight.mjs +18 -4
- package/scripts/lib/hs-source-push.mjs +386 -356
- package/scripts/lib/window-placement.mjs +109 -0
- package/spexharness/src/adapters/claude-code.mjs +11 -3
- package/spexharness/src/adapters/copilot.mjs +236 -0
- package/spexharness/src/adapters/detect-harness.mjs +34 -0
- package/spexharness/src/gates/_shell-write-targets.mjs +77 -0
- package/spexharness/src/gates/deep-research-cost-gate.mjs +4 -3
- package/spexharness/src/gates/diagnose-capture-reminder.mjs +112 -0
- package/spexharness/src/gates/directive-obligation-gate.decide.mjs +132 -0
- package/spexharness/src/gates/directive-obligation-gate.mjs +183 -0
- package/spexharness/src/gates/vault-mirror-catchup.mjs +124 -0
- package/spexharness/src/gates/vault-write-tier-guard.decide.mjs +125 -0
- package/spexharness/src/gates/vault-write-tier-guard.mjs +42 -0
- package/spexharness/src/intent-classifier.mjs +4 -2
- package/spexharness/src/intent-directive.mjs +626 -541
- package/spexharness/src/rule-table.mjs +31 -1
- package/vendor/heyspex-mcp/account-switch.mjs +6 -5
- package/vendor/heyspex-mcp/capture-buffer-patches.mjs +31 -3
- package/vendor/heyspex-mcp/capture-console-client.mjs +37 -2
- package/vendor/heyspex-mcp/capture-focus.mjs +26 -2
- package/vendor/heyspex-mcp/capture-outbox.mjs +10 -4
- package/vendor/heyspex-mcp/capture-sources.mjs +195 -0
- package/vendor/heyspex-mcp/capture-tools.mjs +56 -11
- package/vendor/heyspex-mcp/claim-tools.mjs +25 -2
- package/vendor/heyspex-mcp/cli-verbs.mjs +19 -21
- package/vendor/heyspex-mcp/cli.mjs +7 -1
- package/vendor/heyspex-mcp/close-branch-report.mjs +102 -0
- package/vendor/heyspex-mcp/cloud-vault-writes.mjs +197 -7
- package/vendor/heyspex-mcp/console-fetch.mjs +192 -28
- package/vendor/heyspex-mcp/console-transport.mjs +7 -1
- package/vendor/heyspex-mcp/credentials.mjs +9 -8
- package/vendor/heyspex-mcp/dev-tools.mjs +7 -0
- package/vendor/heyspex-mcp/filing-tools.mjs +35 -0
- package/vendor/heyspex-mcp/fleet-queue-tools.mjs +2 -1
- package/vendor/heyspex-mcp/folder-trust-store.mjs +2 -1
- package/vendor/heyspex-mcp/http-transport.mjs +2 -0
- package/vendor/heyspex-mcp/list-tools.mjs +1 -1
- package/vendor/heyspex-mcp/mcp-config.mjs +14 -1
- package/vendor/heyspex-mcp/memory-tools.mjs +523 -523
- package/vendor/heyspex-mcp/obligation-backstop.mjs +103 -0
- package/vendor/heyspex-mcp/occupied-keys.mjs +1 -0
- package/vendor/heyspex-mcp/on-deck-brief.mjs +19 -2
- package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -1708
- package/vendor/heyspex-mcp/plan-push.mjs +3 -2
- package/vendor/heyspex-mcp/preflight-gate.mjs +1 -0
- package/vendor/heyspex-mcp/procedure-handlers.mjs +327 -325
- package/vendor/heyspex-mcp/procedure-tools.mjs +1181 -1159
- package/vendor/heyspex-mcp/promote-capture.mjs +2 -0
- package/vendor/heyspex-mcp/promote-research.mjs +6 -0
- package/vendor/heyspex-mcp/read-path.mjs +162 -6
- package/vendor/heyspex-mcp/request-context.mjs +25 -1
- package/vendor/heyspex-mcp/research-handlers.mjs +6 -4
- package/vendor/heyspex-mcp/roadmap-default.mjs +70 -0
- package/vendor/heyspex-mcp/session-owner.mjs +3 -2
- package/vendor/heyspex-mcp/session-tools.mjs +10 -0
- package/vendor/heyspex-mcp/spec-edit-tools.mjs +8 -1
- package/vendor/heyspex-mcp/split-research.mjs +3 -0
- package/vendor/heyspex-mcp/submit-for-review.mjs +18 -1
- package/vendor/heyspex-mcp/summary-write-tools.mjs +5 -1
- package/vendor/heyspex-mcp/test-helpers.mjs +18 -3
- package/vendor/heyspex-mcp/tool-catalog.mjs +7 -1
- package/vendor/heyspex-mcp/tool-dispatch.mjs +18 -0
- package/vendor/heyspex-mcp/vault-io.mjs +720 -724
- package/vendor/heyspex-mcp/vault-resolve.mjs +197 -9
- package/vendor/heyspex-mcp/whoami.mjs +2 -1
- package/vendor/heyspex-mcp/write-outbox.mjs +512 -0
package/dist/cli/hs-defer.mjs
CHANGED
|
@@ -39,11 +39,26 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
mod
|
|
40
40
|
));
|
|
41
41
|
|
|
42
|
+
// scripts/lib/heyspex-home.mjs
|
|
43
|
+
import { homedir } from "node:os";
|
|
44
|
+
function heyspexHome(env = process.env) {
|
|
45
|
+
const override = env?.HEYSPEX_HOME;
|
|
46
|
+
if (typeof override === "string" && override.trim().length > 0) {
|
|
47
|
+
return override.trim();
|
|
48
|
+
}
|
|
49
|
+
return homedir();
|
|
50
|
+
}
|
|
51
|
+
var init_heyspex_home = __esm({
|
|
52
|
+
"scripts/lib/heyspex-home.mjs"() {
|
|
53
|
+
"use strict";
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
42
57
|
// vendor/heyspex-mcp/credentials.mjs
|
|
43
58
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
44
|
-
import os, { homedir } from "node:os";
|
|
59
|
+
import os, { homedir as homedir2 } from "node:os";
|
|
45
60
|
import { dirname, join, resolve } from "node:path";
|
|
46
|
-
function credentialsFilePath(homeDir =
|
|
61
|
+
function credentialsFilePath(homeDir = heyspexHome()) {
|
|
47
62
|
return join(homeDir, ".heyspex", "credentials.yaml");
|
|
48
63
|
}
|
|
49
64
|
function parseMcpToken(raw) {
|
|
@@ -139,7 +154,7 @@ function readLegacyConfigAccountId(read, homeDir) {
|
|
|
139
154
|
const value = raw?.match(CONFIG_ACCOUNT_ID_RE)?.[1]?.trim() ?? "";
|
|
140
155
|
return value || null;
|
|
141
156
|
}
|
|
142
|
-
function readCurrentAccountId({ homeDir =
|
|
157
|
+
function readCurrentAccountId({ homeDir = heyspexHome(), readFile } = {}) {
|
|
143
158
|
const read = readFile ?? ((p) => readFileSync(p, "utf8"));
|
|
144
159
|
const store = parseCredentialsStore(readTextOrNull(read, credentialsFilePath(homeDir)));
|
|
145
160
|
if (store.schemaVersion === 2 && store.currentAccountId && store.currentAccountId !== LEGACY_ACCOUNT_ID) {
|
|
@@ -152,6 +167,7 @@ var MCP_TOKEN_LINE_RE, CREDENTIALS_SCHEMA_VERSION, LEGACY_ACCOUNT_ID, ACCOUNT_FI
|
|
|
152
167
|
var init_credentials = __esm({
|
|
153
168
|
"vendor/heyspex-mcp/credentials.mjs"() {
|
|
154
169
|
"use strict";
|
|
170
|
+
init_heyspex_home();
|
|
155
171
|
MCP_TOKEN_LINE_RE = /^mcp_token:[ \t]*["']?([^"'\r\n#]+)/m;
|
|
156
172
|
CREDENTIALS_SCHEMA_VERSION = 2;
|
|
157
173
|
LEGACY_ACCOUNT_ID = "legacy";
|
|
@@ -163,9 +179,9 @@ var init_credentials = __esm({
|
|
|
163
179
|
|
|
164
180
|
// scripts/lib/dev-mode.mjs
|
|
165
181
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
166
|
-
import { homedir as
|
|
182
|
+
import { homedir as homedir3 } from "node:os";
|
|
167
183
|
import { join as join2 } from "node:path";
|
|
168
|
-
function devModeFilePath(homeDir =
|
|
184
|
+
function devModeFilePath(homeDir = heyspexHome()) {
|
|
169
185
|
return join2(homeDir, ".heyspex", DEV_MODE_FILENAME);
|
|
170
186
|
}
|
|
171
187
|
function normalizeMode(raw) {
|
|
@@ -190,7 +206,7 @@ function deriveSemantics(mode, reliance) {
|
|
|
190
206
|
vaultWriteMode: local ? "local" : "cloud"
|
|
191
207
|
};
|
|
192
208
|
}
|
|
193
|
-
function readLocalDevModeRecord({ homeDir =
|
|
209
|
+
function readLocalDevModeRecord({ homeDir = heyspexHome(), readFile = defaultReadFile } = {}) {
|
|
194
210
|
let raw;
|
|
195
211
|
try {
|
|
196
212
|
raw = readFile(devModeFilePath(homeDir));
|
|
@@ -220,7 +236,7 @@ function readLocalDevModeRecord({ homeDir = homedir2(), readFile = defaultReadFi
|
|
|
220
236
|
}
|
|
221
237
|
function resolveDevMode({
|
|
222
238
|
env = process.env,
|
|
223
|
-
homeDir =
|
|
239
|
+
homeDir = heyspexHome(),
|
|
224
240
|
readFile = defaultReadFile,
|
|
225
241
|
cloudSetting = void 0
|
|
226
242
|
} = {}) {
|
|
@@ -283,6 +299,7 @@ var CLOUD_CONSOLE_URL, LOCAL_CONSOLE_URL, DEV_MODE_FILENAME, defaultReadFile;
|
|
|
283
299
|
var init_dev_mode = __esm({
|
|
284
300
|
"scripts/lib/dev-mode.mjs"() {
|
|
285
301
|
"use strict";
|
|
302
|
+
init_heyspex_home();
|
|
286
303
|
init_credentials();
|
|
287
304
|
CLOUD_CONSOLE_URL = "https://app.heyspex.com";
|
|
288
305
|
LOCAL_CONSOLE_URL = "http://localhost:3000";
|
|
@@ -293,7 +310,7 @@ var init_dev_mode = __esm({
|
|
|
293
310
|
|
|
294
311
|
// scripts/lib/console-url-resolver.mjs
|
|
295
312
|
import { readFileSync as readFileSync3 } from "node:fs";
|
|
296
|
-
import { homedir as
|
|
313
|
+
import { homedir as homedir4 } from "node:os";
|
|
297
314
|
import { join as join3 } from "node:path";
|
|
298
315
|
function trimTrailingSlash(url) {
|
|
299
316
|
return url.replace(/\/+$/, "");
|
|
@@ -317,7 +334,7 @@ function warnStaleLoopbackCredentialsOnce(credentialsUrl, derivedUrl, { log }) {
|
|
|
317
334
|
} catch {
|
|
318
335
|
}
|
|
319
336
|
}
|
|
320
|
-
function readCredentialsConsoleUrl({ homeDir =
|
|
337
|
+
function readCredentialsConsoleUrl({ homeDir = heyspexHome(), readFile = defaultReadFile2 } = {}) {
|
|
321
338
|
try {
|
|
322
339
|
const raw = readFile(join3(homeDir, ".heyspex", "credentials.yaml"));
|
|
323
340
|
const match = String(raw ?? "").match(/^console_url:\s*["']?([^"'\r\n#]+)/m);
|
|
@@ -353,7 +370,7 @@ function resolveModeEnvelope({ env, homeDir }) {
|
|
|
353
370
|
function resolveConsoleUrl({
|
|
354
371
|
repoRoot: repoRoot2,
|
|
355
372
|
env = process.env,
|
|
356
|
-
homeDir =
|
|
373
|
+
homeDir = heyspexHome(),
|
|
357
374
|
strict = false,
|
|
358
375
|
devMode,
|
|
359
376
|
log = (line) => process.stderr.write(line),
|
|
@@ -386,6 +403,7 @@ var DEFAULT_CONSOLE_URL, LOOPBACK_HOSTS, staleLoopbackCredentialsWarned, Console
|
|
|
386
403
|
var init_console_url_resolver = __esm({
|
|
387
404
|
"scripts/lib/console-url-resolver.mjs"() {
|
|
388
405
|
"use strict";
|
|
406
|
+
init_heyspex_home();
|
|
389
407
|
init_dev_mode();
|
|
390
408
|
DEFAULT_CONSOLE_URL = LOCAL_CONSOLE_URL;
|
|
391
409
|
LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]", "0.0.0.0"]);
|
|
@@ -401,11 +419,26 @@ var init_console_url_resolver = __esm({
|
|
|
401
419
|
}
|
|
402
420
|
});
|
|
403
421
|
|
|
422
|
+
// spex-console/src/lib/heyspex-home.ts
|
|
423
|
+
import { homedir as homedir5 } from "node:os";
|
|
424
|
+
function heyspexHome2(env = process.env) {
|
|
425
|
+
const override = env?.HEYSPEX_HOME;
|
|
426
|
+
if (typeof override === "string" && override.trim().length > 0) {
|
|
427
|
+
return override.trim();
|
|
428
|
+
}
|
|
429
|
+
return homedir5();
|
|
430
|
+
}
|
|
431
|
+
var init_heyspex_home2 = __esm({
|
|
432
|
+
"spex-console/src/lib/heyspex-home.ts"() {
|
|
433
|
+
"use strict";
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
404
437
|
// vendor/heyspex-mcp/session-owner.mjs
|
|
405
438
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
406
|
-
import { homedir as
|
|
439
|
+
import { homedir as homedir6 } from "node:os";
|
|
407
440
|
import { join as join4 } from "node:path";
|
|
408
|
-
function resolveSessionOwnerUncached({ env = process.env, homeDir =
|
|
441
|
+
function resolveSessionOwnerUncached({ env = process.env, homeDir = heyspexHome(), readFile } = {}) {
|
|
409
442
|
const fromEnv = typeof env?.HS_ACCOUNT_ID === "string" ? env.HS_ACCOUNT_ID.trim() : "";
|
|
410
443
|
if (fromEnv) return fromEnv;
|
|
411
444
|
return readCurrentAccountId({ homeDir, readFile });
|
|
@@ -413,6 +446,7 @@ function resolveSessionOwnerUncached({ env = process.env, homeDir = homedir4(),
|
|
|
413
446
|
var init_session_owner = __esm({
|
|
414
447
|
"vendor/heyspex-mcp/session-owner.mjs"() {
|
|
415
448
|
"use strict";
|
|
449
|
+
init_heyspex_home();
|
|
416
450
|
init_credentials();
|
|
417
451
|
}
|
|
418
452
|
});
|
|
@@ -426,11 +460,10 @@ var init_default_workspace = __esm({
|
|
|
426
460
|
|
|
427
461
|
// spex-console/src/lib/cli/vault-workspace-shared.ts
|
|
428
462
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
429
|
-
import os2 from "node:os";
|
|
430
463
|
function resolveConfiguredAccountId(opts = {}) {
|
|
431
464
|
return resolveSessionOwnerUncached({
|
|
432
465
|
env: opts.env ?? process.env,
|
|
433
|
-
homeDir: opts.homeDir ??
|
|
466
|
+
homeDir: opts.homeDir ?? heyspexHome2(),
|
|
434
467
|
readFile: opts.readFile ?? ((p) => readFileSync5(p, "utf-8"))
|
|
435
468
|
});
|
|
436
469
|
}
|
|
@@ -464,6 +497,7 @@ var CLOUD_ACCOUNT_ID_REQUIRED_MESSAGE;
|
|
|
464
497
|
var init_vault_workspace_shared = __esm({
|
|
465
498
|
"spex-console/src/lib/cli/vault-workspace-shared.ts"() {
|
|
466
499
|
"use strict";
|
|
500
|
+
init_heyspex_home2();
|
|
467
501
|
init_session_owner();
|
|
468
502
|
init_default_workspace();
|
|
469
503
|
CLOUD_ACCOUNT_ID_REQUIRED_MESSAGE = "refusing -- no signed-in account (no HS_ACCOUNT_ID env var, and no account_id: in ~/.heyspex/config.yaml). Run `hs login` first; nothing was written.";
|
|
@@ -1157,7 +1191,7 @@ var init_diagnose_skeleton = __esm({
|
|
|
1157
1191
|
});
|
|
1158
1192
|
|
|
1159
1193
|
// dist/cli/._sql-orm-inert.cli-shim.mjs
|
|
1160
|
-
var inert, customType, drizzle, sql, and, or, eq, ne, isNull, asc, gt, count, inArray, bigint, bigserial, boolean, foreignKey, index, integer, jsonb, pgEnum, pgTable, primaryKey, text, timestamp, uniqueIndex;
|
|
1194
|
+
var inert, customType, drizzle, sql, and, or, eq, ne, isNull, desc, asc, gt, count, inArray, bigint, bigserial, boolean, foreignKey, index, integer, jsonb, pgEnum, pgTable, primaryKey, text, timestamp, uniqueIndex;
|
|
1161
1195
|
var init_sql_orm_inert_cli_shim = __esm({
|
|
1162
1196
|
"dist/cli/._sql-orm-inert.cli-shim.mjs"() {
|
|
1163
1197
|
"use strict";
|
|
@@ -1183,6 +1217,7 @@ var init_sql_orm_inert_cli_shim = __esm({
|
|
|
1183
1217
|
eq = inert;
|
|
1184
1218
|
ne = inert;
|
|
1185
1219
|
isNull = inert;
|
|
1220
|
+
desc = inert;
|
|
1186
1221
|
asc = inert;
|
|
1187
1222
|
gt = inert;
|
|
1188
1223
|
count = inert;
|
|
@@ -1214,7 +1249,7 @@ var init_interfaces = __esm({
|
|
|
1214
1249
|
});
|
|
1215
1250
|
|
|
1216
1251
|
// spex-console/src/lib/db/schema/postgres.ts
|
|
1217
|
-
var edgeTypeEnum, validationSeverityEnum, outboxOpEnum, tsvector, specs, tags, edges, wikilinks, specLinks, aliases, validationIssues, indexMeta, frontmatterFields, eventOutbox, captureSessions, handoffContext, claimEventKindEnum, activeClaimStatusEnum, pendingReasonEnum, focusEventKindEnum, specEventKindEnum, focusPin, captureFocusPin, captureFocusSelection, focusSelection, focusSkips, activeClaims, claimWaiters, fileClaims, claimEvents, focusEvents, focusAreas, focusAreasEvents, specEvents, rateLimitBuckets, userVaults, milestoneSnapshots, modelRegistryEntries, launchIntentStatusEnum, launchIntents, companionRelayPresence, companionSettingsStore, consoleSettingsStore, wipLedger, wipLedgerArchive, gatherResults, agentSessions, usageEvents, streamEvents, jobStreams, resolutionStatusEnum, resolutionFocusPin, resolutionLedger, workspaces, vaults, accountSettings, vaultGrants, pendingVaultGrants, githubInstallations, fleetMachines, fleetTasks, fleetResults, userApiKeys, apiKeys, mcpSessions, pairingCodes, companionSessions, inviteRequests, notifications, webhookIngestions, specSettlements;
|
|
1252
|
+
var edgeTypeEnum, validationSeverityEnum, outboxOpEnum, tsvector, specs, tags, edges, wikilinks, specLinks, aliases, validationIssues, indexMeta, frontmatterFields, eventOutbox, captureSessions, handoffContext, claimEventKindEnum, activeClaimStatusEnum, pendingReasonEnum, focusEventKindEnum, specEventKindEnum, focusPin, captureFocusPin, captureFocusSelection, focusSelection, focusSkips, activeClaims, claimWaiters, fileClaims, claimEvents, focusEvents, focusAreas, focusAreasEvents, specEvents, rateLimitBuckets, userVaults, milestoneSnapshots, modelRegistryEntries, launchIntentStatusEnum, launchIntents, companionRelayPresence, companionSettingsStore, consoleSettingsStore, wipLedger, wipLedgerArchive, gatherResults, agentSessions, usageEvents, streamEvents, jobStreams, resolutionStatusEnum, resolutionFocusPin, resolutionLedger, workspaces, vaults, accountSettings, vaultGrants, pendingVaultGrants, githubInstallations, fleetMachines, fleetTasks, fleetResults, userApiKeys, apiKeys, mcpSessions, pairingCodes, companionSessions, inviteRequests, notifications, webhookIngestions, specSettlements, sessionBranchDeclarations;
|
|
1218
1253
|
var init_postgres = __esm({
|
|
1219
1254
|
"spex-console/src/lib/db/schema/postgres.ts"() {
|
|
1220
1255
|
"use strict";
|
|
@@ -1656,7 +1691,13 @@ var init_postgres = __esm({
|
|
|
1656
1691
|
"priority_change",
|
|
1657
1692
|
"parent_change",
|
|
1658
1693
|
"claim_acquired",
|
|
1659
|
-
"claim_released"
|
|
1694
|
+
"claim_released",
|
|
1695
|
+
// Collaborator write audit (HS-FWB6, migration 0077).
|
|
1696
|
+
"spec_created",
|
|
1697
|
+
"spec_edited",
|
|
1698
|
+
"spec_deleted",
|
|
1699
|
+
"capture_written",
|
|
1700
|
+
"wip_recorded"
|
|
1660
1701
|
]);
|
|
1661
1702
|
focusPin = pgTable(
|
|
1662
1703
|
"focus_pin",
|
|
@@ -2849,11 +2890,43 @@ var init_postgres = __esm({
|
|
|
2849
2890
|
// `owner/name`
|
|
2850
2891
|
branch: text("branch").notNull(),
|
|
2851
2892
|
commitSha: text("commit_sha").notNull(),
|
|
2852
|
-
settledAt: timestamp("settled_at", { withTimezone: true }).notNull().default(sql`now()`)
|
|
2893
|
+
settledAt: timestamp("settled_at", { withTimezone: true }).notNull().default(sql`now()`),
|
|
2894
|
+
// The pull request that carries this settlement
|
|
2895
|
+
// ([[HS-9D25-CWPX-EPIC-branch-lifecycle-open-a-pull-request]]). NULL until
|
|
2896
|
+
// the branch has gone quiet and a PR was opened or found; a write made
|
|
2897
|
+
// after its PR merged stays NULL, which is what triggers the next PR.
|
|
2898
|
+
pullRequestNumber: integer("pull_request_number"),
|
|
2899
|
+
pullRequestUrl: text("pull_request_url")
|
|
2853
2900
|
},
|
|
2854
2901
|
(table) => [
|
|
2855
2902
|
// "latest settlement for this spec" — the read path's only query.
|
|
2856
|
-
index("spec_settlements_spec_settled_idx").on(table.specId, table.settledAt.desc())
|
|
2903
|
+
index("spec_settlements_spec_settled_idx").on(table.specId, table.settledAt.desc()),
|
|
2904
|
+
// The PR sweep's only query: branches with settlements not yet in a PR.
|
|
2905
|
+
index("spec_settlements_unproposed_idx").on(table.vaultId, table.repo, table.branch).where(sql`${table.pullRequestNumber} IS NULL`)
|
|
2906
|
+
]
|
|
2907
|
+
);
|
|
2908
|
+
sessionBranchDeclarations = pgTable(
|
|
2909
|
+
"session_branch_declarations",
|
|
2910
|
+
{
|
|
2911
|
+
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
|
|
2912
|
+
vaultId: text("vault_id").notNull().default(DEFAULT_VAULT_ID),
|
|
2913
|
+
actorKey: text("actor_key").notNull(),
|
|
2914
|
+
sessionId: text("session_id").notNull(),
|
|
2915
|
+
branch: text("branch").notNull(),
|
|
2916
|
+
declaredAt: timestamp("declared_at", { withTimezone: true }).notNull().default(sql`now()`),
|
|
2917
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull()
|
|
2918
|
+
},
|
|
2919
|
+
(table) => [
|
|
2920
|
+
uniqueIndex("session_branch_declarations_uq").on(
|
|
2921
|
+
table.vaultId,
|
|
2922
|
+
table.actorKey,
|
|
2923
|
+
table.sessionId
|
|
2924
|
+
),
|
|
2925
|
+
index("session_branch_declarations_lookup_idx").on(
|
|
2926
|
+
table.vaultId,
|
|
2927
|
+
table.actorKey,
|
|
2928
|
+
table.declaredAt.desc()
|
|
2929
|
+
)
|
|
2857
2930
|
]
|
|
2858
2931
|
);
|
|
2859
2932
|
}
|
|
@@ -3143,10 +3216,9 @@ var init_types = __esm({
|
|
|
3143
3216
|
|
|
3144
3217
|
// spex-console/src/lib/vault-registry/registry-file.ts
|
|
3145
3218
|
import { existsSync, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
3146
|
-
import { homedir as homedir5 } from "node:os";
|
|
3147
3219
|
import { dirname as dirname2, join as join5, resolve as resolve2 } from "node:path";
|
|
3148
3220
|
function vaultRegistryDir(opts = {}) {
|
|
3149
|
-
return opts.registryDir ?? join5(
|
|
3221
|
+
return opts.registryDir ?? join5(heyspexHome2(), ".heyspex");
|
|
3150
3222
|
}
|
|
3151
3223
|
function vaultRegistryFilePath(opts = {}) {
|
|
3152
3224
|
return join5(vaultRegistryDir(opts), "registry.json");
|
|
@@ -3300,6 +3372,7 @@ function accountPointersOf(registry, accountId) {
|
|
|
3300
3372
|
var init_registry_file = __esm({
|
|
3301
3373
|
"spex-console/src/lib/vault-registry/registry-file.ts"() {
|
|
3302
3374
|
"use strict";
|
|
3375
|
+
init_heyspex_home2();
|
|
3303
3376
|
init_types();
|
|
3304
3377
|
init_types();
|
|
3305
3378
|
}
|
|
@@ -3478,6 +3551,30 @@ function isAbsolutePathForCompare(p) {
|
|
|
3478
3551
|
const s = p.trim();
|
|
3479
3552
|
return /^[\\/]/.test(s) || /^[a-zA-Z]:[\\/]/.test(s);
|
|
3480
3553
|
}
|
|
3554
|
+
function expandPinPlaceholders(value, repoRoot2) {
|
|
3555
|
+
return value.replace(/\$\{(?:CLAUDE_PROJECT_DIR|workspaceFolder)(?::-[^}]*)?\}/g, repoRoot2);
|
|
3556
|
+
}
|
|
3557
|
+
function lexicalJoin(base, rel) {
|
|
3558
|
+
const parts = `${base}/${rel}`.replace(/\\/g, "/").split("/");
|
|
3559
|
+
const out = [];
|
|
3560
|
+
for (const seg of parts) {
|
|
3561
|
+
if (seg === "" && out.length > 0) continue;
|
|
3562
|
+
if (seg === ".") continue;
|
|
3563
|
+
if (seg === ".." && out.length > 1) {
|
|
3564
|
+
out.pop();
|
|
3565
|
+
continue;
|
|
3566
|
+
}
|
|
3567
|
+
out.push(seg);
|
|
3568
|
+
}
|
|
3569
|
+
return out.join("/");
|
|
3570
|
+
}
|
|
3571
|
+
function parseMarkerVaultPath(content) {
|
|
3572
|
+
const m = content.match(/^vault_path:[ \t]*(.+?)[ \t]*$/m);
|
|
3573
|
+
if (!m) return null;
|
|
3574
|
+
const v = m[1].trim().replace(/\s+#.*$/, "").replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1").trim();
|
|
3575
|
+
if (!v || v.includes("${") || /^[\\/]/.test(v) || /^[a-zA-Z]:[\\/]/.test(v)) return null;
|
|
3576
|
+
return v;
|
|
3577
|
+
}
|
|
3481
3578
|
function readPinnedVaultRoot(repoRoot2, deps) {
|
|
3482
3579
|
const pins = [];
|
|
3483
3580
|
for (const rel of SATELLITE_MANIFEST_RELS) {
|
|
@@ -3494,9 +3591,13 @@ function readPinnedVaultRoot(repoRoot2, deps) {
|
|
|
3494
3591
|
}
|
|
3495
3592
|
if (typeof value !== "string") continue;
|
|
3496
3593
|
const trimmed = value.trim();
|
|
3497
|
-
if (!trimmed
|
|
3498
|
-
|
|
3499
|
-
|
|
3594
|
+
if (!trimmed) continue;
|
|
3595
|
+
const expanded = expandPinPlaceholders(trimmed, repoRoot2);
|
|
3596
|
+
if (expanded.includes("${")) continue;
|
|
3597
|
+
if (/^[a-zA-Z]:(?![\\/])/.test(expanded)) continue;
|
|
3598
|
+
const abs = isAbsolutePathForCompare(expanded) ? expanded.includes("..") ? lexicalJoin(expanded, ".") : expanded : lexicalJoin(repoRoot2, expanded);
|
|
3599
|
+
if (expanded !== trimmed && isAtOrUnder(abs, repoRoot2)) continue;
|
|
3600
|
+
pins.push({ source: rel.join("/"), value: abs });
|
|
3500
3601
|
}
|
|
3501
3602
|
return pins;
|
|
3502
3603
|
}
|
|
@@ -3547,6 +3648,24 @@ function readMarkerVaultId(dir) {
|
|
|
3547
3648
|
return null;
|
|
3548
3649
|
}
|
|
3549
3650
|
}
|
|
3651
|
+
function readMarkerSatellite(dir) {
|
|
3652
|
+
let raw;
|
|
3653
|
+
try {
|
|
3654
|
+
raw = readFileSync7(path2.join(dir, "heyspex.yaml"), "utf8");
|
|
3655
|
+
} catch {
|
|
3656
|
+
return null;
|
|
3657
|
+
}
|
|
3658
|
+
const vaultPath = parseMarkerVaultPath(raw);
|
|
3659
|
+
if (!vaultPath) return null;
|
|
3660
|
+
const vaultId = parseMarkerVaultId(raw);
|
|
3661
|
+
const candidate = path2.resolve(dir, vaultPath);
|
|
3662
|
+
let vaultRootAbs = null;
|
|
3663
|
+
if (candidate.toLowerCase() !== path2.resolve(dir).toLowerCase() && isVaultRootDir(candidate)) {
|
|
3664
|
+
const theirs = readMarkerVaultId(candidate);
|
|
3665
|
+
if (!vaultId || !theirs || theirs === vaultId) vaultRootAbs = candidate;
|
|
3666
|
+
}
|
|
3667
|
+
return { vaultId, vaultRootAbs };
|
|
3668
|
+
}
|
|
3550
3669
|
function isVaultRootDir(dir) {
|
|
3551
3670
|
const norm = (p) => path2.resolve(p).replace(/[\\/]+/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
3552
3671
|
if (norm(dir) === norm(tmpdir())) return false;
|
|
@@ -3567,6 +3686,14 @@ function findCwdVaultOrAttachment(startDir, stopAt) {
|
|
|
3567
3686
|
const boundary = stopAt ? path2.resolve(stopAt) : null;
|
|
3568
3687
|
let dir = startDir;
|
|
3569
3688
|
for (let i = 0; i < 256; i += 1) {
|
|
3689
|
+
const marked = readMarkerSatellite(dir);
|
|
3690
|
+
if (marked) {
|
|
3691
|
+
return {
|
|
3692
|
+
repoRootAbs: marked.vaultRootAbs ?? dir,
|
|
3693
|
+
satellite: true,
|
|
3694
|
+
markerVaultId: marked.vaultId
|
|
3695
|
+
};
|
|
3696
|
+
}
|
|
3570
3697
|
const pinned = readPinnedVaultRoot(dir, deps).find((pin) => !isAtOrUnder(pin.value, dir));
|
|
3571
3698
|
if (pinned) return { repoRootAbs: path2.resolve(pinned.value), satellite: true };
|
|
3572
3699
|
if (isVaultRootDir(dir)) return { repoRootAbs: dir, satellite: false };
|
|
@@ -3612,6 +3739,9 @@ async function resolveActiveVaultRoot(options2 = {}) {
|
|
|
3612
3739
|
const cwdMatch = findCwdVaultOrAttachment(cwdBase, options2.cwdWalkRoot);
|
|
3613
3740
|
if (cwdMatch?.satellite) {
|
|
3614
3741
|
onTier({ tier: "satellite-pin", outcome: "resolved", detail: cwdMatch.repoRootAbs });
|
|
3742
|
+
if (cwdMatch.markerVaultId) {
|
|
3743
|
+
return finalize(cwdMatch.markerVaultId, path2.resolve(cwdMatch.repoRootAbs), "satellite-pin");
|
|
3744
|
+
}
|
|
3615
3745
|
return finalizePathTier(cwdMatch.repoRootAbs, "satellite-pin");
|
|
3616
3746
|
}
|
|
3617
3747
|
if (cwdMatch) {
|
|
@@ -4795,6 +4925,55 @@ var init_branch_policy = __esm({
|
|
|
4795
4925
|
}
|
|
4796
4926
|
});
|
|
4797
4927
|
|
|
4928
|
+
// spex-console/src/lib/git-export/branch-resolver.ts
|
|
4929
|
+
function isValidSessionBranch(name, defaultBranch) {
|
|
4930
|
+
const b = name.trim();
|
|
4931
|
+
if (!b) return { ok: false, reason: "branch name is empty" };
|
|
4932
|
+
if (b === defaultBranch) {
|
|
4933
|
+
return { ok: false, reason: `\`${b}\` is the default branch; the drain never writes it` };
|
|
4934
|
+
}
|
|
4935
|
+
if (PROTECTED_SESSION_BRANCHES.includes(b)) {
|
|
4936
|
+
return { ok: false, reason: `\`${b}\` is a protected ref` };
|
|
4937
|
+
}
|
|
4938
|
+
const hasControlChar = [...b].some((c) => c.charCodeAt(0) < 32 || c.charCodeAt(0) === 127);
|
|
4939
|
+
if (hasControlChar || /[\s~^:?*[\\]/.test(b)) {
|
|
4940
|
+
return { ok: false, reason: "branch name contains characters git refs do not allow" };
|
|
4941
|
+
}
|
|
4942
|
+
if (b.includes("..") || b.includes("@{") || b.includes("//")) {
|
|
4943
|
+
return { ok: false, reason: "branch name contains a forbidden sequence (.. @{ //)" };
|
|
4944
|
+
}
|
|
4945
|
+
if (b.startsWith("/") || b.endsWith("/") || b.startsWith("-") || b.endsWith(".") || b === "@") {
|
|
4946
|
+
return { ok: false, reason: "branch name has a forbidden leading or trailing character" };
|
|
4947
|
+
}
|
|
4948
|
+
if (b.split("/").some((seg) => seg.startsWith(".") || seg.endsWith(".lock"))) {
|
|
4949
|
+
return {
|
|
4950
|
+
ok: false,
|
|
4951
|
+
reason: "branch name has a path segment starting with . or ending in .lock"
|
|
4952
|
+
};
|
|
4953
|
+
}
|
|
4954
|
+
return { ok: true };
|
|
4955
|
+
}
|
|
4956
|
+
function resolveSessionTargetBranch(input) {
|
|
4957
|
+
const dated = resolveTargetBranch({
|
|
4958
|
+
user: input.user,
|
|
4959
|
+
date: input.date,
|
|
4960
|
+
defaultBranch: input.defaultBranch
|
|
4961
|
+
});
|
|
4962
|
+
const declared = input.sessionBranch?.trim();
|
|
4963
|
+
if (!declared) return { branch: dated, source: "dated" };
|
|
4964
|
+
const check = isValidSessionBranch(declared, input.defaultBranch);
|
|
4965
|
+
if (!check.ok) return { branch: dated, source: "dated", reason: check.reason };
|
|
4966
|
+
return { branch: declared, source: "session" };
|
|
4967
|
+
}
|
|
4968
|
+
var PROTECTED_SESSION_BRANCHES;
|
|
4969
|
+
var init_branch_resolver = __esm({
|
|
4970
|
+
"spex-console/src/lib/git-export/branch-resolver.ts"() {
|
|
4971
|
+
"use strict";
|
|
4972
|
+
init_branch_policy();
|
|
4973
|
+
PROTECTED_SESSION_BRANCHES = ["main", "master", "HEAD", "trunk"];
|
|
4974
|
+
}
|
|
4975
|
+
});
|
|
4976
|
+
|
|
4798
4977
|
// spex-console/src/lib/git-export/config.ts
|
|
4799
4978
|
function parseGithubRemote(githubRemote) {
|
|
4800
4979
|
const match = githubRemote.match(/^([^/\s]+)\/([^/\s]+)$/);
|
|
@@ -5197,6 +5376,39 @@ var init_github_client = __esm({
|
|
|
5197
5376
|
}
|
|
5198
5377
|
});
|
|
5199
5378
|
|
|
5379
|
+
// spex-console/src/lib/git-export/session-branch-store.ts
|
|
5380
|
+
async function readActiveDeclaration(db, vaultId, actorKey, now) {
|
|
5381
|
+
const rows = await db.select().from(sessionBranchDeclarations).where(
|
|
5382
|
+
and(
|
|
5383
|
+
eq(sessionBranchDeclarations.vaultId, vaultId),
|
|
5384
|
+
eq(sessionBranchDeclarations.actorKey, actorKey),
|
|
5385
|
+
gt(sessionBranchDeclarations.expiresAt, now)
|
|
5386
|
+
)
|
|
5387
|
+
).orderBy(desc(sessionBranchDeclarations.declaredAt)).limit(1);
|
|
5388
|
+
const row = rows[0];
|
|
5389
|
+
if (!row) return null;
|
|
5390
|
+
return {
|
|
5391
|
+
vaultId: row.vaultId,
|
|
5392
|
+
actorKey: row.actorKey,
|
|
5393
|
+
sessionId: row.sessionId,
|
|
5394
|
+
branch: row.branch,
|
|
5395
|
+
declaredAt: row.declaredAt.toISOString(),
|
|
5396
|
+
expiresAt: row.expiresAt.toISOString()
|
|
5397
|
+
};
|
|
5398
|
+
}
|
|
5399
|
+
async function readActiveSessionBranch(db, vaultId, actorKey, now) {
|
|
5400
|
+
return (await readActiveDeclaration(db, vaultId, actorKey, now))?.branch ?? null;
|
|
5401
|
+
}
|
|
5402
|
+
var SESSION_BRANCH_TTL_MS;
|
|
5403
|
+
var init_session_branch_store = __esm({
|
|
5404
|
+
"spex-console/src/lib/git-export/session-branch-store.ts"() {
|
|
5405
|
+
"use strict";
|
|
5406
|
+
init_sql_orm_inert_cli_shim();
|
|
5407
|
+
init_postgres();
|
|
5408
|
+
SESSION_BRANCH_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
5409
|
+
}
|
|
5410
|
+
});
|
|
5411
|
+
|
|
5200
5412
|
// spex-console/src/lib/git-export/settlement-store.ts
|
|
5201
5413
|
async function recordSettlement(tx, input) {
|
|
5202
5414
|
await tx.insert(specSettlements).values({
|
|
@@ -5427,6 +5639,7 @@ async function processVault(db, vaultId, env, now, deps, batchLimit, jobTimeoutM
|
|
|
5427
5639
|
result: { status: "error", message: target.message }
|
|
5428
5640
|
};
|
|
5429
5641
|
}
|
|
5642
|
+
const lookupSessionBranch = deps.lookupSessionBranch ?? ((vId, actor) => readActiveSessionBranch(tx, vId, actor, now()));
|
|
5430
5643
|
const { config, tokenSource, installationId } = target;
|
|
5431
5644
|
const provider = createPatCommitProvider(() => config.token);
|
|
5432
5645
|
let pendingSettlement = null;
|
|
@@ -5440,11 +5653,18 @@ async function processVault(db, vaultId, env, now, deps, batchLimit, jobTimeoutM
|
|
|
5440
5653
|
fetchBundles: (specIds) => fetchDrainBundles(tx, vaultId, specIds),
|
|
5441
5654
|
resolveActorIdentity,
|
|
5442
5655
|
commit: async (plan, message, coAuthor) => {
|
|
5443
|
-
|
|
5656
|
+
let sessionBranch = null;
|
|
5657
|
+
try {
|
|
5658
|
+
sessionBranch = await lookupSessionBranch(vaultId, coAuthor.name);
|
|
5659
|
+
} catch {
|
|
5660
|
+
sessionBranch = null;
|
|
5661
|
+
}
|
|
5662
|
+
const targetBranch = resolveSessionTargetBranch({
|
|
5444
5663
|
user: coAuthor.name,
|
|
5445
5664
|
date: now(),
|
|
5446
|
-
defaultBranch: config.branch
|
|
5447
|
-
|
|
5665
|
+
defaultBranch: config.branch,
|
|
5666
|
+
sessionBranch
|
|
5667
|
+
}).branch;
|
|
5448
5668
|
const outcome = await commitPlanToGitHub(
|
|
5449
5669
|
provider,
|
|
5450
5670
|
config,
|
|
@@ -5585,12 +5805,13 @@ var init_drain_runner = __esm({
|
|
|
5585
5805
|
init_postgres();
|
|
5586
5806
|
init_github_app();
|
|
5587
5807
|
init_advisory_lock();
|
|
5588
|
-
|
|
5808
|
+
init_branch_resolver();
|
|
5589
5809
|
init_config();
|
|
5590
5810
|
init_drain();
|
|
5591
5811
|
init_drain_skip();
|
|
5592
5812
|
init_export_status();
|
|
5593
5813
|
init_github_client();
|
|
5814
|
+
init_session_branch_store();
|
|
5594
5815
|
init_settlement_store();
|
|
5595
5816
|
BOT_NAME = "heyspex-bot";
|
|
5596
5817
|
BOT_EMAIL = "bot@heyspex.app";
|
|
@@ -8154,7 +8375,7 @@ var init_plan_tier = __esm({
|
|
|
8154
8375
|
|
|
8155
8376
|
// spex-console/src/lib/db/clients/vault-router.ts
|
|
8156
8377
|
import { existsSync as existsSync4, readFileSync as readFileSync8 } from "node:fs";
|
|
8157
|
-
import { homedir as
|
|
8378
|
+
import { homedir as homedir7 } from "node:os";
|
|
8158
8379
|
import { join as join6 } from "node:path";
|
|
8159
8380
|
function normalizeDatabaseRef(raw) {
|
|
8160
8381
|
if (typeof raw !== "string") return null;
|
|
@@ -8287,7 +8508,7 @@ var init_vault_router = __esm({
|
|
|
8287
8508
|
init_postgres_client_cli_shim();
|
|
8288
8509
|
DEDICATED_DB_ENV_PREFIX = "HEYSPEX_DEDICATED_DB_";
|
|
8289
8510
|
DEDICATED_REFS_ENV = "DEDICATED_DATABASE_REFS";
|
|
8290
|
-
CREDENTIALS_PATH = join6(
|
|
8511
|
+
CREDENTIALS_PATH = join6(homedir7(), ".heyspex", "credentials.yaml");
|
|
8291
8512
|
REF_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
8292
8513
|
ROUTER_KEY = Symbol.for("heyspex.vaultRouter");
|
|
8293
8514
|
globalRouter = globalThis;
|
package/dist/cli/hs-dev.mjs
CHANGED
|
@@ -6,12 +6,24 @@ import process3 from "node:process";
|
|
|
6
6
|
|
|
7
7
|
// spex-console/src/lib/dev-mode.ts
|
|
8
8
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
9
|
-
import { homedir as homedir2 } from "node:os";
|
|
10
9
|
import { join as join2 } from "node:path";
|
|
11
10
|
|
|
11
|
+
// spex-console/src/lib/heyspex-home.ts
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
function heyspexHome(env = process.env) {
|
|
14
|
+
const override = env?.HEYSPEX_HOME;
|
|
15
|
+
if (typeof override === "string" && override.trim().length > 0) {
|
|
16
|
+
return override.trim();
|
|
17
|
+
}
|
|
18
|
+
return homedir();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// scripts/lib/heyspex-home.mjs
|
|
22
|
+
import { homedir as homedir2 } from "node:os";
|
|
23
|
+
|
|
12
24
|
// vendor/heyspex-mcp/credentials.mjs
|
|
13
25
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
14
|
-
import os, { homedir } from "node:os";
|
|
26
|
+
import os, { homedir as homedir3 } from "node:os";
|
|
15
27
|
import { dirname, join, resolve } from "node:path";
|
|
16
28
|
function underTestRunner(env = process.env) {
|
|
17
29
|
return Boolean(env.VITEST) || Boolean(env.NODE_TEST_CONTEXT);
|
|
@@ -74,12 +86,12 @@ function deriveSemantics(mode, reliance) {
|
|
|
74
86
|
vaultWriteMode: local ? "local" : "cloud"
|
|
75
87
|
};
|
|
76
88
|
}
|
|
77
|
-
function devModeFilePath(homeDir =
|
|
89
|
+
function devModeFilePath(homeDir = heyspexHome()) {
|
|
78
90
|
return join2(homeDir, ".heyspex", "dev-mode.json");
|
|
79
91
|
}
|
|
80
92
|
var defaultReadFile = (p) => readFileSync2(p, "utf8");
|
|
81
93
|
function readLocalDevModeRecord({
|
|
82
|
-
homeDir =
|
|
94
|
+
homeDir = heyspexHome(),
|
|
83
95
|
readFile = defaultReadFile
|
|
84
96
|
} = {}) {
|
|
85
97
|
let raw;
|
|
@@ -114,7 +126,7 @@ function readLocalDevModeRecord({
|
|
|
114
126
|
}
|
|
115
127
|
function resolveDevMode({
|
|
116
128
|
env = process.env,
|
|
117
|
-
homeDir =
|
|
129
|
+
homeDir = heyspexHome(),
|
|
118
130
|
readFile = defaultReadFile,
|
|
119
131
|
cloudSetting = void 0
|
|
120
132
|
} = {}) {
|
|
@@ -228,7 +240,7 @@ function upsertCredentialsYamlKeys(homeDir, updates, deps = {}) {
|
|
|
228
240
|
return filePath;
|
|
229
241
|
}
|
|
230
242
|
function readCredentialsMcpToken({
|
|
231
|
-
homeDir =
|
|
243
|
+
homeDir = heyspexHome(),
|
|
232
244
|
readFile = defaultReadFile
|
|
233
245
|
} = {}) {
|
|
234
246
|
try {
|
|
@@ -265,7 +277,7 @@ async function discardResponseBody(res) {
|
|
|
265
277
|
async function fetchCloudDevMode({
|
|
266
278
|
consoleUrl,
|
|
267
279
|
fetchImpl = fetch,
|
|
268
|
-
homeDir =
|
|
280
|
+
homeDir = heyspexHome(),
|
|
269
281
|
readFile = defaultReadFile,
|
|
270
282
|
timeoutMs = 4e3
|
|
271
283
|
}) {
|
|
@@ -305,7 +317,7 @@ var DevModeNotAdminError = class extends Error {
|
|
|
305
317
|
};
|
|
306
318
|
async function applyDevMode(targetMode, targetReliance, deps = {}) {
|
|
307
319
|
const {
|
|
308
|
-
homeDir =
|
|
320
|
+
homeDir = heyspexHome(),
|
|
309
321
|
fetchImpl = fetch,
|
|
310
322
|
source = "cli",
|
|
311
323
|
now = () => (/* @__PURE__ */ new Date()).toISOString(),
|