@moolam/edge-agent 1.0.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.
@@ -0,0 +1,247 @@
1
+ /**
2
+ * @module slm_runtime
3
+ *
4
+ * Pluggable local inference boundary of the Edge Harness.
5
+ *
6
+ * The harness never links against a specific inference engine. Instead it
7
+ * speaks `SlmRuntime`, and adapters bind that interface to whatever the
8
+ * host device offers:
9
+ * - llama.cpp / GGUF (`@moolam/bindings-slm` LlamaCppSlmRuntime;
10
+ * ModelInterface via createLlamaCppModelAdapter / createSlmModelAdapter)
11
+ * - ONNX Runtime Mobile (quantized INT4/INT8 exports)
12
+ * - MediaPipe LLM Inference API (Android AICore)
13
+ * - Apple Foundation Models / MLX (iOS)
14
+ * - any localhost OpenAI-compatible server (Ollama, llamafile)
15
+ *
16
+ * CognitiveCore consumes ModelInterface. Pass a loaded LlamaCppSlmRuntime
17
+ * into edge cognitive bindings, or call createLlamaCppModelAdapter and
18
+ * inject the resulting model into the binding set.
19
+ *
20
+ * This is what makes the Edge Harness sovereign: a district deployment can
21
+ * swap models and engines without touching a line of domain code.
22
+ */
23
+ /** Init/load obligation named on typed failures (never silent catch-and-continue). */
24
+ export const EDGE_SLM_LOAD_OBLIGATION = "EDGE.SLM_LOAD";
25
+ /**
26
+ * Typed initialization/load failure for local model weights.
27
+ * Hosts MUST surface this to the operator — never retry unboundedly.
28
+ */
29
+ export class SlmRuntimeInitError extends Error {
30
+ name = "SlmRuntimeInitError";
31
+ failureClass;
32
+ obligationId;
33
+ reason;
34
+ constructor(message, opts) {
35
+ super(message);
36
+ this.failureClass = opts.failureClass;
37
+ this.reason = opts.reason;
38
+ this.obligationId = opts.obligationId ?? EDGE_SLM_LOAD_OBLIGATION;
39
+ }
40
+ }
41
+ /** Magic prefix for drill / on-disk weight fixtures (not a full GGUF parser). */
42
+ export const SLM_WEIGHTS_MAGIC = "SUTRA-WEIGHTS-v1";
43
+ /**
44
+ * File-backed SlmRuntime load seam used for edge degradation drills and
45
+ * host deployments that materialize weights from disk before inference.
46
+ *
47
+ * Missing or corrupt weights → {@link SlmRuntimeInitError} once per `load()`
48
+ * (no internal retry loop). Generation requires a prior successful load.
49
+ */
50
+ export class LocalWeightSlmRuntime {
51
+ card;
52
+ options;
53
+ loaded = false;
54
+ loadAttempts = 0;
55
+ constructor(card, options) {
56
+ this.card = card;
57
+ this.options = options;
58
+ if (!options.weightsPath || !String(options.weightsPath).trim()) {
59
+ throw new SlmRuntimeInitError("LocalWeightSlmRuntime requires weightsPath", {
60
+ failureClass: "config",
61
+ reason: "config",
62
+ });
63
+ }
64
+ }
65
+ /** How many times `load()` has been invoked (crash-loop detection). */
66
+ get loadAttemptCount() {
67
+ return this.loadAttempts;
68
+ }
69
+ get isLoaded() {
70
+ return this.loaded;
71
+ }
72
+ async load() {
73
+ this.loadAttempts += 1;
74
+ if (this.loaded) {
75
+ this.emit({ op: "load", outcome: "ok" });
76
+ return;
77
+ }
78
+ const fs = await import("node:fs/promises");
79
+ const path = this.options.weightsPath;
80
+ let bytes;
81
+ try {
82
+ bytes = new Uint8Array(await fs.readFile(path));
83
+ }
84
+ catch (err) {
85
+ const code = err && typeof err === "object" && "code" in err
86
+ ? String(err.code)
87
+ : "";
88
+ if (code === "ENOENT" || code === "ENOTDIR") {
89
+ throw this.failLoad("missing", `model weights missing at path`);
90
+ }
91
+ throw this.failLoad("corrupt", `model weights unreadable (${code || "io_error"})`);
92
+ }
93
+ if (bytes.byteLength === 0) {
94
+ throw this.failLoad("corrupt", "model weights file is empty");
95
+ }
96
+ const header = new TextDecoder().decode(bytes.subarray(0, Math.min(bytes.byteLength, SLM_WEIGHTS_MAGIC.length)));
97
+ if (header !== SLM_WEIGHTS_MAGIC) {
98
+ throw this.failLoad("corrupt", "model weights magic header mismatch");
99
+ }
100
+ if (this.options.inspectWeights && !this.options.inspectWeights(bytes)) {
101
+ throw this.failLoad("corrupt", "model weights failed integrity inspect");
102
+ }
103
+ this.loaded = true;
104
+ this.emit({ op: "load", outcome: "ok" });
105
+ }
106
+ async unload() {
107
+ this.loaded = false;
108
+ this.emit({ op: "unload", outcome: "ok" });
109
+ }
110
+ async generate(_params) {
111
+ if (!this.loaded) {
112
+ throw new SlmRuntimeInitError("SlmRuntime.generate before successful load", {
113
+ failureClass: "config",
114
+ reason: "config",
115
+ });
116
+ }
117
+ // Reference: weights-validated stub; native adapters replace with real inference.
118
+ return { text: "", tokensPerSecond: 0, finishReason: "stop" };
119
+ }
120
+ async *generateStream(params) {
121
+ const result = await this.generate(params);
122
+ if (result.text)
123
+ yield result.text;
124
+ }
125
+ async embed(_text) {
126
+ if (!this.loaded) {
127
+ throw new SlmRuntimeInitError("SlmRuntime.embed before successful load", {
128
+ failureClass: "config",
129
+ reason: "config",
130
+ });
131
+ }
132
+ return new Float32Array(8);
133
+ }
134
+ failLoad(reason, message) {
135
+ const failureClass = reason === "missing" ? "missing_weights" : "corrupt_weights";
136
+ const error = new SlmRuntimeInitError(message, {
137
+ failureClass,
138
+ reason,
139
+ });
140
+ this.emit({
141
+ op: "load",
142
+ outcome: "init_error",
143
+ failureClass,
144
+ obligationId: EDGE_SLM_LOAD_OBLIGATION,
145
+ reason,
146
+ });
147
+ return error;
148
+ }
149
+ emit(partial) {
150
+ const event = {
151
+ event: "edge_agent.slm_runtime",
152
+ modelId: this.card.modelId,
153
+ ...partial,
154
+ };
155
+ const sid = this.options.subjectId?.trim();
156
+ const did = this.options.deviceId?.trim();
157
+ if (sid)
158
+ event.subjectId = sid;
159
+ if (did)
160
+ event.deviceId = did;
161
+ this.options.onTelemetry?.(event);
162
+ }
163
+ }
164
+ /**
165
+ * Adapter for any localhost OpenAI-compatible endpoint (Ollama, llamafile,
166
+ * llama.cpp server). This is the reference adapter used by the Playground and
167
+ * by desktop deployments; mobile targets ship their own native adapters.
168
+ */
169
+ export class OpenAiCompatibleSlmRuntime {
170
+ card;
171
+ baseUrl;
172
+ constructor(card, baseUrl = "http://127.0.0.1:11434/v1") {
173
+ this.card = card;
174
+ this.baseUrl = baseUrl;
175
+ }
176
+ async load() {
177
+ // Warm the model by issuing a 1-token generation; Ollama-style servers
178
+ // load weights lazily on first request.
179
+ await this.generate({ prompt: " ", maxTokens: 1, temperature: 0, deadlineMs: 120_000 });
180
+ }
181
+ async unload() {
182
+ // OpenAI-compatible servers manage their own eviction; nothing to do.
183
+ }
184
+ async generate(params) {
185
+ const controller = new AbortController();
186
+ const timer = setTimeout(() => controller.abort(), params.deadlineMs);
187
+ const startedAt = performance.now();
188
+ try {
189
+ const res = await fetch(`${this.baseUrl}/completions`, {
190
+ method: "POST",
191
+ headers: { "content-type": "application/json" },
192
+ signal: controller.signal,
193
+ body: JSON.stringify({
194
+ model: this.card.modelId,
195
+ prompt: params.prompt,
196
+ max_tokens: params.maxTokens,
197
+ temperature: params.temperature,
198
+ stop: params.stopSequences,
199
+ }),
200
+ });
201
+ if (!res.ok) {
202
+ throw new Error(`local SLM server returned HTTP ${res.status}`);
203
+ }
204
+ const body = (await res.json());
205
+ const choice = body.choices[0];
206
+ if (!choice)
207
+ throw new Error("local SLM server returned no choices");
208
+ const elapsedS = (performance.now() - startedAt) / 1000;
209
+ const tokens = body.usage?.completion_tokens ?? Math.ceil(choice.text.length / 4);
210
+ return {
211
+ text: choice.text,
212
+ tokensPerSecond: elapsedS > 0 ? tokens / elapsedS : 0,
213
+ finishReason: choice.finish_reason === "length" ? "length" : "stop",
214
+ };
215
+ }
216
+ catch (err) {
217
+ if (controller.signal.aborted) {
218
+ return { text: "", tokensPerSecond: 0, finishReason: "deadline" };
219
+ }
220
+ throw err;
221
+ }
222
+ finally {
223
+ clearTimeout(timer);
224
+ }
225
+ }
226
+ async *generateStream(params) {
227
+ // Reference implementation degrades to buffered generation; native
228
+ // adapters override with true SSE/token streaming.
229
+ const result = await this.generate(params);
230
+ yield result.text;
231
+ }
232
+ async embed(text) {
233
+ const res = await fetch(`${this.baseUrl}/embeddings`, {
234
+ method: "POST",
235
+ headers: { "content-type": "application/json" },
236
+ body: JSON.stringify({ model: this.card.modelId, input: text }),
237
+ });
238
+ if (!res.ok)
239
+ throw new Error(`embedding request failed: HTTP ${res.status}`);
240
+ const body = (await res.json());
241
+ const vector = body.data[0]?.embedding;
242
+ if (!vector)
243
+ throw new Error("embedding response contained no vector");
244
+ return Float32Array.from(vector);
245
+ }
246
+ }
247
+ //# sourceMappingURL=slm_runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slm_runtime.js","sourceRoot":"","sources":["../src/slm_runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Edge-owned trajectory writer.
3
+ *
4
+ * The adapter binds the shared write-ahead queue to exactly one subject and
5
+ * one sovereign locality. Loop-hook integration is intentionally separate.
6
+ */
7
+ import type { StorageDriver } from "@moolam/contracts";
8
+ import { type CaptureTrajectoryResult, type TrajectoryCaptureConsent, type TrajectoryWriterEvent } from "@moolam/telemetry";
9
+ import type { HLCTimestamp, TurnTrajectoryV1 } from "@moolam/sync-protocol";
10
+ export type EdgeTrajectoryCaptureWriterOptions = {
11
+ storage: StorageDriver;
12
+ subjectId: string;
13
+ deviceId: string;
14
+ locality?: TurnTrajectoryV1["locality"];
15
+ /** Resolve the current active record; null means capture is disabled. */
16
+ resolveActiveConsentRecordId: () => string | null | undefined;
17
+ resolveConsent: (consentRecordId: string) => TrajectoryCaptureConsent | null | undefined;
18
+ capacity?: number;
19
+ storageTimeoutMs?: number;
20
+ maxRetries?: number;
21
+ onTelemetry?: (event: TrajectoryWriterEvent) => void;
22
+ onHookTelemetry?: (event: EdgeTrajectoryCaptureHookEvent) => void;
23
+ };
24
+ export type EdgeTrajectoryCaptureHookInput = {
25
+ turnId: string;
26
+ subjectId: string;
27
+ deviceId: string;
28
+ sessionId: string;
29
+ capturedAt: HLCTimestamp;
30
+ utterance: string;
31
+ reply: string;
32
+ modelId: string;
33
+ declined: boolean;
34
+ };
35
+ export type EdgeTrajectoryCaptureHookEvent = {
36
+ event: "edge_agent.trajectory_capture";
37
+ outcome: "scheduled" | "skipped" | "queued" | "rejected";
38
+ subjectId: string;
39
+ deviceId: string;
40
+ turnId: string;
41
+ failureClass?: "consent_missing" | "consent_resolve_failed" | "cross_subject" | "cross_device" | "content_too_large" | "hash_failed" | string;
42
+ };
43
+ export type ScheduleTrajectoryCaptureResult = {
44
+ scheduled: true;
45
+ subjectId: string;
46
+ turnId: string;
47
+ } | {
48
+ scheduled: false;
49
+ subjectId: string;
50
+ turnId: string;
51
+ failureClass: string;
52
+ };
53
+ /**
54
+ * Subject-scoped SQLite trajectory persistence for an edge installation.
55
+ *
56
+ * `captureTrajectory` is synchronous: it only admits to the bounded queue.
57
+ * Durable write-ahead and final inserts run in the background.
58
+ */
59
+ export declare class EdgeTrajectoryCaptureWriter {
60
+ private readonly queue;
61
+ private readonly subjectId;
62
+ private readonly deviceId;
63
+ private readonly locality;
64
+ private readonly resolveActiveConsentRecordId;
65
+ private readonly onHookTelemetry;
66
+ private readonly pendingBuilds;
67
+ constructor(options: EdgeTrajectoryCaptureWriterOptions);
68
+ initialize(): Promise<void>;
69
+ captureTrajectory(input: unknown): CaptureTrajectoryResult;
70
+ /**
71
+ * Completion hook invoked only after CognitiveCore's reflect stage resolves.
72
+ *
73
+ * Consent is resolved before hashing. Hashing and queue persistence continue
74
+ * asynchronously, so the completed turn never awaits trajectory I/O.
75
+ */
76
+ captureAfterReflect(input: EdgeTrajectoryCaptureHookInput): ScheduleTrajectoryCaptureResult;
77
+ flush(timeoutMs?: number): Promise<boolean>;
78
+ get queueDepth(): number;
79
+ get droppedCount(): number;
80
+ private rejectHook;
81
+ private emitHook;
82
+ }
83
+ //# sourceMappingURL=trajectory_capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trajectory_capture.d.ts","sourceRoot":"","sources":["../src/trajectory_capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Edge-owned trajectory writer.
3
+ *
4
+ * The adapter binds the shared write-ahead queue to exactly one subject and
5
+ * one sovereign locality. Loop-hook integration is intentionally separate.
6
+ */
7
+ import { TrajectoryWriteAheadQueue, } from "@moolam/telemetry";
8
+ const TRAJECTORY_CONTENT_HASH_MAX_BYTES = 64_000;
9
+ /**
10
+ * Subject-scoped SQLite trajectory persistence for an edge installation.
11
+ *
12
+ * `captureTrajectory` is synchronous: it only admits to the bounded queue.
13
+ * Durable write-ahead and final inserts run in the background.
14
+ */
15
+ export class EdgeTrajectoryCaptureWriter {
16
+ queue;
17
+ subjectId;
18
+ deviceId;
19
+ locality;
20
+ resolveActiveConsentRecordId;
21
+ onHookTelemetry;
22
+ pendingBuilds = new Set();
23
+ constructor(options) {
24
+ this.subjectId = options.subjectId.trim();
25
+ this.deviceId = options.deviceId.trim();
26
+ this.locality = options.locality ?? "on-device";
27
+ if (!this.deviceId) {
28
+ throw new Error("edge trajectory writer deviceId is required");
29
+ }
30
+ this.resolveActiveConsentRecordId = options.resolveActiveConsentRecordId;
31
+ this.onHookTelemetry = options.onHookTelemetry;
32
+ this.queue = new TrajectoryWriteAheadQueue({
33
+ driver: options.storage,
34
+ subjectId: this.subjectId,
35
+ locality: this.locality,
36
+ resolveConsent: options.resolveConsent,
37
+ ...(options.capacity === undefined ? {} : { capacity: options.capacity }),
38
+ ...(options.storageTimeoutMs === undefined
39
+ ? {}
40
+ : { storageTimeoutMs: options.storageTimeoutMs }),
41
+ ...(options.maxRetries === undefined
42
+ ? {}
43
+ : { maxRetries: options.maxRetries }),
44
+ ...(options.onTelemetry === undefined
45
+ ? {}
46
+ : { onTelemetry: options.onTelemetry }),
47
+ });
48
+ }
49
+ async initialize() {
50
+ await this.queue.initialize();
51
+ }
52
+ captureTrajectory(input) {
53
+ return this.queue.captureTrajectory(input);
54
+ }
55
+ /**
56
+ * Completion hook invoked only after CognitiveCore's reflect stage resolves.
57
+ *
58
+ * Consent is resolved before hashing. Hashing and queue persistence continue
59
+ * asynchronously, so the completed turn never awaits trajectory I/O.
60
+ */
61
+ captureAfterReflect(input) {
62
+ if (input.subjectId !== this.subjectId) {
63
+ return this.rejectHook(input, "cross_subject");
64
+ }
65
+ if (input.deviceId !== this.deviceId) {
66
+ return this.rejectHook(input, "cross_device");
67
+ }
68
+ let consentRecordId;
69
+ try {
70
+ consentRecordId = this.resolveActiveConsentRecordId()?.trim() ?? "";
71
+ }
72
+ catch {
73
+ return this.rejectHook(input, "consent_resolve_failed");
74
+ }
75
+ if (!consentRecordId) {
76
+ this.emitHook(input, "skipped", "consent_missing");
77
+ return {
78
+ scheduled: false,
79
+ subjectId: input.subjectId,
80
+ turnId: input.turnId,
81
+ failureClass: "consent_missing",
82
+ };
83
+ }
84
+ const promptBytes = new TextEncoder().encode(input.utterance);
85
+ const responseBytes = new TextEncoder().encode(input.reply);
86
+ if (promptBytes.byteLength > TRAJECTORY_CONTENT_HASH_MAX_BYTES ||
87
+ responseBytes.byteLength > TRAJECTORY_CONTENT_HASH_MAX_BYTES) {
88
+ return this.rejectHook(input, "content_too_large");
89
+ }
90
+ const build = Promise.all([
91
+ sha256Hex(promptBytes),
92
+ sha256Hex(responseBytes),
93
+ ])
94
+ .then(([promptHash, responseHash]) => {
95
+ const record = {
96
+ trajectoryFormatVersion: "trajectory.v1",
97
+ turnId: input.turnId,
98
+ subjectId: input.subjectId,
99
+ deviceId: input.deviceId,
100
+ sessionId: input.sessionId,
101
+ capturedAt: input.capturedAt,
102
+ locality: this.locality,
103
+ consentRecordId,
104
+ stages: [
105
+ { stage: "perceive", status: "ok", chunkIndex: 0 },
106
+ { stage: "reason", status: "ok", chunkIndex: 0 },
107
+ {
108
+ stage: "act",
109
+ status: input.declined ? "skipped" : "ok",
110
+ chunkIndex: 0,
111
+ },
112
+ ],
113
+ toolCalls: [],
114
+ outcomes: {
115
+ status: "completed",
116
+ terminalStage: input.declined ? "reason" : "act",
117
+ },
118
+ modelId: input.modelId,
119
+ promptHash,
120
+ responseHash,
121
+ promptByteLength: promptBytes.byteLength,
122
+ responseByteLength: responseBytes.byteLength,
123
+ };
124
+ const result = this.queue.captureTrajectory(record);
125
+ this.emitHook(input, result.queued ? "queued" : "rejected", result.queued ? undefined : result.failureClass);
126
+ })
127
+ .catch(() => {
128
+ this.emitHook(input, "rejected", "hash_failed");
129
+ })
130
+ .finally(() => {
131
+ this.pendingBuilds.delete(build);
132
+ });
133
+ this.pendingBuilds.add(build);
134
+ this.emitHook(input, "scheduled");
135
+ return {
136
+ scheduled: true,
137
+ subjectId: input.subjectId,
138
+ turnId: input.turnId,
139
+ };
140
+ }
141
+ async flush(timeoutMs) {
142
+ await Promise.allSettled([...this.pendingBuilds]);
143
+ return timeoutMs === undefined
144
+ ? await this.queue.flush()
145
+ : await this.queue.flush(timeoutMs);
146
+ }
147
+ get queueDepth() {
148
+ return this.queue.queueDepth;
149
+ }
150
+ get droppedCount() {
151
+ return this.queue.droppedCount;
152
+ }
153
+ rejectHook(input, failureClass) {
154
+ this.emitHook(input, "rejected", failureClass);
155
+ return {
156
+ scheduled: false,
157
+ subjectId: input.subjectId,
158
+ turnId: input.turnId,
159
+ failureClass,
160
+ };
161
+ }
162
+ emitHook(input, outcome, failureClass) {
163
+ if (!this.onHookTelemetry)
164
+ return;
165
+ const event = {
166
+ event: "edge_agent.trajectory_capture",
167
+ outcome,
168
+ subjectId: input.subjectId,
169
+ deviceId: input.deviceId,
170
+ turnId: input.turnId,
171
+ ...(failureClass === undefined ? {} : { failureClass }),
172
+ };
173
+ try {
174
+ this.onHookTelemetry(event);
175
+ }
176
+ catch (error) {
177
+ console.error(JSON.stringify({
178
+ event: "edge_agent.trajectory_capture.observer",
179
+ outcome: "rejected",
180
+ subjectId: input.subjectId,
181
+ deviceId: input.deviceId,
182
+ failureClass: error instanceof Error ? error.name.slice(0, 64) : "observer_failed",
183
+ }));
184
+ }
185
+ }
186
+ }
187
+ async function sha256Hex(bytes) {
188
+ const digest = await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes).buffer);
189
+ return `sha256:${[...new Uint8Array(digest)]
190
+ .map((byte) => byte.toString(16).padStart(2, "0"))
191
+ .join("")}`;
192
+ }
193
+ //# sourceMappingURL=trajectory_capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trajectory_capture.js","sourceRoot":"","sources":["../src/trajectory_capture.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@moolam/edge-agent",
3
+ "version": "1.0.0",
4
+ "description": "The Edge Harness. Offline-first autonomous agent runtime for local SLMs (Phi-3, Gemma, quantized GGUF/ONNX) with durable friction telemetry and on-device vector memory.",
5
+ "license": "Apache-2.0",
6
+ "homepage": "https://github.com/moolamai/sutra/tree/main/packages/edge-agent#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/moolamai/sutra.git",
10
+ "directory": "packages/edge-agent"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "dependencies": {
28
+ "@moolam/cognitive-core": "1.0.0",
29
+ "@moolam/contracts": "1.0.0",
30
+ "@moolam/observability": "1.0.0",
31
+ "@moolam/runtime": "1.0.0",
32
+ "@moolam/sync-protocol": "1.0.0",
33
+ "@moolam/telemetry": "1.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@opentelemetry/sdk-trace-base": "2.0.1",
37
+ "@types/node": "^22.20.0",
38
+ "typescript": "^5.8.0",
39
+ "@moolam/contract-conformance": "1.0.0"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc -p tsconfig.json",
43
+ "typecheck": "tsc -p tsconfig.json --noEmit",
44
+ "test": "pnpm run build && node --test tests/chat_prompt_assembly.test.mjs tests/slm_model_adapter.test.mjs tests/slm_runtime_weights.test.mjs tests/model_adapter_conformance.test.mjs tests/local_vector_memory.test.mjs tests/memory_decay_pinning.test.mjs tests/edge_cognitive_bindings.test.mjs tests/edge_agent_event_bus.test.mjs tests/edge_agent_turn_completed.test.mjs tests/edge_agent_sync_outcome.test.mjs tests/edge_agent_unified_turn.test.mjs tests/trajectory_capture_hook.test.mjs tests/trajectory_capture_load.test.mjs tests/offline_edge_regression.test.mjs tests/offline_horizon.test.mjs tests/coldstart.test.mjs tests/coldstart_parity.test.mjs",
45
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
46
+ }
47
+ }