spexcode 0.2.3 → 0.2.4
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/README.md +2 -2
- package/package.json +1 -1
- package/spec-cli/src/sessions.ts +4 -0
- package/spec-cli/src/worktree-sources.ts +19 -0
package/README.md
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
Spec-driven development with AI agents in the loop. SpexCode keeps a versioned tree of specs inside
|
|
15
15
|
your git repo, links every spec to the code it governs, and runs a session manager that dispatches
|
|
16
16
|
coding agents into isolated worktrees. You review and merge; the tool keeps intent and
|
|
17
|
-
implementation from drifting apart.
|
|
17
|
+
implementation from drifting apart.
|
|
18
18
|
|
|
19
|
-
[](https://spexcode.net/assets/spec-tree-growth.mp4)
|
|
20
20
|
|
|
21
21
|
<sub>▶ This repo's own spec tree, replayed from its git history — 160 spec nodes growing over three weeks. Click for the [full video](https://spexcode.net/assets/spec-tree-growth.mp4).</sub>
|
|
22
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spexcode",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
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",
|
package/spec-cli/src/sessions.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { randomUUID } from 'node:crypto'
|
|
|
4
4
|
import { readFileSync, writeFileSync, appendFileSync, existsSync, renameSync, mkdirSync, rmSync, readdirSync, realpathSync, statSync } from 'node:fs'
|
|
5
5
|
import { join, dirname, relative, isAbsolute } from 'node:path'
|
|
6
6
|
import { fileURLToPath } from 'node:url'
|
|
7
|
+
import { linkUntrackedSpecSources } from './worktree-sources.js'
|
|
7
8
|
import { git, gitA, gitTry, repoRoot, mergeBaseDiff, mergeConflicts, type ReviewDiffFile } from './git.js'
|
|
8
9
|
import { loadSpecs } from './specs.js'
|
|
9
10
|
import { defaultHarness, defaultLauncher, harnessById, resolveLauncher, rvSock, rendezvousListening, type Harness, type DispatchResult, type PaneProbe, type ProcTable } from './harness.js'
|
|
@@ -1061,6 +1062,9 @@ export async function newSession(node: string | null, prompt: string, parent: st
|
|
|
1061
1062
|
const branch = `node/${slug}`
|
|
1062
1063
|
const path = join(mainRoot(), '.worktrees', slug)
|
|
1063
1064
|
await gitA(['-C', mainRoot(), 'worktree', 'add', '-b', branch, path, mainBranch()])
|
|
1065
|
+
// a private-overlay repo keeps the spec sources out of git, so the checkout alone leaves this worktree
|
|
1066
|
+
// spec-blind and hook-dead — link them from main ([[private-overlay]]; no-op on a default-mode repo).
|
|
1067
|
+
linkUntrackedSpecSources(mainRoot(), path)
|
|
1064
1068
|
// prepared but NOT launched: enters the queue as `queued`. drainQueue() below launches it at once when a
|
|
1065
1069
|
// slot is free, else it waits — durable as a global record (+ its worktree), so it survives a backend
|
|
1066
1070
|
// restart and is still findable. governed:true — this is a DASHBOARD/CLI-launched session, so it feeds the
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { existsSync, symlinkSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
// @@@ worktree-sources ([[private-overlay]]) - a fresh session worktree checks out only TRACKED content, and
|
|
5
|
+
// private mode keeps `.spec` + `spexcode.json` untracked (spexcode.local.json is untracked in BOTH modes) —
|
|
6
|
+
// so git alone hands a dispatched agent a worktree with NO spec tree: every hook handler script is absent
|
|
7
|
+
// (the dispatcher silently runs nothing), spex sees zero nodes, and the gate re-renders per event over empty
|
|
8
|
+
// config roots. Link those sources from the main checkout instead. On a default-mode repo the checkout
|
|
9
|
+
// already carries them, so each link guard no-ops — one mechanism, never a mode branch. A failure degrades
|
|
10
|
+
// that worker (no hooks, no specs), so it is reported, not swallowed.
|
|
11
|
+
export function linkUntrackedSpecSources(main: string, wt: string): void {
|
|
12
|
+
for (const f of ['.spec', 'spexcode.json', 'spexcode.local.json']) {
|
|
13
|
+
try {
|
|
14
|
+
if (existsSync(join(main, f)) && !existsSync(join(wt, f))) symlinkSync(join(main, f), join(wt, f))
|
|
15
|
+
} catch (e) {
|
|
16
|
+
console.error(`spexcode: could not link ${f} from ${main} into worktree ${wt} — that worker runs without it (${e})`)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|