spexcode 0.6.6 → 0.6.8
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 +12 -7
- package/node_modules/@spexcode/session-application/dist/index.d.ts +17 -0
- package/node_modules/@spexcode/session-application/dist/index.js +35 -0
- package/node_modules/@spexcode/session-application/dist/migration.d.ts +51 -0
- package/node_modules/@spexcode/session-application/dist/migration.js +694 -0
- package/node_modules/@spexcode/session-application/dist/production.d.ts +109 -0
- package/node_modules/@spexcode/session-application/dist/production.js +438 -0
- package/node_modules/@spexcode/session-application/dist/schema.d.ts +2 -0
- package/node_modules/@spexcode/session-application/dist/schema.js +39 -0
- package/node_modules/@spexcode/session-application/package.json +29 -0
- package/node_modules/@spexcode/session-events/dist/errors.d.ts +6 -0
- package/node_modules/@spexcode/session-events/dist/errors.js +11 -0
- package/node_modules/@spexcode/session-events/dist/index.d.ts +46 -0
- package/node_modules/@spexcode/session-events/dist/index.js +245 -0
- package/node_modules/@spexcode/session-events/dist/schema.d.ts +3 -0
- package/node_modules/@spexcode/session-events/dist/schema.js +44 -0
- package/node_modules/@spexcode/session-events/package.json +24 -0
- package/node_modules/@spexcode/session-protocol/dist/canonical.d.ts +36 -0
- package/node_modules/@spexcode/session-protocol/dist/canonical.js +139 -0
- package/node_modules/@spexcode/session-protocol/dist/engine.d.ts +22 -0
- package/node_modules/@spexcode/session-protocol/dist/engine.js +478 -0
- package/node_modules/@spexcode/session-protocol/dist/errors.d.ts +8 -0
- package/node_modules/@spexcode/session-protocol/dist/errors.js +39 -0
- package/node_modules/@spexcode/session-protocol/dist/index.d.ts +60 -0
- package/node_modules/@spexcode/session-protocol/dist/index.js +4 -0
- package/node_modules/@spexcode/session-protocol/dist/schema.d.ts +36 -0
- package/node_modules/@spexcode/session-protocol/dist/schema.js +192 -0
- package/node_modules/@spexcode/{session-core → session-protocol}/package.json +4 -8
- package/node_modules/@spexcode/session-runtime/dist/errors.d.ts +6 -0
- package/node_modules/@spexcode/session-runtime/dist/errors.js +11 -0
- package/node_modules/@spexcode/session-runtime/dist/index.d.ts +33 -0
- package/node_modules/@spexcode/session-runtime/dist/index.js +193 -0
- package/node_modules/@spexcode/session-runtime/dist/schema.d.ts +2 -0
- package/node_modules/@spexcode/session-runtime/dist/schema.js +37 -0
- package/node_modules/@spexcode/session-runtime/package.json +24 -0
- package/node_modules/@spexcode/session-selflaunch/bin/spex-session.mjs +4 -0
- package/node_modules/@spexcode/session-selflaunch/dist/cli.d.ts +25 -0
- package/node_modules/@spexcode/session-selflaunch/dist/cli.js +156 -0
- package/node_modules/@spexcode/session-selflaunch/dist/index.d.ts +28 -0
- package/node_modules/@spexcode/session-selflaunch/dist/index.js +25 -0
- package/node_modules/@spexcode/session-selflaunch/dist/locality.d.ts +20 -0
- package/node_modules/@spexcode/session-selflaunch/dist/locality.js +83 -0
- package/node_modules/@spexcode/session-selflaunch/dist/path.d.ts +13 -0
- package/node_modules/@spexcode/session-selflaunch/dist/path.js +45 -0
- package/node_modules/@spexcode/session-selflaunch/package.json +35 -0
- package/node_modules/@spexcode/session-topology/dist/errors.d.ts +6 -0
- package/node_modules/@spexcode/session-topology/dist/errors.js +11 -0
- package/node_modules/@spexcode/session-topology/dist/index.d.ts +24 -0
- package/node_modules/@spexcode/session-topology/dist/index.js +173 -0
- package/node_modules/@spexcode/session-topology/dist/schema.d.ts +3 -0
- package/node_modules/@spexcode/session-topology/dist/schema.js +27 -0
- package/node_modules/@spexcode/session-topology/package.json +24 -0
- package/node_modules/@spexcode/spec-cli/bin/spex.mjs +56 -19
- package/node_modules/@spexcode/spec-cli/dist/cli.js +102 -59
- package/node_modules/@spexcode/spec-cli/dist/client.d.ts +1 -3
- package/node_modules/@spexcode/spec-cli/dist/client.js +49 -30
- package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.d.ts +11 -0
- package/node_modules/@spexcode/spec-cli/dist/codex-runtime-generations.js +46 -9
- package/node_modules/@spexcode/spec-cli/dist/delivery-lock.d.ts +2 -0
- package/node_modules/@spexcode/spec-cli/dist/delivery-lock.js +58 -0
- package/node_modules/@spexcode/spec-cli/dist/doctor.js +53 -11
- package/node_modules/@spexcode/spec-cli/dist/execution-trace.d.ts +1 -0
- package/node_modules/@spexcode/spec-cli/dist/execution-trace.js +2 -2
- package/node_modules/@spexcode/spec-cli/dist/gateway-hub.js +2 -1
- package/node_modules/@spexcode/spec-cli/dist/gateway.js +6 -3
- package/node_modules/@spexcode/spec-cli/dist/graphCache.js +32 -2
- package/node_modules/@spexcode/spec-cli/dist/graphSnapshot.js +57 -2
- package/node_modules/@spexcode/spec-cli/dist/graphStream.d.ts +2 -0
- package/node_modules/@spexcode/spec-cli/dist/graphStream.js +83 -3
- package/node_modules/@spexcode/spec-cli/dist/guide.js +20 -7
- package/node_modules/@spexcode/spec-cli/dist/harness-select.js +16 -3
- package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +15 -3
- package/node_modules/@spexcode/spec-cli/dist/harness.js +331 -50
- package/node_modules/@spexcode/spec-cli/dist/help.js +11 -8
- package/node_modules/@spexcode/spec-cli/dist/hook-prompts.js +8 -0
- package/node_modules/@spexcode/spec-cli/dist/host-resources.js +29 -8
- package/node_modules/@spexcode/spec-cli/dist/host.d.ts +7 -0
- package/node_modules/@spexcode/spec-cli/dist/host.js +93 -0
- package/node_modules/@spexcode/spec-cli/dist/index.js +324 -22
- package/node_modules/@spexcode/spec-cli/dist/init.js +1 -1
- package/node_modules/@spexcode/spec-cli/dist/lint.js +70 -35
- package/node_modules/@spexcode/spec-cli/dist/listen.d.ts +3 -2
- package/node_modules/@spexcode/spec-cli/dist/listen.js +14 -2
- package/node_modules/@spexcode/spec-cli/dist/machine-peer.js +1 -1
- package/node_modules/@spexcode/spec-cli/dist/materialize.d.ts +2 -2
- package/node_modules/@spexcode/spec-cli/dist/materialize.js +176 -35
- package/node_modules/@spexcode/spec-cli/dist/pty-bridge.js +14 -14
- package/node_modules/@spexcode/spec-cli/dist/reviews.js +12 -7
- package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.d.ts +11 -0
- package/node_modules/@spexcode/spec-cli/dist/runtime-ownership.js +79 -1
- package/node_modules/@spexcode/spec-cli/dist/session-application.d.ts +23 -0
- package/node_modules/@spexcode/spec-cli/dist/session-application.js +189 -0
- package/node_modules/@spexcode/spec-cli/dist/session-declarations.js +13 -1
- package/node_modules/@spexcode/spec-cli/dist/session-files.d.ts +6 -0
- package/node_modules/@spexcode/spec-cli/dist/session-files.js +13 -1
- package/node_modules/@spexcode/spec-cli/dist/session-follow.js +39 -22
- package/node_modules/@spexcode/{session-core/dist/record-lock.d.ts → spec-cli/dist/session-record-lock.d.ts} +0 -4
- package/node_modules/@spexcode/spec-cli/dist/session-record-lock.js +94 -0
- package/node_modules/@spexcode/spec-cli/dist/session-runtime-adapter.d.ts +44 -0
- package/node_modules/@spexcode/spec-cli/dist/session-runtime-adapter.js +37 -0
- package/node_modules/@spexcode/spec-cli/dist/session-timeline.d.ts +25 -2
- package/node_modules/@spexcode/spec-cli/dist/session-timeline.js +68 -11
- package/node_modules/@spexcode/spec-cli/dist/session-web.js +4 -4
- package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +108 -15
- package/node_modules/@spexcode/spec-cli/dist/sessions.js +1465 -744
- package/node_modules/@spexcode/spec-cli/dist/source-list.d.ts +13 -0
- package/node_modules/@spexcode/spec-cli/dist/source-list.js +99 -0
- package/node_modules/@spexcode/spec-cli/dist/source-read.d.ts +16 -0
- package/node_modules/@spexcode/spec-cli/dist/source-read.js +84 -0
- package/node_modules/@spexcode/spec-cli/dist/spec-attachments.d.ts +7 -0
- package/node_modules/@spexcode/spec-cli/dist/spec-attachments.js +89 -0
- package/node_modules/@spexcode/spec-cli/dist/spec-body-edit.d.ts +23 -0
- package/node_modules/@spexcode/spec-cli/dist/spec-body-edit.js +138 -0
- package/node_modules/@spexcode/spec-cli/dist/supervise.js +15 -6
- package/node_modules/@spexcode/spec-cli/dist/transcript-reader.d.ts +36 -0
- package/node_modules/@spexcode/spec-cli/dist/transcript-reader.js +251 -0
- package/node_modules/@spexcode/spec-cli/hooks/dispatch.sh +19 -31
- package/node_modules/@spexcode/spec-cli/hooks/harness.sh +6 -6
- package/node_modules/@spexcode/spec-cli/package.json +6 -6
- package/node_modules/@spexcode/spec-cli/templates/hooks/post-checkout +4 -2
- package/node_modules/@spexcode/spec-cli/templates/hooks/post-merge +2 -1
- package/node_modules/@spexcode/spec-cli/templates/hooks/pre-commit +5 -3
- package/node_modules/@spexcode/spec-cli/templates/hooks/reference-transaction +5 -3
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/commands/spec.md +2 -7
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/idle/idle.sh +4 -10
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/idle/spec.md +1 -1
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/mark-active/mark-active.sh +22 -24
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/mark-active/spec.md +10 -2
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-fail/fail.sh +8 -7
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-fail/spec.md +3 -1
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-listen/session-listen.sh +133 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/session-listen/spec.md +36 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/spec.md +2 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/stop-gate/spec.md +1 -1
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/core/stop-gate/stop-gate.sh +17 -20
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/skills/merge/spec.md +33 -0
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/skills/spec.md +2 -6
- package/node_modules/@spexcode/spec-cli/templates/spec/project/.plugins/spec.md +7 -0
- package/node_modules/@spexcode/spec-core/dist/anchors.d.ts +13 -2
- package/node_modules/@spexcode/spec-core/dist/anchors.js +311 -15
- package/node_modules/@spexcode/spec-core/dist/git.d.ts +4 -0
- package/node_modules/@spexcode/spec-core/dist/git.js +9 -9
- package/node_modules/@spexcode/spec-core/dist/layout.d.ts +12 -0
- package/node_modules/@spexcode/spec-core/dist/layout.js +4 -2
- package/node_modules/@spexcode/spec-core/dist/resilience.d.ts +1 -0
- package/node_modules/@spexcode/spec-core/dist/resilience.js +8 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.d.ts +1 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewFilters.js +7 -3
- package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.d.ts +1 -0
- package/node_modules/@spexcode/spec-core/dist/review/reviewQuery.js +4 -0
- package/node_modules/@spexcode/spec-core/dist/specs.d.ts +2 -0
- package/node_modules/@spexcode/spec-core/dist/specs.js +30 -0
- package/node_modules/@spexcode/spec-core/package.json +4 -1
- package/node_modules/@spexcode/spec-eval/dist/cli.js +1 -1
- package/node_modules/@spexcode/spec-eval/dist/evaltab.d.ts +1 -0
- package/node_modules/@spexcode/spec-eval/dist/evaltab.js +6 -1
- package/node_modules/@spexcode/spec-eval/dist/freshness.d.ts +1 -1
- package/node_modules/@spexcode/spec-eval/dist/freshness.js +12 -12
- package/node_modules/@spexcode/spec-eval/dist/host.d.ts +2 -1
- package/node_modules/@spexcode/spec-eval/dist/sessioneval.d.ts +2 -1
- package/node_modules/@spexcode/spec-eval/dist/sessioneval.js +20 -3
- package/node_modules/@spexcode/spec-eval/package.json +2 -2
- package/node_modules/@spexcode/spec-forge/package.json +2 -2
- package/node_modules/@vscode/tree-sitter-wasm/LICENSE +21 -0
- package/node_modules/@vscode/tree-sitter-wasm/README.md +36 -0
- package/node_modules/@vscode/tree-sitter-wasm/SECURITY.md +41 -0
- package/node_modules/@vscode/tree-sitter-wasm/cgmanifest.json +16 -0
- package/node_modules/@vscode/tree-sitter-wasm/package.json +42 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-c-sharp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-cpp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-go.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-java.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-javascript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-php.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-python.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ruby.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-rust.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-tsx.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js +4075 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter.d.ts +1027 -0
- package/package.json +9 -3
- package/node_modules/@spexcode/session-core/dist/delivery-queue.d.ts +0 -23
- package/node_modules/@spexcode/session-core/dist/delivery-queue.js +0 -195
- package/node_modules/@spexcode/session-core/dist/index.d.ts +0 -5
- package/node_modules/@spexcode/session-core/dist/index.js +0 -5
- package/node_modules/@spexcode/session-core/dist/internal.d.ts +0 -3
- package/node_modules/@spexcode/session-core/dist/internal.js +0 -3
- package/node_modules/@spexcode/session-core/dist/message.d.ts +0 -22
- package/node_modules/@spexcode/session-core/dist/message.js +0 -52
- package/node_modules/@spexcode/session-core/dist/record-lock.js +0 -152
- package/node_modules/@spexcode/session-core/dist/runtime-session.d.ts +0 -50
- package/node_modules/@spexcode/session-core/dist/runtime-session.js +0 -286
- package/node_modules/@spexcode/session-core/dist/session-cursors.d.ts +0 -14
- package/node_modules/@spexcode/session-core/dist/session-cursors.js +0 -82
- package/node_modules/@spexcode/session-core/dist/session-timeline.d.ts +0 -46
- package/node_modules/@spexcode/session-core/dist/session-timeline.js +0 -216
- package/node_modules/@spexcode/spec-cli/hooks/compat/mark-active-0.5.2-eef1.fixture +0 -53
- package/node_modules/@spexcode/spec-cli/hooks/compat/mark-active-sed-v0.fixture +0 -46
|
@@ -38,7 +38,7 @@ The successful receipt names what to read, monitor, and reply on. --ssh uses an
|
|
|
38
38
|
communication tunnel: its full id anchors the remote project, creation stays parentless and remote, and its
|
|
39
39
|
prompt carries a runnable reply path over that same tunnel.`, ['project-bound']],
|
|
40
40
|
ls: [['spex session ls [SEL…] [--children[=<PARENT-SEL>]] [--status a,b] [--all] [--json]', 'spex session ls --ssh <address> <FULL-SESSION-ID> [--children=<PARENT-SEL>] [--status a,b] [--json]'],
|
|
41
|
-
'One-shot table of this project\'s
|
|
41
|
+
'One-shot table of this project\'s session records, with each direct parent beside the row. --children scopes it to the caller\'s direct children; --children=<PARENT-SEL> names another parent without changing positional selector grammar. The heading summarizes the displayed scope by status. Closed records are hidden from the working projection; --all includes them, and naming one explicitly always shows it. A missing id is a loud record miss. --ssh uses an existing gateway-to-gateway communication tunnel; its full id anchors one remote project rather than filtering the table.', ['selector']],
|
|
42
42
|
resources: ['spex session resources [--json]', 'Read-only host/process ownership, budgets, shared refs, and findings.'],
|
|
43
43
|
files: [['spex session files add <path>', 'spex session files ls', 'spex session files retract <path>'],
|
|
44
44
|
'Publish, list, or withdraw YOUR session’s live file paths. Posting stores an absolute path beside the session record without copying bytes; the dashboard downloads it only when the human clicks.'],
|
|
@@ -72,16 +72,14 @@ provably cannot land.`, ['selector', 'project-bound']],
|
|
|
72
72
|
existing gateway-to-gateway communication tunnel and requires a full session id; live-pane capture stays local.`, ['selector']],
|
|
73
73
|
resume: ['spex session resume <SEL> [--force]', 'Relaunch ONLY if confirmed offline; --force is for a wedged session.', ['selector', 'project-bound']],
|
|
74
74
|
stop: ['spex session stop <SEL>', 'Soft stop: kill the exact agent and KEEP the worktree resumable.', ['selector', 'project-bound']],
|
|
75
|
-
|
|
76
|
-
unarchive: ['spex session unarchive <SEL>', 'Deprecated compatibility spelling: same behavior as resume, relaunching the same conversation.', ['selector']],
|
|
77
|
-
close: [['spex session close <SEL>', 'spex session close --ssh <address> <FULL-SESSION-ID>'], `Retire ANOTHER session — one you dispatched — deleting its worktree, branch and record.
|
|
75
|
+
close: [['spex session close <SEL>', 'spex session close --ssh <address> <FULL-SESSION-ID>'], `Close ANOTHER session — one you dispatched — after an exact cold stop. Dirty work is committed to refs/spex-archive/<id>; only the worktree is removed. The branch, record, transcript, and conversation remain available to resume.
|
|
78
76
|
<SEL> names that session; it is never \`.\` and never your own id. Closing yourself deletes the worktree
|
|
79
|
-
you are running in, mid-turn. Your own ending is a declaration: \`done --propose close\`. --ssh uses an existing
|
|
77
|
+
you are running in, mid-turn. A live turn is refused; stop it first. Your own ending is a declaration: \`done --propose close\`. --ssh uses an existing
|
|
80
78
|
gateway-to-gateway communication tunnel and requires a full session id.`, ['selector', 'project-bound']],
|
|
81
79
|
quarantine: ['spex session quarantine <ID> --adapter <harness> [--thread <native-id>] --tmux <id> --worktree <absent-path> --branch <absent-branch> [--restore]',
|
|
82
80
|
'Move only an unreadable record after the backend proves every named residue absent. --thread is an adapter-native conversation id, never the SpexCode session id; omit it for Claude. Quarantine and --restore both require the original exact id because corrupt rows are outside selectors.', ['project-bound']],
|
|
83
81
|
done: ['spex session done --propose merge|nothing|close [--note T]',
|
|
84
|
-
'`merge` declares review: committed work ready for human review
|
|
82
|
+
'`merge` declares review: committed work ready for human review and is the ONLY declaration that offers a clickable merge. `nothing` is an intended trap: it writes no state and sends the agent to the true merge, close, ask, or park destination. `close` declares close-pending only for settled work: discardable worktree and no outstanding human decision, follow-up, or inspection. The human closes it. This declaration is how a session ends itself; never run `session close` on your own id.'],
|
|
85
83
|
park: ['spex session park --note <what-you-await>',
|
|
86
84
|
'Declare parked only when a managed watch delivery or real background task will wake your own session. It self-resumes; waiting for a human is asking, not parked.'],
|
|
87
85
|
ask: ['spex session ask --note <what-you-await>',
|
|
@@ -92,7 +90,7 @@ LOCAL-only (fails loud on a remote backend); show --capture and send are non-int
|
|
|
92
90
|
}
|
|
93
91
|
const SESSION_HELP_GROUPS = [
|
|
94
92
|
{ title: 'Manager verbs (dispatch, monitor, land)', verbs: ['new', 'ls', 'resources', 'watch', 'wait', 'review', 'merge', 'reparent'] },
|
|
95
|
-
{ title: 'Control another session', verbs: ['send', 'interrupt', 'rename', 'show', 'resume', 'stop', '
|
|
93
|
+
{ title: 'Control another session', verbs: ['send', 'interrupt', 'rename', 'show', 'resume', 'stop', 'close', 'quarantine'] },
|
|
96
94
|
{ title: 'Worker verbs (declare YOUR OWN state — a claim the graph and your supervisor act on)', verbs: ['done', 'park', 'ask', 'files', 'web'] },
|
|
97
95
|
{ title: 'Human escape hatch', verbs: ['attach'] },
|
|
98
96
|
];
|
|
@@ -150,7 +148,11 @@ Scaffolds adoption in one shot: seeds a starter .spec tree (project root + .plug
|
|
|
150
148
|
spexcode.json, installs the git hooks, and materializes the harness artifacts (contract block +
|
|
151
149
|
shims). --harness is REQUIRED — the explicit choice of which harnesses materialize delivers into
|
|
152
150
|
(stamped as spexcode.json "harnesses"; only their launchers are seeded); a pre-existing "harnesses"
|
|
153
|
-
field satisfies it
|
|
151
|
+
field satisfies it; --harness none delivers into NO harness (spec tree + lint + git hooks only, nothing
|
|
152
|
+
written into any agent's config). Additive: it never replaces a file you own — where a harness discovers its
|
|
153
|
+
hooks in your own config (.claude/settings.json, …) only SpexCode's entries are merged in and out, and a
|
|
154
|
+
skill/agent name you already use is skipped and reported rather than overwritten.
|
|
155
|
+
--preset picks the .plugins plugin tier (cumulative).
|
|
154
156
|
Footprint is fixed: materialized artifacts are never tracked — hidden via the per-clone .git/info/exclude, with
|
|
155
157
|
a tracked/mixed CLAUDE.md/AGENTS.md covered by the clean/smudge filter (see spex guide footprint).`,
|
|
156
158
|
see: 'spex guide (the full setup workflow) · spex uninstall (the inverse) · spex spec lint (adoption TODO)',
|
|
@@ -473,6 +475,7 @@ Machine plumbing — called by generated hooks and launch scripts, never typed b
|
|
|
473
475
|
session-state <st> --session <id> a lifecycle hook authors the session's state
|
|
474
476
|
session-fail --session <id> the StopFailure hook marks the session errored
|
|
475
477
|
session-idle --session <id> the idle-prompt hook marks an active session idle
|
|
478
|
+
session-hook-state --session <id> hook-only canonical lifecycle read (tab-separated)
|
|
476
479
|
commit-gate the Stop gate's deterministic commit check (exit 0 = ready to declare done)
|
|
477
480
|
hook-prompt <name> render canonical model-facing text for a runtime hook
|
|
478
481
|
nudge <node> the post-merge hook prints the issue nudge for a merged node
|
|
@@ -58,6 +58,14 @@ const DEFINITIONS = Object.freeze([
|
|
|
58
58
|
content: NO_PROMPT('session-fail', 'It records a failed governed turn as error.'),
|
|
59
59
|
render: () => '',
|
|
60
60
|
},
|
|
61
|
+
{
|
|
62
|
+
name: 'session-listen',
|
|
63
|
+
title: 'session-listen',
|
|
64
|
+
description: 'Lifecycle delivery signal; runtime adopter messages are delivered at harness input boundaries.',
|
|
65
|
+
role: 'signal',
|
|
66
|
+
content: NO_PROMPT('session-listen', 'It delivers adopter-owned queued messages as runtime context when configured.'),
|
|
67
|
+
render: () => '',
|
|
68
|
+
},
|
|
61
69
|
{
|
|
62
70
|
name: 'spec-first',
|
|
63
71
|
title: 'spec-first',
|
|
@@ -4,11 +4,12 @@ import { randomUUID } from 'node:crypto';
|
|
|
4
4
|
import { mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { dirname, join } from 'node:path';
|
|
6
6
|
import { defaultHarness, HARNESSES, harnessById, harnessByIdOrNull, sessionIdentityEnvVars } from './harness.js';
|
|
7
|
-
import { listSessionIds, readConfig, readJsonConfig, readPublicRecordEntry,
|
|
7
|
+
import { listSessionIds, readConfig, readJsonConfig, readPublicRecordEntry, runtimeRoot } from '@spexcode/spec-core';
|
|
8
8
|
import { repoRoot } from '@spexcode/spec-core';
|
|
9
9
|
import { endpointRecordPath } from './host.js';
|
|
10
10
|
import { detachedRuntimeGenerationToken, parseProcStat, processStartToken, verifyDetachedRuntime } from '@spexcode/spec-core';
|
|
11
11
|
import { readBackendInstanceRecords } from './runtime-ownership.js';
|
|
12
|
+
import { configuredSessionApplicationIfCutover } from './session-application.js';
|
|
12
13
|
const DEFAULTS = {
|
|
13
14
|
sessionRssMiB: 1024,
|
|
14
15
|
backendRssMiB: 2048,
|
|
@@ -146,20 +147,40 @@ const descendants = (root, procs) => {
|
|
|
146
147
|
};
|
|
147
148
|
const publicRecordInventory = () => {
|
|
148
149
|
const entries = listSessionIds().map(readPublicRecordEntry);
|
|
150
|
+
const application = configuredSessionApplicationIfCutover();
|
|
149
151
|
const byId = new Map();
|
|
150
|
-
|
|
152
|
+
const projected = entries.map((entry) => {
|
|
153
|
+
if (entry.kind !== 'ok' || !application || !entry.raw.governed)
|
|
154
|
+
return entry;
|
|
155
|
+
const state = application.readState(entry.raw.session_id);
|
|
156
|
+
if (!state)
|
|
157
|
+
throw new ResourceConflict(`session ${entry.raw.session_id} has no canonical application state after JSON cutover`);
|
|
158
|
+
return {
|
|
159
|
+
...entry,
|
|
160
|
+
raw: {
|
|
161
|
+
...entry.raw,
|
|
162
|
+
status: state.status,
|
|
163
|
+
proposal: state.proposal,
|
|
164
|
+
note: state.note,
|
|
165
|
+
parent: state.parentSessionId,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
for (const entry of projected) {
|
|
151
170
|
if (entry.kind === 'ok')
|
|
152
171
|
byId.set(entry.raw.session_id, entry);
|
|
153
172
|
else if (entry.kind === 'corrupt')
|
|
154
173
|
byId.set(entry.sessionId, entry);
|
|
155
174
|
}
|
|
156
175
|
return {
|
|
157
|
-
entries,
|
|
158
|
-
records:
|
|
176
|
+
entries: projected,
|
|
177
|
+
records: projected.flatMap((entry) => entry.kind === 'ok' ? [entry.raw] : []),
|
|
159
178
|
byId,
|
|
160
179
|
};
|
|
161
180
|
};
|
|
162
|
-
|
|
181
|
+
// Resource ownership must use the same lifecycle projection as the board. The raw reader remains for
|
|
182
|
+
// ungoverned/runtime identity discovery, but governed rows come from the canonical inventory above.
|
|
183
|
+
const rawRecords = () => publicRecordInventory().records;
|
|
163
184
|
const runtimePid = (file) => {
|
|
164
185
|
try {
|
|
165
186
|
const pid = Number(readFileSync(file, 'utf8').trim());
|
|
@@ -374,9 +395,9 @@ const ownerTotals = (processes) => ({
|
|
|
374
395
|
cpuPercent: Math.round(processes.reduce((n, p) => n + p.cpuPercent, 0) * 10) / 10,
|
|
375
396
|
});
|
|
376
397
|
const terminal = (rec) => !!rec && rec.status === 'awaiting' && (rec.proposal === 'nothing' || rec.proposal === 'close');
|
|
377
|
-
const probeRuntime = async (descriptor) => {
|
|
398
|
+
const probeRuntime = async (descriptor, referenceIds) => {
|
|
378
399
|
try {
|
|
379
|
-
return await descriptor.probe();
|
|
400
|
+
return await descriptor.probe(referenceIds);
|
|
380
401
|
}
|
|
381
402
|
catch (error) {
|
|
382
403
|
return { healthy: false, references: [], error: error.message };
|
|
@@ -473,7 +494,7 @@ const sessionStopBlocker = async (id, harnessId, recs = rawRecords(), knownProbe
|
|
|
473
494
|
}
|
|
474
495
|
return null;
|
|
475
496
|
};
|
|
476
|
-
const probeShared = async (shared) => new Map(await Promise.all([...shared].map(async ([key, entry]) => [key, await probeRuntime(entry.descriptor)])));
|
|
497
|
+
const probeShared = async (shared) => new Map(await Promise.all([...shared].map(async ([key, entry]) => [key, await probeRuntime(entry.descriptor, entry.recs.map((rec) => rec.harness_session_id).filter((id) => !!id))])));
|
|
477
498
|
const sharedFindings = (references, probe) => {
|
|
478
499
|
const findings = [];
|
|
479
500
|
if (!probe.healthy)
|
|
@@ -36,6 +36,13 @@ export type ProjectDirectoryListing = {
|
|
|
36
36
|
};
|
|
37
37
|
export declare function browseProjectDirectories(dir?: string): ProjectDirectoryListing;
|
|
38
38
|
export declare function addKnownProject(dir: string): string;
|
|
39
|
+
export type RemoveProjectResult = {
|
|
40
|
+
root: string;
|
|
41
|
+
projectId: string;
|
|
42
|
+
sessions: number;
|
|
43
|
+
runtimeRecordRemoved: boolean;
|
|
44
|
+
};
|
|
45
|
+
export declare function removeKnownProject(root: string, confirmation: string): RemoveProjectResult;
|
|
39
46
|
export type ProjectEntry = {
|
|
40
47
|
projectId: string;
|
|
41
48
|
root: string;
|
|
@@ -13,6 +13,7 @@ import { MachinePeerGateway } from './machine-peer.js';
|
|
|
13
13
|
import { DEFAULT_PROJECT_ICON, requireIdentityChoice } from '@spexcode/spec-core/identity';
|
|
14
14
|
import { resolveProjectIdentity, writeGatewayIcon, } from '@spexcode/spec-core';
|
|
15
15
|
import { cliEntrypointArgs } from './tsx-bin.js';
|
|
16
|
+
import { clearProjectPassword } from './gateway-auth.js';
|
|
16
17
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
17
18
|
export const endpointRecordPath = (root) => join(spexcodeHome(), 'projects', encodeProject(root), 'backend.json');
|
|
18
19
|
// atomic publish: tmp + rename, so a reader never sees a torn record (the old write-in-place could be
|
|
@@ -174,6 +175,70 @@ function catalogAdd(root) {
|
|
|
174
175
|
return;
|
|
175
176
|
writeCatalog([...entries, { root, addedAt: new Date().toISOString() }]);
|
|
176
177
|
}
|
|
178
|
+
function activeProjectSessions(root) {
|
|
179
|
+
const dir = join(spexcodeHome(), 'projects', encodeProject(root), 'sessions');
|
|
180
|
+
let entries;
|
|
181
|
+
try {
|
|
182
|
+
entries = readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
let active = 0;
|
|
188
|
+
for (const id of entries) {
|
|
189
|
+
try {
|
|
190
|
+
const record = JSON.parse(readFileSync(join(dir, id, 'runtime.json'), 'utf8'));
|
|
191
|
+
if (record?.archived !== true && record?.stopped !== true && record?.closedAt == null)
|
|
192
|
+
active++;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// An unreadable record is not safe to classify as inactive. It stays a loud blocker for removal.
|
|
196
|
+
active++;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return active;
|
|
200
|
+
}
|
|
201
|
+
export function removeKnownProject(root, confirmation) {
|
|
202
|
+
const entries = readCatalog();
|
|
203
|
+
const entry = entries.find((e) => e.root === root);
|
|
204
|
+
const projectId = encodeProject(root);
|
|
205
|
+
if (!entry)
|
|
206
|
+
throw Object.assign(new Error(`project '${projectId}' is not in the catalog`), { status: 404 });
|
|
207
|
+
const sessions = activeProjectSessions(root);
|
|
208
|
+
if (sessions)
|
|
209
|
+
throw Object.assign(new Error(`project has ${sessions} active session record(s); stop or close them before removing the registration`), { status: 409 });
|
|
210
|
+
const snapshotEntry = snapshot.find((p) => p.root === root);
|
|
211
|
+
if (snapshotEntry?.online)
|
|
212
|
+
throw Object.assign(new Error('project backend is online; stop it before removing the registration'), { status: 409 });
|
|
213
|
+
const expected = `REMOVE ${snapshotEntry?.identity.title || basename(root)}`;
|
|
214
|
+
if (confirmation !== expected)
|
|
215
|
+
throw Object.assign(new Error(`confirmation must exactly equal '${expected}'`), { status: 400 });
|
|
216
|
+
let runtimeRecordRemoved = false;
|
|
217
|
+
const recordFile = endpointRecordPath(root);
|
|
218
|
+
const record = readEndpointRecord(recordFile);
|
|
219
|
+
if (record) {
|
|
220
|
+
let alive = false;
|
|
221
|
+
try {
|
|
222
|
+
process.kill(record.pid, 0);
|
|
223
|
+
alive = true;
|
|
224
|
+
}
|
|
225
|
+
catch { /* no process at that pid */ }
|
|
226
|
+
if (alive) {
|
|
227
|
+
throw Object.assign(new Error('backend runtime could not be proven stopped; registration was preserved'), { status: 409 });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
writeCatalog(entries.filter((e) => e.root !== root));
|
|
231
|
+
clearProjectPassword(projectId);
|
|
232
|
+
if (record) {
|
|
233
|
+
try {
|
|
234
|
+
rmSync(recordFile);
|
|
235
|
+
runtimeRecordRemoved = true;
|
|
236
|
+
}
|
|
237
|
+
catch { /* already gone */ }
|
|
238
|
+
}
|
|
239
|
+
snapshot = snapshot.filter((p) => p.root !== root);
|
|
240
|
+
return { root, projectId, sessions, runtimeRecordRemoved };
|
|
241
|
+
}
|
|
177
242
|
async function fetchInstance(url) {
|
|
178
243
|
const ctrl = new AbortController();
|
|
179
244
|
const t = setTimeout(() => ctrl.abort(), 900);
|
|
@@ -515,6 +580,34 @@ export function startHostDashboard(opts) {
|
|
|
515
580
|
}
|
|
516
581
|
return true;
|
|
517
582
|
}
|
|
583
|
+
const remove = path.match(/^\/projects\/([^/]+)$/);
|
|
584
|
+
if (remove && req.method === 'DELETE') {
|
|
585
|
+
const projectId = decodeURIComponent(remove[1]);
|
|
586
|
+
if (!projectId) {
|
|
587
|
+
json(res, 404, { error: 'unknown project' });
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
let body = {};
|
|
591
|
+
try {
|
|
592
|
+
body = JSON.parse(await readBody(req) || '{}');
|
|
593
|
+
}
|
|
594
|
+
catch { /* validation below is the answer */ }
|
|
595
|
+
try {
|
|
596
|
+
const list = await reconcileNow();
|
|
597
|
+
const entry = list.find((p) => p.projectId === projectId);
|
|
598
|
+
if (!entry) {
|
|
599
|
+
json(res, 404, { error: `unknown project '${projectId}'` });
|
|
600
|
+
return true;
|
|
601
|
+
}
|
|
602
|
+
const removed = removeKnownProject(entry.root, typeof body?.confirmation === 'string' ? body.confirmation : '');
|
|
603
|
+
json(res, 200, { ok: true, ...removed });
|
|
604
|
+
}
|
|
605
|
+
catch (e) {
|
|
606
|
+
const error = e;
|
|
607
|
+
json(res, error.status ?? 400, { error: error.message });
|
|
608
|
+
}
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
518
611
|
if (path === '/projects/icon' && req.method === 'PUT') {
|
|
519
612
|
let body;
|
|
520
613
|
try {
|