spexcode 0.6.5 → 0.6.6

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 (56) hide show
  1. package/node_modules/@spexcode/{spec-cli → session-core}/dist/delivery-queue.d.ts +1 -1
  2. package/node_modules/@spexcode/{spec-cli → session-core}/dist/delivery-queue.js +18 -2
  3. package/node_modules/@spexcode/session-core/dist/index.d.ts +5 -0
  4. package/node_modules/@spexcode/session-core/dist/index.js +5 -0
  5. package/node_modules/@spexcode/session-core/dist/internal.d.ts +3 -0
  6. package/node_modules/@spexcode/session-core/dist/internal.js +3 -0
  7. package/node_modules/@spexcode/session-core/dist/message.d.ts +22 -0
  8. package/node_modules/@spexcode/session-core/dist/message.js +52 -0
  9. package/node_modules/@spexcode/session-core/dist/record-lock.d.ts +7 -0
  10. package/node_modules/@spexcode/session-core/dist/record-lock.js +152 -0
  11. package/node_modules/@spexcode/session-core/dist/runtime-session.d.ts +50 -0
  12. package/node_modules/@spexcode/session-core/dist/runtime-session.js +286 -0
  13. package/node_modules/@spexcode/session-core/dist/session-timeline.d.ts +46 -0
  14. package/node_modules/@spexcode/session-core/dist/session-timeline.js +216 -0
  15. package/node_modules/@spexcode/session-core/package.json +33 -0
  16. package/node_modules/@spexcode/spec-cli/bin/spex.mjs +2 -1
  17. package/node_modules/@spexcode/spec-cli/dist/claude-headless.d.ts +4 -1
  18. package/node_modules/@spexcode/spec-cli/dist/claude-headless.js +13 -4
  19. package/node_modules/@spexcode/spec-cli/dist/cli.js +72 -23
  20. package/node_modules/@spexcode/spec-cli/dist/client.d.ts +2 -1
  21. package/node_modules/@spexcode/spec-cli/dist/client.js +13 -8
  22. package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.d.ts +5 -0
  23. package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.js +112 -0
  24. package/node_modules/@spexcode/spec-cli/dist/doctor.js +7 -1
  25. package/node_modules/@spexcode/spec-cli/dist/gateway-hub.js +7 -5
  26. package/node_modules/@spexcode/spec-cli/dist/gateway.d.ts +1 -0
  27. package/node_modules/@spexcode/spec-cli/dist/gateway.js +44 -20
  28. package/node_modules/@spexcode/spec-cli/dist/graphCache.js +2 -1
  29. package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.js +2 -1
  30. package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +15 -2
  31. package/node_modules/@spexcode/spec-cli/dist/harness.js +174 -54
  32. package/node_modules/@spexcode/spec-cli/dist/help.d.ts +5 -0
  33. package/node_modules/@spexcode/spec-cli/dist/help.js +26 -6
  34. package/node_modules/@spexcode/spec-cli/dist/index.js +3 -3
  35. package/node_modules/@spexcode/spec-cli/dist/listen.d.ts +2 -1
  36. package/node_modules/@spexcode/spec-cli/dist/listen.js +10 -10
  37. package/node_modules/@spexcode/spec-cli/dist/opencode-headless.d.ts +1 -0
  38. package/node_modules/@spexcode/spec-cli/dist/opencode-headless.js +7 -0
  39. package/node_modules/@spexcode/spec-cli/dist/runtime-rotate.d.ts +1 -0
  40. package/node_modules/@spexcode/spec-cli/dist/runtime-rotate.js +58 -0
  41. package/node_modules/@spexcode/spec-cli/dist/session-follow.js +1 -1
  42. package/node_modules/@spexcode/spec-cli/dist/session-timeline.d.ts +6 -46
  43. package/node_modules/@spexcode/spec-cli/dist/session-timeline.js +8 -221
  44. package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +25 -4
  45. package/node_modules/@spexcode/spec-cli/dist/sessions.js +822 -394
  46. package/node_modules/@spexcode/spec-cli/dist/supervise.js +3 -3
  47. package/node_modules/@spexcode/spec-cli/package.json +6 -4
  48. package/node_modules/@spexcode/spec-core/dist/git.d.ts +4 -0
  49. package/node_modules/@spexcode/spec-core/dist/git.js +32 -0
  50. package/node_modules/@spexcode/spec-core/dist/layout.d.ts +4 -0
  51. package/node_modules/@spexcode/spec-core/package.json +1 -1
  52. package/node_modules/@spexcode/spec-eval/package.json +2 -2
  53. package/node_modules/@spexcode/spec-forge/package.json +2 -2
  54. package/package.json +3 -3
  55. /package/node_modules/@spexcode/{spec-cli → session-core}/dist/session-cursors.d.ts +0 -0
  56. /package/node_modules/@spexcode/{spec-cli → session-core}/dist/session-cursors.js +0 -0
