spexcode 0.5.5 → 0.5.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/package.json +1 -1
- package/spec-cli/src/cli.ts +18 -1
- package/spec-cli/src/client.ts +21 -0
- package/spec-cli/src/git.ts +460 -238
- package/spec-cli/src/harness.ts +116 -24
- package/spec-cli/src/help.ts +3 -1
- package/spec-cli/src/index.ts +48 -9
- package/spec-cli/src/layout.ts +2 -0
- package/spec-cli/src/mentions.ts +10 -5
- package/spec-cli/src/process-identity.ts +20 -0
- package/spec-cli/src/reviewSnapshot.ts +4 -0
- package/spec-cli/src/reviews.ts +10 -5
- package/spec-cli/src/session-maintenance.ts +2 -1
- package/spec-cli/src/sessions.ts +898 -140
- package/spec-cli/src/specs.ts +3 -3
- package/spec-dashboard/dist/assets/{App-C5vbTw8Q.js → App-u2P7KdSg.js} +2 -2
- package/spec-dashboard/dist/assets/Dashboard-B8wp5_61.js +27 -0
- package/spec-dashboard/dist/assets/{EvalsPage-BS7ITcNo.js → EvalsPage-Bq1Tkb8y.js} +2 -2
- package/spec-dashboard/dist/assets/IssuesPage-BlkPSkmv.js +1 -0
- package/spec-dashboard/dist/assets/{MobileApp-DVLnk9hz.js → MobileApp-B1GxRZXK.js} +2 -2
- package/spec-dashboard/dist/assets/{Modal-6mHq6fbZ.js → Modal-bAkq9IIT.js} +1 -1
- package/spec-dashboard/dist/assets/{PageScroll-CAY4S4g4.js → PageScroll-px_rUZVJ.js} +1 -1
- package/spec-dashboard/dist/assets/{ProjectsPage-UQyzsTWN.js → ProjectsPage-8uGqYM12.js} +1 -1
- package/spec-dashboard/dist/assets/SessionInterface-CswwbewF.js +39 -0
- package/spec-dashboard/dist/assets/SessionWindow-IspcLjFA.js +1 -0
- package/spec-dashboard/dist/assets/{Settings-igR17pns.js → Settings-bpAbfnmS.js} +1 -1
- package/spec-dashboard/dist/assets/{Thread-B-ZUarN1.js → Thread-BpL3N3kw.js} +11 -11
- package/spec-dashboard/dist/assets/{TimelineChat-sc49Qj5d.js → TimelineChat-Ckmb1Ez2.js} +1 -1
- package/spec-dashboard/dist/assets/{data-B1ot4PF0.js → data-CQFbQEMH.js} +1 -1
- package/spec-dashboard/dist/assets/index-CixSnz1H.css +1 -0
- package/spec-dashboard/dist/assets/index-Di1ch5dd.js +41 -0
- package/spec-dashboard/dist/index.html +2 -2
- package/spec-dashboard/dist/assets/Dashboard-u8RIS3NY.js +0 -27
- package/spec-dashboard/dist/assets/IssuesPage-DXbqQFW_.js +0 -1
- package/spec-dashboard/dist/assets/SessionInterface-DKU4c1Z-.js +0 -39
- package/spec-dashboard/dist/assets/SessionWindow-zGwJaGbR.js +0 -1
- package/spec-dashboard/dist/assets/index-BqBNCa1V.js +0 -41
- package/spec-dashboard/dist/assets/index-CzutlTDf.css +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spexcode",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
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/cli.ts
CHANGED
|
@@ -50,7 +50,7 @@ function flushExit(code = 0): Promise<never> {
|
|
|
50
50
|
}
|
|
51
51
|
const has = (name: string) => process.argv.includes(`--${name}`)
|
|
52
52
|
// bare positionals after argv index `from`, skipping flags and their values (selectors for ls/watch).
|
|
53
|
-
const VALUE_FLAGS = new Set(['--status', '--as', '--interval', '--propose', '--note', '--node', '--prompt', '--prompt-file', '--timeout', '--reason', '--out', '--password', '--tls-cert', '--tls-key', '--harness', '--launcher', '--harness-session', '--port', '--api', '--api-port', '--host', '--preset', '--limit', '--session', '--depth', '--focus', '--keys', '--allow-stop', '--allow-resume', '--ttl-ms', '--wait-ms'])
|
|
53
|
+
const VALUE_FLAGS = new Set(['--status', '--as', '--interval', '--propose', '--note', '--node', '--prompt', '--prompt-file', '--timeout', '--reason', '--out', '--password', '--tls-cert', '--tls-key', '--harness', '--launcher', '--harness-session', '--port', '--api', '--api-port', '--host', '--preset', '--limit', '--session', '--depth', '--focus', '--keys', '--allow-stop', '--allow-resume', '--ttl-ms', '--wait-ms', '--adapter', '--thread', '--tmux', '--worktree', '--branch'])
|
|
54
54
|
function positionals(from: number): string[] {
|
|
55
55
|
const out: string[] = []
|
|
56
56
|
for (let i = from; i < process.argv.length; i++) {
|
|
@@ -873,6 +873,23 @@ if (cmd === 'serve') {
|
|
|
873
873
|
const closed = await c.clientClose(full)
|
|
874
874
|
if (!closed) { console.error(`spex session close: no such session ${full} (record remains; no close was committed)`); process.exit(1) }
|
|
875
875
|
console.log(`closed ${full}`)
|
|
876
|
+
} else if (sub === 'quarantine') {
|
|
877
|
+
rejectUnknownFlags('spex session quarantine', 4, ['adapter', 'thread', 'tmux', 'worktree', 'branch', 'restore', 'api', 'port'])
|
|
878
|
+
if (!id) { console.error('usage: spex session quarantine <ID> --adapter <harness> [--thread <native-id>] --tmux <session-id> --worktree <absent-path> --branch <absent-branch>') ; process.exit(2) }
|
|
879
|
+
if (has('restore')) {
|
|
880
|
+
// Quarantine addresses an unreadable row which selector resolution intentionally excludes. Both the
|
|
881
|
+
// move and its reverse therefore take the literal exact id, with the backend proving record state.
|
|
882
|
+
const restored = await c.clientRestoreQuarantine(id)
|
|
883
|
+
console.log(`restored quarantined record ${restored.id} from ${restored.bundle}`)
|
|
884
|
+
} else {
|
|
885
|
+
const adapter = flag('adapter'), tmux = flag('tmux'), worktree = flag('worktree'), branch = flag('branch')
|
|
886
|
+
if (!adapter || !tmux || !worktree || !branch) {
|
|
887
|
+
console.error('usage: spex session quarantine <ID> --adapter <harness> [--thread <native-id>] --tmux <session-id> --worktree <absent-path> --branch <absent-branch>')
|
|
888
|
+
process.exit(2)
|
|
889
|
+
}
|
|
890
|
+
const quarantined = await c.clientQuarantine(id, { adapter, thread: flag('thread') ?? null, tmux, worktree, branch })
|
|
891
|
+
console.log(`quarantined ${quarantined.id} -> ${quarantined.bundle}`)
|
|
892
|
+
}
|
|
876
893
|
} else if (sub === 'send') {
|
|
877
894
|
const full = await resolveSelectorOrExit(id)
|
|
878
895
|
if (has('keys')) {
|
package/spec-cli/src/client.ts
CHANGED
|
@@ -276,6 +276,27 @@ export async function clientClose(id: string): Promise<boolean> {
|
|
|
276
276
|
return !!(await r.json().catch(() => ({ ok: false })))?.ok
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
+
export async function clientQuarantine(
|
|
280
|
+
id: string,
|
|
281
|
+
witness: { adapter: string; thread: string | null; tmux: string; worktree: string; branch: string },
|
|
282
|
+
): Promise<{ id: string; bundle: string; sha256: string; observedAt: string }> {
|
|
283
|
+
await guarded('session quarantine')
|
|
284
|
+
const r = await apiFetch(`/api/sessions/${seg(id)}/quarantine`, post(witness))
|
|
285
|
+
if (!r.ok) throw new BackendError(`backend refused to quarantine ${id}: ${await r.text()}`, r.status)
|
|
286
|
+
const body = await r.json() as { ok?: boolean; id?: string; bundle?: string; sha256?: string; observedAt?: string }
|
|
287
|
+
if (!body.ok || !body.id || !body.bundle || !body.sha256 || !body.observedAt) throw new BackendError(`backend returned an invalid quarantine result for ${id}`, r.status)
|
|
288
|
+
return { id: body.id, bundle: body.bundle, sha256: body.sha256, observedAt: body.observedAt }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export async function clientRestoreQuarantine(id: string): Promise<{ id: string; bundle: string; sha256: string; observedAt: string }> {
|
|
292
|
+
await guarded('session quarantine')
|
|
293
|
+
const r = await apiFetch(`/api/sessions/${seg(id)}/quarantine/restore`, post({}))
|
|
294
|
+
if (!r.ok) throw new BackendError(`backend refused to restore ${id}: ${await r.text()}`, r.status)
|
|
295
|
+
const body = await r.json() as { ok?: boolean; id?: string; bundle?: string; sha256?: string; observedAt?: string }
|
|
296
|
+
if (!body.ok || !body.id || !body.bundle || !body.sha256 || !body.observedAt) throw new BackendError(`backend returned an invalid quarantine restore for ${id}`, r.status)
|
|
297
|
+
return { id: body.id, bundle: body.bundle, sha256: body.sha256, observedAt: body.observedAt }
|
|
298
|
+
}
|
|
299
|
+
|
|
279
300
|
// POST /api/sessions/:id/archive — cold-archive the session ([[archive]]). The legacy on=false spelling is a
|
|
280
301
|
// signpost to the same resume transition; it never performs a record-only unarchive.
|
|
281
302
|
export async function clientArchive(id: string, on = true): Promise<boolean> {
|