spexcode 0.6.7 → 0.7.0-next.0
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 +31 -0
- package/node_modules/@spexcode/session-selflaunch/dist/locality.js +135 -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 +175 -21
- package/node_modules/@spexcode/spec-cli/dist/cli.js +121 -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/file-write.js +14 -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 +29 -18
- package/node_modules/@spexcode/spec-cli/dist/harness-select.js +16 -3
- package/node_modules/@spexcode/spec-cli/dist/harness.d.ts +24 -6
- package/node_modules/@spexcode/spec-cli/dist/harness.js +510 -72
- 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 +98 -1
- package/node_modules/@spexcode/spec-cli/dist/index.js +294 -36
- 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.d.ts +2 -1
- package/node_modules/@spexcode/spec-cli/dist/machine-peer.js +46 -15
- 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/opencode.js +10 -2
- package/node_modules/@spexcode/spec-cli/dist/pi-harness.js +18 -5
- package/node_modules/@spexcode/spec-cli/dist/pi-headless.d.ts +2 -0
- package/node_modules/@spexcode/spec-cli/dist/pi-headless.js +27 -0
- 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-transcript.d.ts +57 -0
- package/node_modules/@spexcode/spec-cli/dist/session-transcript.js +137 -0
- package/node_modules/@spexcode/spec-cli/dist/session-web.js +4 -4
- package/node_modules/@spexcode/spec-cli/dist/sessions.d.ts +112 -15
- package/node_modules/@spexcode/spec-cli/dist/sessions.js +1553 -764
- package/node_modules/@spexcode/spec-cli/dist/shim-runtime.js +14 -0
- 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/hooks/dispatch.sh +19 -31
- package/node_modules/@spexcode/spec-cli/hooks/harness.sh +6 -6
- package/node_modules/@spexcode/spec-cli/package.json +8 -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 -1
- 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-core/templates/spexcode.json +36 -13
- 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/@spexcode/transcript/dist/frames.d.ts +44 -0
- package/node_modules/@spexcode/transcript/dist/frames.js +85 -0
- package/node_modules/@spexcode/transcript/dist/index.d.ts +5 -0
- package/node_modules/@spexcode/transcript/dist/index.js +5 -0
- package/node_modules/@spexcode/transcript/dist/live.d.ts +16 -0
- package/node_modules/@spexcode/transcript/dist/live.js +65 -0
- package/node_modules/@spexcode/transcript/dist/parsers.d.ts +47 -0
- package/node_modules/@spexcode/transcript/dist/parsers.js +285 -0
- package/node_modules/@spexcode/transcript/dist/readers.d.ts +10 -0
- package/node_modules/@spexcode/transcript/dist/readers.js +296 -0
- package/node_modules/@spexcode/transcript/dist/turns.d.ts +42 -0
- package/node_modules/@spexcode/transcript/dist/turns.js +11 -0
- package/node_modules/@spexcode/transcript/package.json +30 -0
- 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/node_modules/smol-toml/LICENSE +24 -0
- package/node_modules/smol-toml/README.md +418 -0
- package/node_modules/smol-toml/dist/date.d.ts +41 -0
- package/node_modules/smol-toml/dist/date.js +127 -0
- package/node_modules/smol-toml/dist/error.d.ts +38 -0
- package/node_modules/smol-toml/dist/error.js +63 -0
- package/node_modules/smol-toml/dist/extract.js +69 -0
- package/node_modules/smol-toml/dist/index.cjs +734 -0
- package/node_modules/smol-toml/dist/index.d.ts +43 -0
- package/node_modules/smol-toml/dist/index.js +33 -0
- package/node_modules/smol-toml/dist/parse.d.ts +36 -0
- package/node_modules/smol-toml/dist/parse.js +149 -0
- package/node_modules/smol-toml/dist/primitive.js +238 -0
- package/node_modules/smol-toml/dist/stringify.d.ts +31 -0
- package/node_modules/smol-toml/dist/stringify.js +181 -0
- package/node_modules/smol-toml/dist/struct.js +179 -0
- package/node_modules/smol-toml/dist/util.d.ts +38 -0
- package/node_modules/smol-toml/dist/util.js +89 -0
- package/node_modules/smol-toml/package.json +68 -0
- package/package.json +9 -3
- package/node_modules/@spexcode/session-core/dist/delivery-queue.d.ts +0 -24
- package/node_modules/@spexcode/session-core/dist/delivery-queue.js +0 -206
- 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 -53
- package/node_modules/@spexcode/session-core/dist/record-lock.js +0 -152
- package/node_modules/@spexcode/session-core/dist/runtime-session.d.ts +0 -62
- package/node_modules/@spexcode/session-core/dist/runtime-session.js +0 -326
- 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 -47
- package/node_modules/@spexcode/session-core/dist/session-timeline.js +0 -216
- package/node_modules/@spexcode/spec-cli/dist/execution-trace.d.ts +0 -26
- package/node_modules/@spexcode/spec-cli/dist/execution-trace.js +0 -475
- package/node_modules/@spexcode/spec-cli/dist/session-execution.d.ts +0 -10
- package/node_modules/@spexcode/spec-cli/dist/session-execution.js +0 -70
- 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
|
@@ -14,7 +14,6 @@ export type Config = {
|
|
|
14
14
|
apiUrl?: string;
|
|
15
15
|
title?: string;
|
|
16
16
|
icon?: string;
|
|
17
|
-
showHeadlessLaunchers?: boolean;
|
|
18
17
|
};
|
|
19
18
|
uploads?: {
|
|
20
19
|
maxBytes?: number;
|
|
@@ -111,8 +110,10 @@ export type RawRecord = {
|
|
|
111
110
|
createdAt: number;
|
|
112
111
|
harness?: string;
|
|
113
112
|
harness_session_id?: string;
|
|
113
|
+
runtime_start_token?: string;
|
|
114
114
|
stopped?: boolean;
|
|
115
115
|
archived?: boolean;
|
|
116
|
+
closed_at?: string;
|
|
116
117
|
cold_proof?: string;
|
|
117
118
|
adapter_recovery?: string;
|
|
118
119
|
launcher?: string;
|
|
@@ -125,6 +126,15 @@ export type RawRecord = {
|
|
|
125
126
|
runtime_revision?: string;
|
|
126
127
|
runtime_metadata?: Record<string, string>;
|
|
127
128
|
base?: string;
|
|
129
|
+
diff_comments?: Array<{
|
|
130
|
+
id: string;
|
|
131
|
+
file_path: string;
|
|
132
|
+
line_start: number;
|
|
133
|
+
line_end: number;
|
|
134
|
+
body: string;
|
|
135
|
+
diff_identity: string;
|
|
136
|
+
sent_at: string | null;
|
|
137
|
+
}>;
|
|
128
138
|
launch_readiness_pending?: '' | RawLaunchReadinessPending;
|
|
129
139
|
};
|
|
130
140
|
export declare const SESSION_LIFECYCLES: readonly ["active", "idle", "awaiting", "parked", "error", "asking", "queued"];
|
|
@@ -139,6 +149,7 @@ export type RawLaunchReadinessOriginal = {
|
|
|
139
149
|
note: string | null;
|
|
140
150
|
stopped: boolean;
|
|
141
151
|
archived: boolean;
|
|
152
|
+
closed_at?: string | null;
|
|
142
153
|
cold_proof: string | null;
|
|
143
154
|
adapter_recovery: string | null;
|
|
144
155
|
};
|
|
@@ -136,7 +136,7 @@ export function mainRoot(proj) {
|
|
|
136
136
|
}
|
|
137
137
|
// @@@ global per-session store - Fork A: NO SpexCode files live in the worktree any more, so the worktree's
|
|
138
138
|
// spec/code tree is pristine (zero per-session pollution). Every per-session runtime artifact — the
|
|
139
|
-
//
|
|
139
|
+
// runtime envelope (runtime.json) AND the launcher products (prompt, launch, launch.sh) AND the recorded comms AND
|
|
140
140
|
// the spec-discipline sentinels — lives in a per-USER GLOBAL store, keyed by the harness `session_id` so two
|
|
141
141
|
// agents in one folder never clobber, and grouped PER PROJECT (mirroring Claude's ~/.claude/projects/<enc>/)
|
|
142
142
|
// so the board enumerates ONE directory. This is the single seam that knows where the store sits; sessions.ts
|
|
@@ -169,7 +169,7 @@ export function treeSlotDir(wt) {
|
|
|
169
169
|
// all keyed by session_id under <home>/projects/<enc>/sessions/.
|
|
170
170
|
export function sessionsRoot() { return join(runtimeRoot(), 'sessions'); }
|
|
171
171
|
export function sessionStoreDir(id) { return join(sessionsRoot(), id); }
|
|
172
|
-
export function sessionRecordPath(id) { return join(sessionStoreDir(id), '
|
|
172
|
+
export function sessionRecordPath(id) { return join(sessionStoreDir(id), 'runtime.json'); }
|
|
173
173
|
export function sessionArtifactPath(id, name) { return join(sessionStoreDir(id), name); }
|
|
174
174
|
export const SESSION_LIFECYCLES = ['active', 'idle', 'awaiting', 'parked', 'error', 'asking', 'queued'];
|
|
175
175
|
export const SESSION_PROPOSALS = ['merge', 'nothing', 'close'];
|
|
@@ -190,6 +190,7 @@ export function rawLaunchReadinessOriginal(raw) {
|
|
|
190
190
|
|| !(original.proposal === null || original.proposal === '' || isSessionProposal(original.proposal))
|
|
191
191
|
|| !(typeof original.note === 'string' || original.note === null)
|
|
192
192
|
|| typeof original.stopped !== 'boolean' || typeof original.archived !== 'boolean'
|
|
193
|
+
|| !(typeof original.closed_at === 'string' || original.closed_at === null || original.closed_at === undefined)
|
|
193
194
|
|| !(typeof original.cold_proof === 'string' || original.cold_proof === null)
|
|
194
195
|
|| !(typeof original.adapter_recovery === 'string' || original.adapter_recovery === null)) {
|
|
195
196
|
throw new Error(`session '${raw.session_id}' has an invalid launch_readiness_pending fence`);
|
|
@@ -281,6 +282,7 @@ export function projectPublicRecordEntry(id, entry) {
|
|
|
281
282
|
note: original.note || null,
|
|
282
283
|
stopped: original.stopped,
|
|
283
284
|
archived: original.archived,
|
|
285
|
+
closed_at: original.closed_at ?? undefined,
|
|
284
286
|
cold_proof: original.cold_proof ?? undefined,
|
|
285
287
|
adapter_recovery: original.adapter_recovery ?? undefined,
|
|
286
288
|
launch_readiness_pending: '',
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
2
3
|
function describe(e) {
|
|
3
4
|
return e instanceof Error ? e.message : String(e);
|
|
4
5
|
}
|
|
6
|
+
// Delayed close deletion lives below this directory and is never a live worktree input.
|
|
7
|
+
export function isTrashWorktreePath(path) {
|
|
8
|
+
const normalized = resolve(path);
|
|
9
|
+
const parts = normalized.split(/[\\/]+/);
|
|
10
|
+
const worktrees = parts.lastIndexOf('.worktrees');
|
|
11
|
+
return worktrees >= 0 && parts[worktrees + 1] === '.trash';
|
|
12
|
+
}
|
|
5
13
|
// run a per-worktree DETAIL read; on a throw, branch on whether the worktree DIRECTORY still exists.
|
|
6
14
|
// dir gone → the worktree was genuinely removed mid-read → return null so the caller omits it.
|
|
7
15
|
// dir present → a flaky detail read (ENOENT race on a sibling file, or a git index/ref lock under a
|
|
@@ -11,6 +11,7 @@ export const EVAL_FILTER_KIND = Object.freeze({
|
|
|
11
11
|
RESULT: 'result',
|
|
12
12
|
BLIND: 'blind',
|
|
13
13
|
UNMEASURED: 'unmeasured',
|
|
14
|
+
DEFERRED: 'deferred',
|
|
14
15
|
DANGLING: 'dangling',
|
|
15
16
|
});
|
|
16
17
|
export const evidenceList = (reading) => reading?.evidence?.length ? reading.evidence
|
|
@@ -146,9 +147,11 @@ export function issueFilterModel(items, raw = {}, context = {}) {
|
|
|
146
147
|
const evalIsResult = (entry) => entry.filterKind === EVAL_FILTER_KIND.RESULT;
|
|
147
148
|
const verdictOf = (entry) => evalIsResult(entry)
|
|
148
149
|
? (entry.verdict?.status || 'unscored')
|
|
149
|
-
: entry.filterKind === EVAL_FILTER_KIND.
|
|
150
|
-
? '
|
|
151
|
-
:
|
|
150
|
+
: entry.filterKind === EVAL_FILTER_KIND.DEFERRED
|
|
151
|
+
? 'deferred'
|
|
152
|
+
: entry.filterKind === EVAL_FILTER_KIND.BLIND || entry.filterKind === EVAL_FILTER_KIND.UNMEASURED
|
|
153
|
+
? 'unmeasured'
|
|
154
|
+
: 'unscored';
|
|
152
155
|
const reviewStateOf = (entry) => (evalIsResult(entry) && entry.fresh && entry.humanOk ? 'reviewed' : 'current');
|
|
153
156
|
// the ONE freshness axis of the Eval adapter — the facet's option values and the verdict sections' split
|
|
154
157
|
// read it, so a chip and its Freshness menu can never disagree about what "stale" counts.
|
|
@@ -194,6 +197,7 @@ const EVAL_CONFIG = {
|
|
|
194
197
|
{ value: 'fail', label: 'reviewList.verdict.fail', split: true },
|
|
195
198
|
{ value: 'pass', label: 'reviewList.verdict.pass', split: true },
|
|
196
199
|
{ value: 'unmeasured', label: 'reviewList.verdict.unmeasured' },
|
|
200
|
+
{ value: 'deferred', label: 'reviewList.verdict.deferred' },
|
|
197
201
|
],
|
|
198
202
|
},
|
|
199
203
|
facets: [
|
|
@@ -31,6 +31,7 @@ export const ISSUE_QUERY_DEFAULT: "is:issue state:open";
|
|
|
31
31
|
export const EVAL_QUERY_DEFAULT: "is:eval";
|
|
32
32
|
export function scopedEvalQuery(sessionId: any): any;
|
|
33
33
|
export function nodeEvalQuery(nodeId: any): any;
|
|
34
|
+
export function nodeIssueQuery(nodeId: any): any;
|
|
34
35
|
export function quoteValue(v: any): string;
|
|
35
36
|
export function tokenize(text: any): ({
|
|
36
37
|
ws: boolean;
|
|
@@ -8,6 +8,10 @@ export const EVAL_QUERY_DEFAULT = 'is:eval';
|
|
|
8
8
|
export const scopedEvalQuery = (sessionId) => setToken(EVAL_QUERY_DEFAULT, 'scope', sessionId);
|
|
9
9
|
// the aggregate score/count doors' address ([[eval-score-badge]]): the default view, node-filtered.
|
|
10
10
|
export const nodeEvalQuery = (nodeId) => setToken(EVAL_QUERY_DEFAULT, 'node', nodeId);
|
|
11
|
+
// a node's OPEN issues ([[context-dock]]): the issue list's default view, node-filtered. Same shape and
|
|
12
|
+
// same reason as the eval twin — a surface that wants "this node's issues" asks for a text, never for a
|
|
13
|
+
// second filter path, so the panel and the list it links to are literally the same query.
|
|
14
|
+
export const nodeIssueQuery = (nodeId) => setToken(ISSUE_QUERY_DEFAULT, 'node', nodeId);
|
|
11
15
|
const KEY_RE = /^([A-Za-z][A-Za-z0-9-]*):(.*)$/s;
|
|
12
16
|
const unquote = (v) => (v.length >= 2 && v.startsWith('"') && v.endsWith('"') ? v.slice(1, -1) : v);
|
|
13
17
|
export const quoteValue = (v) => (/\s/.test(String(v)) ? `"${v}"` : String(v));
|
|
@@ -9,6 +9,7 @@ export type SpecParts = {
|
|
|
9
9
|
expandedSpec: string;
|
|
10
10
|
};
|
|
11
11
|
declare function parseParts(body: string): SpecParts | null;
|
|
12
|
+
export declare function bodyMentions(body: string): string[];
|
|
12
13
|
export type DerivedStatus = 'pending' | 'active' | 'merged' | 'drift';
|
|
13
14
|
export declare function deriveStatus(d: {
|
|
14
15
|
version: number;
|
|
@@ -43,6 +44,7 @@ export declare function specContent(id: string): {
|
|
|
43
44
|
body: string;
|
|
44
45
|
parts: ReturnType<typeof parseParts>;
|
|
45
46
|
} | null;
|
|
47
|
+
export declare function specDir(id: string): string | null;
|
|
46
48
|
export type LoadSpecsOptions = {
|
|
47
49
|
tip?: string;
|
|
48
50
|
history?: HistoryIndex | null;
|
|
@@ -68,6 +68,29 @@ function parseParts(body) {
|
|
|
68
68
|
const t = (a) => a.join('\n').trim();
|
|
69
69
|
return { rawSource: t(acc.rawSource), expandedSpec: t(acc.expandedSpec) };
|
|
70
70
|
}
|
|
71
|
+
// the `[[id]]` reference grammar as a spec BODY writes it. Its consumer is the lint rule that rejects a
|
|
72
|
+
// dangling reference — the one place a `[[name]]` has to be judged against the node universe. It is a
|
|
73
|
+
// parser and not a projection: the loader once shipped the surviving ids as a `mentions` edge on every
|
|
74
|
+
// node, and that edge is gone, because a prose mention is a fact about the GRAPH and never was a fact
|
|
75
|
+
// about the node the reader has open ([[context-dock]]). Prose only: a fenced block or an inline
|
|
76
|
+
// `code span` is sample text (`[[node]]`, `[[<id>]]` placeholders live there), not a reference. Distinct,
|
|
77
|
+
// in first-appearance order; whether a name resolves to a real node is the caller's judgement.
|
|
78
|
+
const MENTION_RE = /\[\[(\.?[\p{L}\p{N}_-]+)\]\]/gu;
|
|
79
|
+
export function bodyMentions(body) {
|
|
80
|
+
const out = new Set();
|
|
81
|
+
let inFence = false;
|
|
82
|
+
for (const rawLine of body.split('\n')) {
|
|
83
|
+
if (/^\s*```/.test(rawLine)) {
|
|
84
|
+
inFence = !inFence;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (inFence)
|
|
88
|
+
continue;
|
|
89
|
+
for (const m of rawLine.replace(/`[^`]*`/g, '').matchAll(MENTION_RE))
|
|
90
|
+
out.add(m[1]);
|
|
91
|
+
}
|
|
92
|
+
return [...out];
|
|
93
|
+
}
|
|
71
94
|
export function deriveStatus(d) {
|
|
72
95
|
if (d.fmStatus === 'pending' && !d.hasCode && d.drift === 0)
|
|
73
96
|
return 'pending';
|
|
@@ -228,6 +251,13 @@ export function specContent(id) {
|
|
|
228
251
|
const r = raws().find((x) => x.id === id);
|
|
229
252
|
return r ? { body: r.body.trim(), parts: parseParts(r.body) } : null;
|
|
230
253
|
}
|
|
254
|
+
// Where a node LIVES, repo-relative — its own folder, not its spec.md. A node's folder is the unit (the
|
|
255
|
+
// same rule the plugin instances are built on), so anything that wants to see what a node carries besides
|
|
256
|
+
// its body asks the spec tree's own reader rather than re-deriving a path from an id.
|
|
257
|
+
export function specDir(id) {
|
|
258
|
+
const r = raws().find((x) => x.id === id);
|
|
259
|
+
return r ? r.relPath.replace(/\/spec\.md$/, '') : null;
|
|
260
|
+
}
|
|
231
261
|
export async function loadSpecs(root = ROOT, options = {}) {
|
|
232
262
|
// The default pair shares one immutable-event snapshot; explicit sides let callers skip or supply either
|
|
233
263
|
// projection. Every node below is then a pure in-memory lookup.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spexcode/spec-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0-next.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SpexCode's dependency-minimal spec graph core.",
|
|
6
6
|
"files": [
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
"engines": {
|
|
18
18
|
"node": ">=22"
|
|
19
19
|
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@vscode/tree-sitter-wasm": "0.3.1"
|
|
22
|
+
},
|
|
20
23
|
"publishConfig": {
|
|
21
24
|
"access": "public"
|
|
22
25
|
},
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"lint": {
|
|
3
|
-
"governedRoots": [
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"showHeadlessLaunchers": false
|
|
3
|
+
"governedRoots": [
|
|
4
|
+
"."
|
|
5
|
+
]
|
|
7
6
|
},
|
|
8
7
|
"uploads": {
|
|
9
8
|
"maxBytes": 2147483648,
|
|
@@ -19,15 +18,39 @@
|
|
|
19
18
|
},
|
|
20
19
|
"sessions": {
|
|
21
20
|
"launchers": {
|
|
22
|
-
"claude": {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
"claude-headless": {
|
|
22
|
+
"harness": "claude-headless",
|
|
23
|
+
"cmd": "claude"
|
|
24
|
+
},
|
|
25
|
+
"claude": {
|
|
26
|
+
"harness": "claude",
|
|
27
|
+
"cmd": "claude"
|
|
28
|
+
},
|
|
29
|
+
"codex-headless": {
|
|
30
|
+
"harness": "codex-headless",
|
|
31
|
+
"cmd": "codex --yolo"
|
|
32
|
+
},
|
|
33
|
+
"codex": {
|
|
34
|
+
"harness": "codex",
|
|
35
|
+
"cmd": "codex"
|
|
36
|
+
},
|
|
37
|
+
"opencode-headless": {
|
|
38
|
+
"harness": "opencode-headless",
|
|
39
|
+
"cmd": "opencode --auto"
|
|
40
|
+
},
|
|
41
|
+
"opencode": {
|
|
42
|
+
"harness": "opencode",
|
|
43
|
+
"cmd": "opencode"
|
|
44
|
+
},
|
|
45
|
+
"pi-headless": {
|
|
46
|
+
"harness": "pi-headless",
|
|
47
|
+
"cmd": "pi"
|
|
48
|
+
},
|
|
49
|
+
"pi": {
|
|
50
|
+
"harness": "pi",
|
|
51
|
+
"cmd": "pi"
|
|
52
|
+
}
|
|
30
53
|
},
|
|
31
|
-
"defaultLauncher": "claude"
|
|
54
|
+
"defaultLauncher": "claude-headless"
|
|
32
55
|
}
|
|
33
56
|
}
|
|
@@ -203,7 +203,7 @@ async function scan(args = []) {
|
|
|
203
203
|
}
|
|
204
204
|
// an anchor is a claim a named unit exists — dead/ambiguous/unextractable is LOUD, and until it is
|
|
205
205
|
// repaired the probe issues no verdict, so the reading stays conservatively stale.
|
|
206
|
-
for (const p of [...axis.problems, ...anchorProblems(root, axis.entries)]) {
|
|
206
|
+
for (const p of [...axis.problems, ...(await anchorProblems(root, axis.entries))]) {
|
|
207
207
|
malformed++;
|
|
208
208
|
findings.push(` • eval-schema: '${s.id}' scenario '${sc.name}' ${p} — fix ${y.evalPath}`);
|
|
209
209
|
}
|
|
@@ -83,6 +83,7 @@ export type EvalContext = {
|
|
|
83
83
|
export declare function evalContext(root: string, specs: Awaited<ReturnType<typeof loadSpecs>>, idx: DriftIndex, hidx: HistoryIndex, remarks?: Map<string, RemarkTrack>, ynodes?: EvalNode[]): Promise<EvalContext>;
|
|
84
84
|
export declare function evalTimelines(ids: readonly string[], ctx?: EvalContext, opts?: {
|
|
85
85
|
order?: boolean;
|
|
86
|
+
latestOnly?: boolean;
|
|
86
87
|
}): Promise<EvalTimeline[]>;
|
|
87
88
|
export declare function evalTimeline(id: string, ctx?: EvalContext): Promise<EvalTimeline>;
|
|
88
89
|
export type BlobResult = {
|
|
@@ -50,9 +50,14 @@ export async function evalTimelines(ids, ctx, opts = {}) {
|
|
|
50
50
|
const codeEntries = specs.find((s) => dirname(s.path) === relative(root, ynode.dir))?.codeEntries ?? [];
|
|
51
51
|
const byName = new Map(ynode.scenarios.map((s) => [s.name, s]));
|
|
52
52
|
const { readings, retractions, oks } = readSidecar(ynode.sidecarPath);
|
|
53
|
-
const
|
|
53
|
+
const allRows = applyRetractions(readings, retractions).map((reading) => ({
|
|
54
54
|
reading, axis: scenarioCodeAxis(byName.get(reading.scenario)?.code, codeEntries),
|
|
55
55
|
}));
|
|
56
|
+
// The board only renders the latest state per scenario. Historical rows remain available to the
|
|
57
|
+
// session/eval detail paths, but sending them through freshness here multiplies immutable Git probes.
|
|
58
|
+
const rows = opts.latestOnly
|
|
59
|
+
? [...allRows.reduce((latest, row) => latest.set(row.reading.scenario, row), new Map()).values()]
|
|
60
|
+
: allRows;
|
|
56
61
|
return { id, ynode, codeEntries, rows, retractions, oks };
|
|
57
62
|
});
|
|
58
63
|
// an order-only read stops HERE, before a single probe: the rows above are already the whole answer.
|
|
@@ -30,7 +30,7 @@ export type AnchorDemand = {
|
|
|
30
30
|
entries: readonly RelationEntry[];
|
|
31
31
|
};
|
|
32
32
|
export declare function anchorProbeFor(root: string, idx: DriftIndex): AnchorProbe;
|
|
33
|
-
export declare function anchorProblems(root: string, entries: readonly RelationEntry[]): string[]
|
|
33
|
+
export declare function anchorProblems(root: string, entries: readonly RelationEntry[]): Promise<string[]>;
|
|
34
34
|
export type RemarkSignal = {
|
|
35
35
|
resolved: boolean;
|
|
36
36
|
resolvedAt?: string;
|
|
@@ -497,7 +497,7 @@ const currentTreeUnitMemo = new Map();
|
|
|
497
497
|
// caller retaining a verdict derived from these units names it by the same identity that decides the parse
|
|
498
498
|
// ([[selector-anchor-scope]]). Returning the key rather than re-deriving it elsewhere is what keeps the two
|
|
499
499
|
// from drifting apart.
|
|
500
|
-
function currentTreeImage(root, x, path) {
|
|
500
|
+
async function currentTreeImage(root, x, path) {
|
|
501
501
|
const source = readFileSync(join(root, path), 'utf8');
|
|
502
502
|
const key = `${x.memoKey(path)}\0${createHash('sha1').update(source).digest('hex')}`;
|
|
503
503
|
const hit = currentTreeUnitMemo.get(key);
|
|
@@ -508,7 +508,7 @@ function currentTreeImage(root, x, path) {
|
|
|
508
508
|
}
|
|
509
509
|
let entry;
|
|
510
510
|
try {
|
|
511
|
-
entry = { units: x.extract(source, path) };
|
|
511
|
+
entry = { units: await x.extract(source, path) };
|
|
512
512
|
}
|
|
513
513
|
catch (err) {
|
|
514
514
|
entry = { failed: err?.message ?? String(err) };
|
|
@@ -520,15 +520,15 @@ function currentTreeImage(root, x, path) {
|
|
|
520
520
|
throw new Error(entry.failed);
|
|
521
521
|
return { key, units: entry.units };
|
|
522
522
|
}
|
|
523
|
-
function entryImage(root, regs, path, selector) {
|
|
523
|
+
async function entryImage(root, regs, path, selector) {
|
|
524
524
|
const x = extractorFor(regs, extOf(path));
|
|
525
525
|
if (!x)
|
|
526
526
|
return { problem: `\`code\` selector \`${path}#${selector}\` — no designated extractor for that language; drop the #anchor or add a language row` };
|
|
527
|
-
const ready = x.ready();
|
|
527
|
+
const ready = await x.ready();
|
|
528
528
|
if (ready !== true)
|
|
529
529
|
return { problem: `\`code\` anchors on ${path} are unverified: ${ready}` };
|
|
530
530
|
try {
|
|
531
|
-
return currentTreeImage(root, x, path);
|
|
531
|
+
return await currentTreeImage(root, x, path);
|
|
532
532
|
}
|
|
533
533
|
catch (err) {
|
|
534
534
|
return { problem: `\`code\` anchors on ${path} are unverified: ${err?.message ?? String(err)}` };
|
|
@@ -550,8 +550,8 @@ function selectorProblem(units, path, selectors) {
|
|
|
550
550
|
}
|
|
551
551
|
return null;
|
|
552
552
|
}
|
|
553
|
-
function entryUnverifiable(root, regs, entry) {
|
|
554
|
-
const image = entryImage(root, regs, entry.path, entry.selectors[0]);
|
|
553
|
+
async function entryUnverifiable(root, regs, entry) {
|
|
554
|
+
const image = await entryImage(root, regs, entry.path, entry.selectors[0]);
|
|
555
555
|
return 'problem' in image ? image.problem : selectorProblem(image.units, entry.path, entry.selectors);
|
|
556
556
|
}
|
|
557
557
|
// @@@ the verify sweep must reach the MACROTASK queue - resolving every reading's `code:` selectors against
|
|
@@ -603,10 +603,10 @@ export function anchorProbeFor(root, idx) {
|
|
|
603
603
|
// one coherent read of each source per sweep: every entry on a path resolves against the same bytes,
|
|
604
604
|
// and the read that names the verdict is the read the verdict was derived from.
|
|
605
605
|
const images = new Map();
|
|
606
|
-
const imageOf = (path, selector) => {
|
|
606
|
+
const imageOf = async (path, selector) => {
|
|
607
607
|
let hit = images.get(path);
|
|
608
608
|
if (hit === undefined) {
|
|
609
|
-
hit = entryImage(root, regs, path, selector);
|
|
609
|
+
hit = await entryImage(root, regs, path, selector);
|
|
610
610
|
images.set(path, hit);
|
|
611
611
|
}
|
|
612
612
|
return hit;
|
|
@@ -630,7 +630,7 @@ export function anchorProbeFor(root, idx) {
|
|
|
630
630
|
const key = anchorKey(sinceSha, e.path, e.selectors);
|
|
631
631
|
if (verdicts.has(key) || queued.has(key))
|
|
632
632
|
continue;
|
|
633
|
-
const image = imageOf(e.path, e.selectors[0]);
|
|
633
|
+
const image = await imageOf(e.path, e.selectors[0]);
|
|
634
634
|
const name = 'problem' in image ? null : `${registry}\x1f${image.key}\x1f${key}`;
|
|
635
635
|
const remembered = scope && name !== null ? scope.anchorVerdicts.get(name) : undefined;
|
|
636
636
|
if (remembered !== undefined) {
|
|
@@ -666,13 +666,13 @@ export function anchorProbeFor(root, idx) {
|
|
|
666
666
|
// the LOUD half: a selector is a claim that a named unit EXISTS, held to the same standard as a ghost path.
|
|
667
667
|
// Dead, ambiguous, unparseable, or no designated extractor — each names itself and its repair, and until
|
|
668
668
|
// repaired the probe issues no verdict, so the reading stays stale. Over-warn, never a silent pass.
|
|
669
|
-
export function anchorProblems(root, entries) {
|
|
669
|
+
export async function anchorProblems(root, entries) {
|
|
670
670
|
const regs = extractors(root);
|
|
671
671
|
const out = [];
|
|
672
672
|
for (const e of entries) {
|
|
673
673
|
if (!e.selectors.length)
|
|
674
674
|
continue;
|
|
675
|
-
const problem = entryUnverifiable(root, regs, e);
|
|
675
|
+
const problem = await entryUnverifiable(root, regs, e);
|
|
676
676
|
if (problem)
|
|
677
677
|
out.push(problem);
|
|
678
678
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RemarkTrack } from './remarks.js';
|
|
2
|
+
import type { ReviewDiffFile } from '@spexcode/spec-core';
|
|
2
3
|
export type EvalHost = {
|
|
3
4
|
loadConfig?: (root: string) => any;
|
|
4
5
|
trackedSourceFiles?: (root: string, roots: string[], policy: any) => string[];
|
|
@@ -19,7 +20,7 @@ export type ReviewPayload = {
|
|
|
19
20
|
label: string;
|
|
20
21
|
ahead: number;
|
|
21
22
|
dirtyNonRuntime: number;
|
|
22
|
-
diff:
|
|
23
|
+
diff: ReviewDiffFile[];
|
|
23
24
|
gates: {
|
|
24
25
|
conflictsWithMain: boolean;
|
|
25
26
|
lint: {
|
|
@@ -218,7 +218,7 @@ export type SessionEvalRevision = {
|
|
|
218
218
|
export type SessionEvalProjection = {
|
|
219
219
|
epoch: string;
|
|
220
220
|
generation: number;
|
|
221
|
-
phase: 'loading' | 'updating' | 'ready' | 'error';
|
|
221
|
+
phase: 'loading' | 'updating' | 'ready' | 'error' | 'dormant';
|
|
222
222
|
revision?: string;
|
|
223
223
|
value?: SessionEvalSummary;
|
|
224
224
|
lastKnown?: {
|
|
@@ -279,6 +279,7 @@ export declare class SessionEvalProjectionCache {
|
|
|
279
279
|
demand<T>(id: string, path: string, run: () => Promise<T>): Promise<T>;
|
|
280
280
|
idle(): Promise<void>;
|
|
281
281
|
accept(id: string, generation: number, revision: string, value: SessionEvalSummary): boolean;
|
|
282
|
+
private dormantEntry;
|
|
282
283
|
private project;
|
|
283
284
|
private matches;
|
|
284
285
|
private publish;
|
|
@@ -116,7 +116,7 @@ async function validateSelectorEntry(context, revision, entry, sourceView) {
|
|
|
116
116
|
if (!x) {
|
|
117
117
|
throw new SessionImpactUnavailableError(`session impact selector '${entry.path}#${entry.selectors[0]}' is unavailable: no designated extractor for '.${extOf(entry.path)}'`);
|
|
118
118
|
}
|
|
119
|
-
const ready = x.ready();
|
|
119
|
+
const ready = await x.ready();
|
|
120
120
|
if (ready !== true) {
|
|
121
121
|
throw new SessionImpactUnavailableError(`session impact selectors on '${entry.path}' are unavailable: ${ready}`);
|
|
122
122
|
}
|
|
@@ -132,7 +132,7 @@ async function validateSelectorEntry(context, revision, entry, sourceView) {
|
|
|
132
132
|
throw new SessionImpactUnavailableError(`session impact selector '${entry.path}#${entry.selectors[0]}' is dead at ${revision.slice(0, 8)}: the file does not exist`);
|
|
133
133
|
}
|
|
134
134
|
try {
|
|
135
|
-
return { extractor: x, units: x.extract(source, entry.path) };
|
|
135
|
+
return { extractor: x, units: await x.extract(source, entry.path) };
|
|
136
136
|
}
|
|
137
137
|
catch (error) {
|
|
138
138
|
throw new SessionImpactUnavailableError(`session impact selectors on '${entry.path}' are unextractable at ${revision.slice(0, 8)}: ${error?.message ?? String(error)}`);
|
|
@@ -1636,6 +1636,16 @@ export class SessionEvalProjectionCache {
|
|
|
1636
1636
|
promise.finally(() => {
|
|
1637
1637
|
if (this.demands.get(id) === promise)
|
|
1638
1638
|
this.demands.delete(id);
|
|
1639
|
+
// The cancel above exists ONLY so the warmup does not duplicate the build this demand is about to run.
|
|
1640
|
+
// Once the demand has settled that reason is spent — and a demand that REJECTED published nothing, so
|
|
1641
|
+
// leaving the mark set kept `authorize` refusing this generation forever and the entry stuck at
|
|
1642
|
+
// `loading`/`updating` with no build ever scheduled. A demand that published is already `ready` and
|
|
1643
|
+
// needs no second build.
|
|
1644
|
+
if (this.entries.get(id) !== entry || entry.demandCancelledGeneration !== entry.generation)
|
|
1645
|
+
return;
|
|
1646
|
+
entry.demandCancelledGeneration = null;
|
|
1647
|
+
this.authorize(entry);
|
|
1648
|
+
queueMicrotask(() => this.startScheduled());
|
|
1639
1649
|
}).catch(() => { });
|
|
1640
1650
|
return promise;
|
|
1641
1651
|
}
|
|
@@ -1660,12 +1670,19 @@ export class SessionEvalProjectionCache {
|
|
|
1660
1670
|
this.notify();
|
|
1661
1671
|
return true;
|
|
1662
1672
|
}
|
|
1673
|
+
// Dormant offline history is demand-only BY POLICY: `authorize` refuses to schedule an offline entry, so
|
|
1674
|
+
// nothing will move it until a demand builds it. `loading`/`updating` are arrival phases — a reader that
|
|
1675
|
+
// renders them as progress waits forever. This names the difference at the one place that knows it.
|
|
1676
|
+
dormantEntry(entry) {
|
|
1677
|
+
return entry.liveness === 'offline' && entry.running == null && entry.scheduled == null
|
|
1678
|
+
&& entry.observerHolds.size === 0 && entry.phase !== 'ready' && entry.phase !== 'error';
|
|
1679
|
+
}
|
|
1663
1680
|
project(entry) {
|
|
1664
1681
|
const stable = entry.current;
|
|
1665
1682
|
return {
|
|
1666
1683
|
epoch: this.epoch,
|
|
1667
1684
|
generation: entry.generation,
|
|
1668
|
-
phase: entry.phase,
|
|
1685
|
+
phase: this.dormantEntry(entry) ? 'dormant' : entry.phase,
|
|
1669
1686
|
...(entry.phase === 'ready' && stable
|
|
1670
1687
|
? { revision: stable.revision, value: stable.value }
|
|
1671
1688
|
: stable ? { lastKnown: stable } : {}),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spexcode/spec-eval",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0-next.0",
|
|
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.
|
|
29
|
+
"@spexcode/spec-core": "0.7.0-next.0"
|
|
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.
|
|
3
|
+
"version": "0.7.0-next.0",
|
|
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.
|
|
25
|
+
"@spexcode/spec-core": "0.7.0-next.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^20.16.0",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type TranscriptRead, type TranscriptReader, type TranscriptTool, type TranscriptTurn } from './turns.js';
|
|
2
|
+
export type StreamTool = Readonly<Omit<TranscriptTool, 'output'> & {
|
|
3
|
+
output?: null;
|
|
4
|
+
}>;
|
|
5
|
+
export type StreamTurn = Readonly<Omit<TranscriptTurn, 'tools'> & {
|
|
6
|
+
tools?: readonly StreamTool[];
|
|
7
|
+
}>;
|
|
8
|
+
export type StreamFrame = Readonly<Omit<TranscriptRead, 'turns'> & {
|
|
9
|
+
kind: 'full' | 'delta';
|
|
10
|
+
turns: readonly StreamTurn[];
|
|
11
|
+
removed?: readonly string[];
|
|
12
|
+
}>;
|
|
13
|
+
export type TranscriptErrorFrame = Readonly<{
|
|
14
|
+
revision: string;
|
|
15
|
+
from: number;
|
|
16
|
+
to: number;
|
|
17
|
+
error: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
}>;
|
|
20
|
+
export type TranscriptFrame = StreamFrame | TranscriptErrorFrame;
|
|
21
|
+
export declare const isErrorFrame: (frame: TranscriptFrame) => frame is TranscriptErrorFrame;
|
|
22
|
+
export declare const ABSENT_REVISION = "absent";
|
|
23
|
+
export declare const withheld: (read: TranscriptRead) => Omit<StreamFrame, "kind">;
|
|
24
|
+
export declare class FrameProducer {
|
|
25
|
+
private primed;
|
|
26
|
+
private sent;
|
|
27
|
+
private counters;
|
|
28
|
+
next(read: TranscriptRead): StreamFrame | null;
|
|
29
|
+
reset(): void;
|
|
30
|
+
}
|
|
31
|
+
export declare const absentFrame: (from: number, to: number) => StreamFrame;
|
|
32
|
+
export type FrameStream = Readonly<{
|
|
33
|
+
publish(now?: number): Promise<TranscriptFrame | null>;
|
|
34
|
+
close(): void;
|
|
35
|
+
}>;
|
|
36
|
+
export declare function openFrameStream(reader: TranscriptReader, threadId: string, from: number, clock?: () => number): FrameStream;
|
|
37
|
+
export type HeldTranscript = Readonly<{
|
|
38
|
+
turns: readonly StreamTurn[];
|
|
39
|
+
}>;
|
|
40
|
+
export type MergedFrame = Readonly<{
|
|
41
|
+
state: HeldTranscript;
|
|
42
|
+
payload: TranscriptErrorFrame | (Omit<StreamFrame, 'kind' | 'removed'>);
|
|
43
|
+
}>;
|
|
44
|
+
export declare function mergeTranscriptFrame(state: HeldTranscript, frame: TranscriptFrame): MergedFrame;
|