@@ -42,7 +42,7 @@ const childApiBase = `http://127.0.0.1:${proxyPort}`;
42
42
  // observe the source closure, compile it, then make the supervisor's normal zero-downtime swap. A source edit
43
43
  // must never cause a restart that still runs the old dist.
44
44
  const watchRoots = workspaceRoot
45
- ? [sourceRoot, join(workspaceRoot, 'spec-forge', 'src'), join(workspaceRoot, 'spec-eval', 'src'), join(workspaceRoot, 'packages', 'spec-core', 'src')]
45
+ ? [sourceRoot, join(workspaceRoot, 'spec-forge', 'src'), join(workspaceRoot, 'spec-eval', 'src'), join(workspaceRoot, 'packages', 'spec-core', 'src'), join(workspaceRoot, 'packages', 'session-core', 'src')]
46
46
  : [here];
47
47
  function buildWorkspace() {
48
48
  if (!workspaceRoot)
@@ -246,11 +246,11 @@ catch { /* already gone */ } };
246
246
  if (publicCfg) {
247
247
  // public mode: the raw proxy stays on loopback; the password-gated gateway owns the public port.
248
248
  const distDir = resolveDistDir();
249
- listenOrExit(proxy, proxyPort, { host: '127.0.0.1', label: 'supervisor (loopback proxy)', cleanup: reapChild, onListen: () => { recordEndpoint(childApiBase); console.log(`spec-cli supervisor on loopback :${proxyPort} (zero-downtime reloads, backend :${first.port})`); } });
249
+ listenOrExit(proxy, proxyPort, { host: '127.0.0.1', label: 'supervisor (loopback proxy)', cleanup: reapChild, onListen: () => recordEndpoint(childApiBase), ready: `spec-cli supervisor on loopback :${proxyPort} (zero-downtime reloads, backend :${first.port})` });
250
250
  startGateway({ publicPort, upstreamPort: proxyPort, password: publicCfg.password, tls: publicCfg.tls, distDir, onBindFail: reapChild });
251
251
  }
252
252
  else {
253
- listenOrExit(proxy, publicPort, { label: 'supervisor', cleanup: reapChild, onListen: () => { recordEndpoint(childApiBase); console.log(`spec-cli supervisor serving on http://localhost:${publicPort} (zero-downtime reloads, backend :${first.port})`); } });
253
+ listenOrExit(proxy, publicPort, { label: 'supervisor', cleanup: reapChild, onListen: () => recordEndpoint(childApiBase), ready: `spec-cli supervisor serving on http://localhost:${publicPort} (zero-downtime reloads, backend :${first.port})` });
254
254
  }
255
255
  startResourceMonitor();
256
256
  // Watch the source closure in a workspace and the emitted directory in an installed package. Debounce a
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spexcode/spec-cli",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "type": "module",
5
5
  "description": "SpexCode CLI + server. The root spexcode package delegates to this compiled package; dashboard assets live in @spexcode/spec-dashboard.",
6
6
  "bin": {
@@ -21,6 +21,7 @@
21
21
  ],
22
22
  "bundledDependencies": [
23
23
  "@spexcode/spec-core",
24
+ "@spexcode/session-core",
24
25
  "@spexcode/spec-eval",
25
26
  "@spexcode/spec-forge"
26
27
  ],
@@ -35,9 +36,10 @@
35
36
  "test": "tsx --import ../scripts/test-home.mjs --test src/*.test.ts"
36
37
  },
