heyspex 0.2.5 → 0.2.7
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 +1 -1
- package/bin/hs.mjs +349 -38
- package/bin/spexcode.mjs +31 -0
- package/dev-factory/lib/dispatch-guard.mjs +75 -0
- package/dev-factory/lib/local-firecrawl.mjs +294 -0
- package/dev-factory/lib/runner-path.mjs +51 -0
- package/dev-factory/lib/seat-context.mjs +20 -4
- package/dev-factory/model-catalog.json +222 -222
- package/dev-factory/spexcrawl/firecrawl-cli.mjs +755 -0
- package/dev-factory/spexcrawl/spexcrawl-cli.mjs +734 -0
- package/dist/cli/hs-connect.mjs +40 -3
- package/dist/cli/hs-defer.mjs +3817 -3741
- package/dist/cli/hs-events.mjs +1296 -0
- package/dist/cli/hs-export-events.mjs +1252 -0
- package/dist/cli/hs-handoff.mjs +2576 -0
- package/dist/cli/hs-index-rebuild.mjs +228 -37
- package/dist/cli/hs-index-reconcile.mjs +231 -40
- package/dist/cli/hs-init.mjs +22 -3
- package/dist/cli/hs-install.mjs +22 -3
- package/dist/cli/hs-join.mjs +40 -3
- package/dist/cli/hs-next-launch.mjs +2777 -0
- package/dist/cli/hs-pin.mjs +1336 -0
- package/dist/cli/hs-prereq.mjs +1380 -0
- package/dist/cli/hs-revalidate.mjs +3257 -0
- package/dist/cli/hs-spawn.mjs +12403 -0
- package/dist/cli/hs-test.mjs +1046 -0
- package/dist/cli/hs-trash.mjs +362 -0
- package/dist/cli/hs-trust.mjs +197 -0
- package/dist/cli/hs-vault-pull.mjs +233 -42
- package/dist/cli/hs-vault-push.mjs +231 -40
- package/dist/cli/hs-vault.mjs +21 -7
- package/dist/cli/hs-workspace.mjs +19 -1
- package/dist/cli-templates/customer-vault/specs/entity-model.md +1728 -1728
- package/dist/cli-templates/customer-vault/specs/protocols/canonical-frontmatter-templates.md +464 -464
- package/dist/cli-templates/customer-vault/specs/protocols/destructive-action-checklist.md +122 -122
- package/dist/cli-templates/customer-vault/specs/protocols/memory-protocol.md +46 -46
- package/dist/cli-templates/customer-vault/specs/protocols/spec-hierarchy.md +530 -530
- package/dist/cli-templates/customer-vault/specs/protocols/spec-summary-authoring.md +83 -83
- 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 -30
- 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-res.md +83 -63
- package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -23
- package/dist/cli-templates/harness-commands/claude/hs-view.md +28 -28
- 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 -24
- 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-res.md +78 -58
- package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +17 -17
- package/dist/cli-templates/harness-commands/cursor/hs-view.md +23 -23
- 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 +9 -2
- package/docs/mcp-client-config.md +6 -0
- package/package.json +266 -257
- package/plugins/heyspex/.claude-plugin/plugin.json +1 -1
- package/plugins/heyspex/.cursor-plugin/plugin.json +1 -1
- package/plugins/heyspex/README.md +6 -0
- package/plugins/heyspex/bin/launch-mcp.mjs +17 -0
- package/plugins/heyspex/hooks/hooks.json +418 -418
- package/scripts/claude-hooks/_intent-classifier-semantic.mjs +2 -2
- package/scripts/claude-hooks/wip-checkpoint.mjs +17 -2
- package/scripts/claude-statusline/statusline-command.mjs +287 -27
- package/scripts/hs-companion.mjs +41 -3
- package/scripts/install-claude-code-hooks.mjs +104 -3
- package/scripts/install-copilot-hooks.mjs +21 -1
- package/scripts/install-cursor-hooks.mjs +4 -3
- package/scripts/lib/capture-execution-guard.mjs +221 -0
- package/scripts/lib/companion-install.mjs +768 -0
- package/scripts/lib/customer-kit.mjs +53 -3
- package/scripts/lib/hs-companion-settings.mjs +26 -0
- package/scripts/lib/hs-source-push.mjs +386 -386
- package/scripts/record-grounding.mjs +38 -0
- package/spexharness/doctrine/baseline/SPEXCODE-DOCTRINE.baseline.json +29 -29
- package/spexharness/src/adapters/copilot-models.mjs +179 -0
- package/spexharness/src/adapters/harness-detect.mjs +148 -0
- package/spexharness/src/gates/directive-obligation-gate.decide.mjs +132 -132
- package/spexharness/src/gates/vault-write-tier-guard.decide.mjs +153 -125
- package/spexharness/src/seat-context.mjs +10 -5
- package/spexharness/src/session-bootstrap.mjs +6 -3
- package/vendor/heyspex-mcp/cli.mjs +6 -1
- package/vendor/heyspex-mcp/config-seed.yaml +15 -15
- package/vendor/heyspex-mcp/dev-factory-overlay.mjs +142 -0
- package/vendor/heyspex-mcp/http-transport.mjs +1 -1
- package/vendor/heyspex-mcp/memory-tools.mjs +523 -523
- package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -1708
- package/vendor/heyspex-mcp/procedure-handlers.mjs +327 -327
- package/vendor/heyspex-mcp/procedure-tools.mjs +1209 -1181
- package/vendor/heyspex-mcp/research-tools.mjs +22 -2
- package/vendor/heyspex-mcp/seat-assign-cli.mjs +242 -0
- package/vendor/heyspex-mcp/seat-assignment-rules.mjs +96 -0
- package/vendor/heyspex-mcp/seat-assignments-client.mjs +265 -0
- package/vendor/heyspex-mcp/seat-defaults-cli.mjs +45 -0
- package/vendor/heyspex-mcp/seat-defaults.mjs +232 -0
- package/vendor/heyspex-mcp/seat-identity.mjs +171 -0
- package/vendor/heyspex-mcp/test-helpers.mjs +37 -23
- package/vendor/heyspex-mcp/vault-io.mjs +720 -720
- package/bin/postinstall.mjs +0 -88
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
# .heyspex/config.yaml — HeySpex workflow settings for this vault.
|
|
2
|
-
# Seeded by `hs init` (ADR-0009 §1: the file lives at the VAULT root and is git-tracked).
|
|
3
|
-
# Field reference: specs/protocols/agent-settings-protocol.md. Change values with
|
|
4
|
-
# `hs settings set <key> <value>` or heyspex_settings_set — never by hand.
|
|
5
|
-
|
|
6
|
-
mvp_mode:
|
|
7
|
-
enabled: true
|
|
8
|
-
review_grain: epic
|
|
9
|
-
review_backlog_never_blocks: true
|
|
10
|
-
|
|
11
|
-
pricing_tier:
|
|
12
|
-
tier: free
|
|
13
|
-
|
|
14
|
-
agent_behaviors:
|
|
15
|
-
ask_forgiveness_not_permission: true
|
|
1
|
+
# .heyspex/config.yaml — HeySpex workflow settings for this vault.
|
|
2
|
+
# Seeded by `hs init` (ADR-0009 §1: the file lives at the VAULT root and is git-tracked).
|
|
3
|
+
# Field reference: specs/protocols/agent-settings-protocol.md. Change values with
|
|
4
|
+
# `hs settings set <key> <value>` or heyspex_settings_set — never by hand.
|
|
5
|
+
|
|
6
|
+
mvp_mode:
|
|
7
|
+
enabled: true
|
|
8
|
+
review_grain: epic
|
|
9
|
+
review_backlog_never_blocks: true
|
|
10
|
+
|
|
11
|
+
pricing_tier:
|
|
12
|
+
tier: free
|
|
13
|
+
|
|
14
|
+
agent_behaviors:
|
|
15
|
+
ask_forgiveness_not_permission: true
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// dev-factory-overlay.mjs — the ONE gate that decides whether the owner's personal
|
|
3
|
+
// dev-factory overlay may load ([[HS-R475-C86Z-TASK-load-the-owner-dev-factory-overlay-only]],
|
|
4
|
+
// epic [[HS-9JMD-C86Z-EPIC-owner-dev-factory-isolation]], research
|
|
5
|
+
// [[HS-RXJO-C86Z-RES-spexfleet-per-user-seat-assignment-with]] §Owner dev-factory isolation).
|
|
6
|
+
//
|
|
7
|
+
// The overlay is the owner's own fleet configuration under `<repo>/dev-factory/`:
|
|
8
|
+
// routing-table.json (which model fills which purpose), seats.json (the seat roster and
|
|
9
|
+
// each seat's fill), budget-config.json (per-company spend caps). It must never be read,
|
|
10
|
+
// inherited or overwritten by another HeySpex developer. It loads only when ALL hold:
|
|
11
|
+
//
|
|
12
|
+
// 1. switch — `HEYSPEX_DEV_FACTORY` is not "0" (the owner's off switch);
|
|
13
|
+
// 2. checkout — the root is a heyspex-app SOURCE checkout: package.json name "heyspex",
|
|
14
|
+
// a `.git` entry (dir, or file for a worktree), a `dev-factory/` dir, and
|
|
15
|
+
// not under `node_modules/` (an installed package is never a checkout);
|
|
16
|
+
// 3. account — when the overlay declares its owners (`dev-factory/overlay-owner.json`
|
|
17
|
+
// `{ "account_ids": [...] }`), the signed-in account (HS_ACCOUNT_ID, else
|
|
18
|
+
// the credentials store's current account) is one of them. Signed out is
|
|
19
|
+
// allowed (not another user; the owner's offline fleet machines keep
|
|
20
|
+
// running). No declaration = no account check (back-compat).
|
|
21
|
+
//
|
|
22
|
+
// An explicit `HS_DEV_FACTORY_ROOT` naming this root's dev-factory dir is the caller's own
|
|
23
|
+
// opt-in (test fixtures, the owner's coordinator) and skips check 2 — it never skips 1 or 3.
|
|
24
|
+
// The console's builder gate (`guardOwnerFactoryRead`) is the account check for HTTP callers.
|
|
25
|
+
//
|
|
26
|
+
// Plain Node ESM, builtins + ./credentials.mjs only, never throws. Packaged (vendor glob) so
|
|
27
|
+
// every packaged reader can call it; a packaged install always resolves "closed" at check 2.
|
|
28
|
+
//
|
|
29
|
+
// node vendor/heyspex-mcp/dev-factory-overlay.mjs # prints the verdict JSON
|
|
30
|
+
// node vendor/heyspex-mcp/dev-factory-overlay.mjs --assert-open # exit 1 unless open, and
|
|
31
|
+
// # proves the files still load
|
|
32
|
+
|
|
33
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
34
|
+
import path from 'node:path';
|
|
35
|
+
import { fileURLToPath } from 'node:url';
|
|
36
|
+
|
|
37
|
+
import { readCurrentAccountId } from './credentials.mjs';
|
|
38
|
+
|
|
39
|
+
export const DEV_FACTORY_SWITCH_ENV = 'HEYSPEX_DEV_FACTORY';
|
|
40
|
+
export const OVERLAY_OWNER_FILE = 'overlay-owner.json';
|
|
41
|
+
/** The overlay files this gate guards, relative to `<root>/dev-factory/`. */
|
|
42
|
+
export const OVERLAY_FILES = Object.freeze(['routing-table.json', 'seats.json', 'budget-config.json']);
|
|
43
|
+
|
|
44
|
+
const norm = (p) => path.resolve(String(p)).replaceAll('\\', '/').replace(/\/+$/, '').toLowerCase();
|
|
45
|
+
|
|
46
|
+
function readJsonOrNull(file) {
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(readFileSync(file, 'utf8'));
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** True when `root` is a heyspex-app source checkout (see header check 2). Never throws. */
|
|
55
|
+
export function isHeyspexSourceCheckout(root) {
|
|
56
|
+
try {
|
|
57
|
+
if (!root) return false;
|
|
58
|
+
const abs = path.resolve(String(root));
|
|
59
|
+
if (/[\\/]node_modules([\\/]|$)/i.test(abs)) return false;
|
|
60
|
+
if (!existsSync(path.join(abs, '.git'))) return false;
|
|
61
|
+
if (!existsSync(path.join(abs, 'dev-factory'))) return false;
|
|
62
|
+
const pkg = readJsonOrNull(path.join(abs, 'package.json'));
|
|
63
|
+
return pkg?.name === 'heyspex';
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** The account ids `dev-factory/overlay-owner.json` declares as the overlay's owners ([] = undeclared). */
|
|
70
|
+
export function declaredOverlayOwners(root) {
|
|
71
|
+
const doc = root ? readJsonOrNull(path.join(String(root), 'dev-factory', OVERLAY_OWNER_FILE)) : null;
|
|
72
|
+
const ids = Array.isArray(doc?.account_ids) ? doc.account_ids : [];
|
|
73
|
+
return ids.filter((id) => typeof id === 'string' && id.trim()).map((id) => id.trim());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The full verdict. `root` is the REPO root (the directory that holds `dev-factory/`).
|
|
78
|
+
* @param {{ root: string, env?: Record<string, string|undefined>, accountId?: string|null }} opts
|
|
79
|
+
* `accountId` — injected signed-in account (tests); read from env/credentials otherwise.
|
|
80
|
+
* @returns {{ open: boolean, reason: string, root: string|null, accountId: string|null, owners: string[] }}
|
|
81
|
+
*/
|
|
82
|
+
export function devFactoryOverlayVerdict({ root, env = process.env, accountId } = {}) {
|
|
83
|
+
const out = (open, reason, extra = {}) => ({ open, reason, root: root ? path.resolve(String(root)) : null, accountId: null, owners: [], ...extra });
|
|
84
|
+
try {
|
|
85
|
+
if (!root) return out(false, 'no-root');
|
|
86
|
+
if (String(env?.[DEV_FACTORY_SWITCH_ENV] ?? '').trim() === '0') return out(false, 'disabled');
|
|
87
|
+
|
|
88
|
+
const override = env?.HS_DEV_FACTORY_ROOT;
|
|
89
|
+
const optedIn = Boolean(override) && norm(override) === norm(path.join(String(root), 'dev-factory'));
|
|
90
|
+
if (!optedIn && !isHeyspexSourceCheckout(root)) return out(false, 'not-source-checkout');
|
|
91
|
+
|
|
92
|
+
const owners = declaredOverlayOwners(root);
|
|
93
|
+
const who =
|
|
94
|
+
accountId !== undefined
|
|
95
|
+
? accountId
|
|
96
|
+
: (env?.HS_ACCOUNT_ID && String(env.HS_ACCOUNT_ID).trim()) || safeCurrentAccountId();
|
|
97
|
+
if (owners.length > 0 && who && !owners.includes(who)) {
|
|
98
|
+
return out(false, 'not-owner-account', { accountId: who, owners });
|
|
99
|
+
}
|
|
100
|
+
const reason = optedIn ? 'override' : owners.length === 0 ? 'owner-undeclared' : who ? 'owner' : 'signed-out';
|
|
101
|
+
return out(true, reason, { accountId: who ?? null, owners });
|
|
102
|
+
} catch {
|
|
103
|
+
return out(false, 'error');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function safeCurrentAccountId() {
|
|
108
|
+
try {
|
|
109
|
+
return readCurrentAccountId() ?? null;
|
|
110
|
+
} catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Boolean form of {@link devFactoryOverlayVerdict}. */
|
|
116
|
+
export function isDevFactoryOverlayOpen(root, opts = {}) {
|
|
117
|
+
return devFactoryOverlayVerdict({ ...opts, root }).open;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Same verdict, keyed by the dev-factory DIRECTORY (what the console's
|
|
122
|
+
* `resolveDevFactoryRoot()` returns) instead of the repo root.
|
|
123
|
+
*/
|
|
124
|
+
export function isDevFactoryDirOverlayOpen(devFactoryDir, opts = {}) {
|
|
125
|
+
if (!devFactoryDir) return false;
|
|
126
|
+
return isDevFactoryOverlayOpen(path.dirname(path.resolve(String(devFactoryDir))), opts);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ── CLI ──────────────────────────────────────────────────────────────────────
|
|
130
|
+
const self = fileURLToPath(import.meta.url);
|
|
131
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === self) {
|
|
132
|
+
const root = path.resolve(path.dirname(self), '..', '..');
|
|
133
|
+
const verdict = devFactoryOverlayVerdict({ root });
|
|
134
|
+
const loads = Object.fromEntries(
|
|
135
|
+
OVERLAY_FILES.map((f) => [f, readJsonOrNull(path.join(root, 'dev-factory', f)) !== null]),
|
|
136
|
+
);
|
|
137
|
+
console.log(JSON.stringify({ ...verdict, loads }, null, 2));
|
|
138
|
+
if (process.argv.includes('--assert-open')) {
|
|
139
|
+
const ok = verdict.open && loads['routing-table.json'] && loads['seats.json'];
|
|
140
|
+
process.exit(ok ? 0 : 1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -111,7 +111,7 @@ export function toolNotAvailableRemotelyError(id, name) {
|
|
|
111
111
|
* @property {(name: string) => boolean} [isKnownTool]
|
|
112
112
|
* Whether a name exists in the FULL catalog — distinguishes "needs the local
|
|
113
113
|
* server" from "no such tool" (default: same as `isToolAllowed`).
|
|
114
|
-
* @property {{ name: string, version: string }} serverInfo
|
|
114
|
+
* @property {{ name: string, version: string, title?: string, icons?: ReadonlyArray<{ src: string, mimeType?: string, sizes?: ReadonlyArray<string> }> }} serverInfo
|
|
115
115
|
* @property {string} [instructions]
|
|
116
116
|
* @property {string} vaultRoot
|
|
117
117
|
* Passed through to `dispatch`. For the remote endpoint this is a path that
|