37
38
  "dependencies": {
38
- "@spexcode/spec-core": "0.6.5",
39
- "@spexcode/spec-eval": "0.6.5",
40
- "@spexcode/spec-forge": "0.6.5"
39
+ "@spexcode/session-core": "0.6.6",
40
+ "@spexcode/spec-core": "0.6.6",
41
+ "@spexcode/spec-eval": "0.6.6",
42
+ "@spexcode/spec-forge": "0.6.6"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@types/node": "^20.16.0",
@@ -51,6 +51,10 @@ export declare function gitRequiredA(args: string[], purpose: string, options?:
51
51
  input?: string;
52
52
  extraEnv?: Record<string, string | undefined>;
53
53
  }): Promise<string>;
54
+ export declare class GitWorkspaceError extends Error {
55
+ constructor(root: string);
56
+ }
57
+ export declare function requireGitWorkspace(root: string): void;
54
58
  export declare function repoRoot(): string;
55
59
  export declare function headSha(root: string): string;
56
60
  export declare function worktreeSpecSig(wtPath: string): string;
@@ -1212,6 +1212,32 @@ export async function gitRequiredA(args, purpose, options = {}) {
1212
1212
  throw new Error(`${purpose}: git ${args.slice(2).join(' ')} failed: ${String(error?.stderr || error?.message || 'unknown git error').trim()}`);
1213
1213
  }
1214
1214
  }
1215
+ const checkedGitWorkspaces = new Set();
1216
+ // A Git-backed read needs a repository before it can derive history. This is not a Git transport failure:
1217
+ // it is the product precondition, shared by every history entrance.
1218
+ export class GitWorkspaceError extends Error {
1219
+ constructor(root) {
1220
+ super(`workspace is not a Git repository: ${resolve(root)}. Run \`git init\` in that directory, then retry.`);
1221
+ this.name = 'GitWorkspaceError';
1222
+ }
1223
+ }
1224
+ export function requireGitWorkspace(root) {
1225
+ const workspace = resolve(root);
1226
+ if (checkedGitWorkspaces.has(workspace))
1227
+ return;
1228
+ try {
1229
+ if (git(['-C', workspace, 'rev-parse', '--git-dir']).trim()) {
1230
+ checkedGitWorkspaces.add(workspace);
1231
+ return;
1232
+ }
1233
+ }
1234
+ catch (error) {
1235
+ // Exit 128 is Git's repository-discovery rejection. Spawn and timeout failures keep their own cause.
1236
+ if (error?.status !== 128 || !String(error?.stderr ?? '').includes('not a git repository'))
1237
+ throw error;
1238
+ }
1239
+ throw new GitWorkspaceError(workspace);
1240
+ }
1215
1241
  // memoized: repoRoot is constant per process, but resolveLayout() calls it per request — avoid a git fork each time.
1216
1242
  let repoRootCache = null;
1217
1243
  export function repoRoot() {
@@ -1451,6 +1477,7 @@ function pendingParent(root, tip) {
1451
1477
  }
1452
1478
  }
1453
1479
  export function historyIndex(root, tip = 'HEAD') {
1480
+ requireGitWorkspace(root);
1454
1481
  if (tip !== 'HEAD') {
1455
1482
  const resolved = git(['-C', root, 'rev-parse', `${tip}^{commit}`]).trim();
1456
1483
  // An issue-only candidate changes no governed content, but its lint result still includes the
@@ -2123,6 +2150,7 @@ async function buildDriftIndex(root, tip, transient, useCache = true, shared) {
2123
2150
  return idx;
2124
2151
  }
2125
2152
  export function driftIndex(root, tip = 'HEAD') {
2153
+ requireGitWorkspace(root);
2126
2154
  if (tip !== 'HEAD') {
2127
2155
  const resolved = git(['-C', root, 'rev-parse', `${tip}^{commit}`]).trim();
2128
2156
  if (pendingOnlyIssues(root, resolved)) {
@@ -2199,6 +2227,7 @@ async function buildIndexPair(root, tip, transient, useCache = true) {
2199
2227
  }
2200
2228
  // Standing correctness oracle: same projection, but every immutable stream comes from Git root history.
2201
2229
  export function sourceIndexesFull(root, tip = 'HEAD') {
2230
+ requireGitWorkspace(root);
2202
2231
  const head = tip === 'HEAD' ? headOrEmpty(root) : '';
2203
2232
  const resolved = tip === 'HEAD'
2204
2233
  ? (head || 'HEAD')
@@ -2208,6 +2237,7 @@ export function sourceIndexesFull(root, tip = 'HEAD') {
2208
2237
  // History and drift are one product projection. Building them together is what gives one lint one ledger
2209
2238
  // transaction; the public single-index functions remain for consumers that genuinely need only one side.
2210
2239
  export function sourceIndexes(root, tip = 'HEAD') {
2240
+ requireGitWorkspace(root);
2211
2241
  if (tip !== 'HEAD') {
2212
2242
  const resolved = git(['-C', root, 'rev-parse', `${tip}^{commit}`]).trim();
2213
2243
  if (pendingOnlyIssues(root, resolved)) {
@@ -2249,6 +2279,7 @@ export function resetHistoryCachesForTests() {
2249
2279
  driftRoots.clear();
2250
2280
  eventPathMemo.clear();
2251
2281
  gitObjectFormatMemo.clear();
2282
+ checkedGitWorkspaces.clear();
2252
2283
  }
2253
2284
  export function historyEventCachePathForTests(root) { return eventCacheLocation(root).path; }
2254
2285
  // @@@ one ordinary ancestry memo, with a batch entrance - every closure below has exactly the same dense
@@ -2366,6 +2397,7 @@ export function inAncestors(idx, bits, sha) {
2366
2397
  // structure, never a graft into the shared index: making off-history tips reachable there would silently
2367
2398
  // switch every ancestry-vs-content decision that keys on `undefined`.
2368
2399
  export async function unionTopology(root, revisions) {
2400
+ requireGitWorkspace(root);
2369
2401
  const roster = [...new Set(revisions)].filter(Boolean);
2370
2402
  const reach = { ord: new Map(), parents: new Map(), anc: new Map() };
2371
2403
  if (!roster.length)
@@ -120,6 +120,10 @@ export type RawRecord = {
120
120
  create_request_id?: string;
121
121
  create_payload_hash?: string;
122
122
  zcode_child_session_ids?: string[];
123
+ runtime_owner?: string;
124
+ runtime_state?: string;
125
+ runtime_revision?: string;
126
+ runtime_metadata?: Record<string, string>;
123
127
  base?: string;
124
128
  launch_readiness_pending?: '' | RawLaunchReadinessPending;
125
129
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spexcode/spec-core",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "type": "module",
5
5
  "description": "SpexCode's dependency-minimal spec graph core.",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spexcode/spec-eval",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "test": "tsx --import ../scripts/test-home.mjs --test src/*.test.ts"
27
27
  },
28
28
  "dependencies": {
29
- "@spexcode/spec-core": "0.6.5"
29
+ "@spexcode/spec-core": "0.6.6"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^20.16.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spexcode/spec-forge",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "test": "tsx --test src/*.test.ts"
23
23
  },
24
24
  "dependencies": {
25
- "@spexcode/spec-core": "0.6.5"
25
+ "@spexcode/spec-core": "0.6.6"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^20.16.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spexcode",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "type": "module",
5
5
  "description": "SpexCode — a spec-driven, self-developing dev tool. The `spex` CLI + spec server reads the .spec tree and its git history, and serves the dashboard.",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  "node": ">=22"
22
22
  },
23
23
  "scripts": {
24
- "build": "npm run build --workspace=@spexcode/spec-core && npm run build --workspace=@spexcode/spec-eval && npm run build --workspace=@spexcode/spec-forge && npm run build --workspace=@spexcode/spec-cli",
24
+ "build": "npm run build --workspace=@spexcode/spec-core && npm run build --workspace=@spexcode/session-core && npm run build --workspace=@spexcode/spec-eval && npm run build --workspace=@spexcode/spec-forge && npm run build --workspace=@spexcode/spec-cli",
25
25
  "api": "npm run build && node bin/spex.mjs serve",
26
26
  "web": "cd spec-dashboard && npm run dev",
27
27
  "build:public": "node scripts/public-graph-build.mjs",
@@ -38,7 +38,7 @@
38
38
  "prepack": "node scripts/sync-init-plugins.mjs --check && node scripts/prepack.mjs"
39
39
  },
40
40
  "dependencies": {
41
- "@spexcode/spec-cli": "0.6.5"
41
+ "@spexcode/spec-cli": "0.6.6"
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public"