@mstar-harness/dsh 3.7.3 → 3.8.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,154 @@
1
+ /**
2
+ * Host half of the panel's engine-status channel: the `mstar/engineStatus`
3
+ * endpoint on the host's SHARED `/api` typert gateway.
4
+ *
5
+ * WHY this shape: a plugin cannot own a route. The host's typertGateway owns
6
+ * the single `/api` interceptor (`connection.rpc.intercept('/api')` would
7
+ * throw), and a third-party `connection.rpc.handle(...)` channel mounts through
8
+ * `webServer` on the CALLING fiber — which would force `webServer` into this
9
+ * plugin's static inject and pend the row on a base-only profile. The working
10
+ * third-party pattern is therefore a cordis service extending
11
+ * `TypertRemoteService` (the namespace IS the service key) whose endpoint
12
+ * descriptors are contributed with `ctx.typert.register(...)` from an OPTIONAL
13
+ * child (`ctx.inject(['typert'], …)`): a composition without a typert registry
14
+ * simply has no `/api` endpoints, and the plugin's runtime keeps working.
15
+ *
16
+ * The browser half calls `connection.rpc.call('/api', 'mstar/engineStatus',
17
+ * { args: { sessionId, cwd } })` — the payload contract is exactly one
18
+ * plain-object `args` field keyed by the declared parameter names.
19
+ *
20
+ * HARD constraint — headless boot safety: this module is reachable from
21
+ * `apply`, and it must never make the host row statically inject `connection`
22
+ * or `webServer`. Everything web-only is inside the optional inject child; the
23
+ * endpoint's own reads (`ctx.get('sessions')`, `ctx.get('sessionController')`)
24
+ * are structural and degrade when the service is absent.
25
+ *
26
+ * VALIDATION CHAIN — the endpoint serves ONE session's snapshot and answers
27
+ * otherwise. In order:
28
+ * 1. argument shape (non-empty ids, an absolute traversal-free `cwd`);
29
+ * 2. the session is resolved SERVER-side — the live `ctx.sessions.get(id)`
30
+ * first, then the session controller's persisted `inspect(id)` fallback;
31
+ * 3. the `{HARNESS_DIR}` comes from the SERVER-side session cwd (or the
32
+ * boot-resolved config root) — never from client-asserted input;
33
+ * 4. the store entry for that session must exist;
34
+ * 5. the client-asserted `cwd` must EQUAL the record's `cwd`, and the record's
35
+ * `cwd` must equal the resolved session's cwd.
36
+ * Every failure returns the explicit unavailable state WITH a reason: never
37
+ * another session's data, never a silently-close match, never a path built from
38
+ * unvalidated input.
39
+ *
40
+ * @module @mstar-harness/dsh/engine-status-endpoint
41
+ */
42
+ import type { Context } from '@deepseek-ai/cordis';
43
+ import type { TypertContribution } from '@deepseek-ai/dsh-typert-registry';
44
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
45
+ import type { HarnessResolver } from './gates/_shared.ts';
46
+ import { MSTAR_ENGINE_STATUS_METHOD, MSTAR_ENGINE_STATUS_NAMESPACE } from './engine-status-wire.ts';
47
+ export { MSTAR_ENGINE_STATUS_METHOD, MSTAR_ENGINE_STATUS_NAMESPACE };
48
+ /** The served snapshot (the stored emission, echoed back with its identity). */
49
+ export interface MstarEngineStatusOk {
50
+ readonly status: 'ok';
51
+ readonly sessionId: string;
52
+ readonly cwd: string;
53
+ /** ISO timestamp of the emission the entry records. */
54
+ readonly at: string;
55
+ /** The agent turn the row was emitted for. */
56
+ readonly turn: number;
57
+ /** The exact catalog payload emitted to that session's model. */
58
+ readonly payload: Record<string, unknown>;
59
+ }
60
+ /**
61
+ * The explicit "no answer" result. `reason` is machine-readable and always
62
+ * present — a degraded path is never silent.
63
+ */
64
+ export interface MstarEngineStatusUnavailableResult {
65
+ readonly status: 'unavailable';
66
+ readonly reason: string;
67
+ }
68
+ /** The endpoint's wire result. */
69
+ export type MstarEngineStatusResult = MstarEngineStatusOk | MstarEngineStatusUnavailableResult;
70
+ /** Options the endpoint needs from the plugin's apply scope. */
71
+ export interface MstarEngineStatusEndpointOptions {
72
+ /** The per-workspace `{HARNESS_DIR}` resolver (the same one the gates use). */
73
+ readonly resolver: HarnessResolver;
74
+ /** The boot-resolved config root when an explicit `harnessDir` is configured. */
75
+ readonly bootHarnessDir: string | null;
76
+ }
77
+ /**
78
+ * Host-side `mstar/engineStatus` service: `/api/mstar/engineStatus` serves the
79
+ * stored snapshot of the session the caller asserts.
80
+ */
81
+ export declare class MstarEngineStatusGateway extends TypertRemoteService {
82
+ private readonly resolver;
83
+ private readonly bootHarnessDir;
84
+ /**
85
+ * @param ctx - owning Cordis context.
86
+ * @param options - the apply-scoped resolver + boot root.
87
+ */
88
+ constructor(ctx: Context, options: MstarEngineStatusEndpointOptions);
89
+ /**
90
+ * Serve one session's stored engine-status snapshot after the validation
91
+ * chain documented in the module header.
92
+ * @param sessionId - the session whose snapshot is requested (client-asserted).
93
+ * @param cwd - the session workspace the client believes it is reading (client-asserted).
94
+ * @returns the stored emission, or the explicit unavailable state with a reason.
95
+ */
96
+ engineStatus(sessionId: string, cwd: string): Promise<MstarEngineStatusResult>;
97
+ /** The validation chain itself (contained by {@link engineStatus}). */
98
+ private serve;
99
+ /**
100
+ * Resolve the authoritative cwd of one session: the LIVE session first
101
+ * (`ctx.sessions.get(id)`), then the session controller's persisted
102
+ * `inspect(id)` fallback for a session that is not currently attached.
103
+ * A missing service, a missing session or a cwd-less header is an explicit
104
+ * unavailable reason, never a guess.
105
+ */
106
+ private resolveSessionCwd;
107
+ }
108
+ /**
109
+ * The generated-style invocation descriptor for `/api/mstar/engineStatus`.
110
+ *
111
+ * Registered EXPLICITLY (not through `@Remote` SRC markers): the host gateway
112
+ * checks its own `ctx.typert.local` table FIRST, while SRC discovery reads a
113
+ * module-private marker table that a locally-resolved plugin copy can never
114
+ * share with the host installation.
115
+ */
116
+ export declare function mstarEngineStatusContribution(): TypertContribution;
117
+ /**
118
+ * Install the host half of the channel on one apply scope.
119
+ *
120
+ * Two optional units, never a static inject on the plugin row:
121
+ * - the `mstar` service — `engineStatusServicePresent` above is the admission
122
+ * test, so a second apply on the same context (a sibling fiber, an HMR
123
+ * re-apply) does not construct a second gateway and keeps the FIRST instance
124
+ * with its own resolver/boot root. Constructing a second one would make the
125
+ * service's `provide` find the name taken and throw out of the child effect,
126
+ * so the present-check is the primary dedupe and the `has been registered`
127
+ * catch arm below covers what it cannot see: the concurrent-apply window, and
128
+ * an unreadable registry (the helper falls through in both cases);
129
+ * - the endpoint contribution, registered inside `ctx.inject(['typert'], …)`
130
+ * and returning that registration's own disposer — so the endpoints withdraw
131
+ * with the child fiber (or when the typert service goes away).
132
+ *
133
+ * DESCRIPTOR DEDUPE RESTS ON THE CATCH ARM. The registry does serve a presence
134
+ * probe — `local.get(endpoint)` answers the LIVE descriptor, or `undefined` when
135
+ * absent — but a pre-flight check cannot close the concurrent-apply window (two
136
+ * applies can both read it absent before either registers), so the registration
137
+ * itself stays the authoritative test. `local.hasSeen(endpoint)` is no
138
+ * substitute: it is a HISTORY probe, `true` for an endpoint registered at least
139
+ * once and staying `true` after it is withdrawn, so as a presence test it would
140
+ * skip re-registration for the endpoint a reload withdrew. A duplicate makes
141
+ * `register` throw, the arm swallows exactly that error and returns a no-op
142
+ * disposer, so a deduped apply can never withdraw another fiber's endpoint. The
143
+ * cost of that is the dependency on typert's error text (`already registered`);
144
+ * a `get`-based pre-check is the way to drop the dependency — it precedes the
145
+ * arm, but cannot replace it.
146
+ *
147
+ * Withdrawal follows ownership: the endpoint lives exactly as long as its OWNER
148
+ * fiber does. A deduped sibling that disposes withdraws nothing (it registered
149
+ * nothing); the owner disposing withdraws the service and the endpoints, and a
150
+ * later apply on a live context registers them afresh.
151
+ * @param ctx - the plugin's apply context.
152
+ * @param options - the apply-scoped resolver + boot root.
153
+ */
154
+ export declare function installEngineStatusEndpoint(ctx: Context, options: MstarEngineStatusEndpointOptions): void;
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Durable engine-status snapshot store — the edge-safe catalog source that a
3
+ * web-only reader (panel/endpoint) can serve WITHOUT re-running the in-process
4
+ * resolution that produces the step catalog.
5
+ *
6
+ * WHY a snapshot: the composed catalog payload is only available at the
7
+ * digest-gated `agent/pre-step` emission; a later reader (a different fiber,
8
+ * or the host endpoint answering a browser request) cannot rebuild it — it
9
+ * would re-resolve `{HARNESS_DIR}`, re-scan status/compass/residual, and could
10
+ * answer with state that never reached the model. Persisting the EXACT emitted
11
+ * payload at the emission site makes the served value a record of what the
12
+ * model actually saw, keyed by the session that saw it.
13
+ *
14
+ * File: `{HARNESS_DIR}/snapshots/engine-status.json`
15
+ *
16
+ * ```json
17
+ * {
18
+ * "sv": 1,
19
+ * "entries": { "<session id>": [ { "rv": 1, "cwd": "/proj", "at": "…", "turn": 3, "payload": { … } } ] }
20
+ * }
21
+ * ```
22
+ *
23
+ * `sv` is the envelope schema version and `rv` the per-entry record version:
24
+ * a reader that does not recognize EITHER must answer "unavailable" rather
25
+ * than parse a shape it does not understand — and (write rule below) a writer
26
+ * must refuse rather than replace one.
27
+ *
28
+ * Durability discipline (same as the agent-flow ledger):
29
+ * - every write runs under the per-directory inter-process write lock
30
+ * ({@link withWorkflowDirLock} — atomic `mkdir` lockdir, the package's
31
+ * single lock primitive);
32
+ * - the file itself is replaced by `writeFileSync(<writer-unique>.tmp)` +
33
+ * `renameSync` (atomic replace — concurrent readers never observe a torn
34
+ * file, and the failure cleanup can only ever remove its own temp file);
35
+ * - retention is enforced on EVERY write: newest
36
+ * {@link ENGINE_STATUS_SNAPSHOT_MAX_PER_SESSION} entries per session,
37
+ * nothing older than {@link ENGINE_STATUS_SNAPSHOT_MAX_AGE_MS}, and the whole
38
+ * envelope under {@link ENGINE_STATUS_SNAPSHOT_MAX_BYTES}.
39
+ *
40
+ * READ RULE (HARD): `sv !== 1`, an unknown shape, an unreadable file, or an
41
+ * absent file all yield the explicit {@link EngineStatusUnavailable} result.
42
+ * A best-effort parse is never returned — a reader must not present guessed
43
+ * state as the model's state.
44
+ *
45
+ * WRITE RULE (HARD): the same rule governs the writer. An existing envelope
46
+ * whose `sv` is unknown, whose JSON is torn, or that cannot be read is NOT
47
+ * replaceable: the write refuses with the explicit `degraded` reason and
48
+ * leaves the bytes untouched. Every session's snapshots live in that one file,
49
+ * so "start from an empty envelope" would silently destroy the snapshots of
50
+ * every other session sharing this `{HARNESS_DIR}` — a store the writer does
51
+ * not understand is never the writer's to overwrite (a version flap between
52
+ * two plugin builds, or a hand-truncated file, must not become data loss).
53
+ *
54
+ * BOUNDS: retention is per-session ({@link ENGINE_STATUS_SNAPSHOT_MAX_PER_SESSION}
55
+ * + {@link ENGINE_STATUS_SNAPSHOT_MAX_AGE_MS}) AND global
56
+ * ({@link ENGINE_STATUS_SNAPSHOT_MAX_BYTES}): a store above the byte ceiling
57
+ * sheds its least-recently-written session buckets — oldest first, never the
58
+ * writing session — and the write path reports the oversize condition ONCE per
59
+ * store so the host can log the one warning the containment contract promises
60
+ * instead of a warning per turn.
61
+ *
62
+ * KEYING (HARD): both session maps are prototype-less (`Object.create(null)`),
63
+ * and the read path gates on `Object.hasOwn`. The session id is caller-chosen
64
+ * on the host's `session.create` (a branded string with no shape validation),
65
+ * so an id equal to an `Object.prototype` member (`__proto__`, `constructor`,
66
+ * `toString`, …) must be an ordinary key: on a plain object literal it would
67
+ * instead read an inherited member (a non-array → `TypeError`) or hit the
68
+ * `__proto__` setter (reported `written` while persisting nothing).
69
+ *
70
+ * @module @mstar-harness/dsh/engine-status-store
71
+ */
72
+ /** Envelope schema version carried by the snapshot file (`sv`). */
73
+ export declare const ENGINE_STATUS_SNAPSHOT_VERSION = 1;
74
+ /** Per-entry record version carried by every stored entry (`rv`). */
75
+ export declare const ENGINE_STATUS_SNAPSHOT_ENTRY_VERSION = 1;
76
+ /** Retention: newest entries kept per session (older ones are pruned on write). */
77
+ export declare const ENGINE_STATUS_SNAPSHOT_MAX_PER_SESSION = 50;
78
+ /** Retention: maximum entry age (30 days) — older entries are pruned on write. */
79
+ export declare const ENGINE_STATUS_SNAPSHOT_MAX_AGE_MS: number;
80
+ /**
81
+ * Retention: global byte ceiling for one store — the bound the per-session
82
+ * numbers above cannot express, since every session in a workspace shares this
83
+ * one file. Calibrated on the measured emission payload (≈19 KB per entry,
84
+ * ≈0.9 MB per session at the 50-entry cap) to ≈16 MB, i.e. ≈17 sessions before
85
+ * the oldest buckets are evicted; the writing session is never the one evicted.
86
+ */
87
+ export declare const ENGINE_STATUS_SNAPSHOT_MAX_BYTES: number;
88
+ /**
89
+ * Lock-acquisition budget (ms) for the advisory snapshot write. The write runs
90
+ * synchronously on the per-turn `agent/pre-step` emission path, so it may never
91
+ * inherit the ledger's 30 s deadline: contention (or a stale lockdir left by a
92
+ * killed host) must degrade the advisory write quickly instead of stalling the
93
+ * agent step — and, in the same process, the `/api` gateway that serves the
94
+ * panel.
95
+ */
96
+ export declare const ENGINE_STATUS_SNAPSHOT_LOCK_TIMEOUT_MS = 250;
97
+ /** Snapshot file location relative to `{HARNESS_DIR}`. */
98
+ export declare const ENGINE_STATUS_SNAPSHOT_RELATIVE_PATH = "snapshots/engine-status.json";
99
+ /**
100
+ * One stored emission: the payload the model saw, plus the identity needed to
101
+ * validate a later reader's claim (`cwd` is the session workspace the payload
102
+ * was resolved for).
103
+ */
104
+ export interface EngineStatusSnapshotEntry {
105
+ /** Record version — a reader must see {@link ENGINE_STATUS_SNAPSHOT_ENTRY_VERSION}. */
106
+ readonly rv: number;
107
+ /** The session workspace the payload was resolved for (validation anchor). */
108
+ readonly cwd: string;
109
+ /** ISO timestamp of the emission. */
110
+ readonly at: string;
111
+ /** The agent turn the payload was emitted for. */
112
+ readonly turn: number;
113
+ /** The exact catalog payload object handed to the step messages. */
114
+ readonly payload: Record<string, unknown>;
115
+ }
116
+ /** Why a snapshot read could not produce the stored entry (every path explicit). */
117
+ export type EngineStatusSnapshotUnavailableReason = 'no-harness-dir' | 'absent' | 'unreadable' | 'invalid-json' | 'envelope-schema' | 'no-session-entry' | 'entry-schema';
118
+ /** The explicit "no answer" result — never a best-effort parse. */
119
+ export interface EngineStatusUnavailable {
120
+ readonly kind: 'unavailable';
121
+ readonly reason: EngineStatusSnapshotUnavailableReason;
122
+ }
123
+ /** Read outcome: the stored entry, or the explicit unavailable state. */
124
+ export type EngineStatusSnapshotRead = {
125
+ readonly kind: 'ok';
126
+ readonly entry: EngineStatusSnapshotEntry;
127
+ } | EngineStatusUnavailable;
128
+ /** Write outcome: written, or the degraded reason (never throws for I/O faults). */
129
+ export type EngineStatusSnapshotWrite = {
130
+ readonly kind: 'written';
131
+ readonly path: string;
132
+ readonly entries: number;
133
+ /** Session buckets shed to stay under the global byte ceiling (0 when none). */
134
+ readonly evicted: number;
135
+ /**
136
+ * Present ONLY on the first oversize write for this store in this process —
137
+ * the caller logs it. One warning per store, never one per turn.
138
+ */
139
+ readonly warn?: string;
140
+ } | {
141
+ readonly kind: 'degraded';
142
+ readonly reason: string;
143
+ };
144
+ /** One write request — the emission site's payload plus its session identity. */
145
+ export interface EngineStatusSnapshotWriteInput {
146
+ /** The session whose catalog row this payload is (`session.header.id`). */
147
+ readonly sessionId: string;
148
+ /** The session workspace the payload was resolved for (`session.header.cwd`). */
149
+ readonly cwd: string;
150
+ /** The agent turn the row was emitted for. */
151
+ readonly turn: number;
152
+ /** The exact payload object handed to the step messages. */
153
+ readonly payload: object;
154
+ /** Emission timestamp (test seam; production uses `new Date()`). */
155
+ readonly now?: Date;
156
+ /** Global byte ceiling override (test seam; production uses the constant). */
157
+ readonly maxBytes?: number;
158
+ }
159
+ /** Absolute snapshot file path for one `{HARNESS_DIR}`. */
160
+ export declare function engineStatusSnapshotPath(harnessDir: string): string;
161
+ /** The explicit unavailable result (single constructor — one shape everywhere). */
162
+ export declare function engineStatusUnavailable(reason: EngineStatusSnapshotUnavailableReason): EngineStatusUnavailable;
163
+ /**
164
+ * Read the newest stored snapshot entry for one session.
165
+ *
166
+ * Every failure path is explicit: `{HARNESS_DIR}` unresolved (`no-harness-dir`),
167
+ * file absent (`absent`), unreadable (`unreadable`), not JSON (`invalid-json`),
168
+ * wrong envelope shape/`sv` (`envelope-schema`), no entries for the session
169
+ * (`no-session-entry`), or an unreadable entry record (`entry-schema`).
170
+ * @param harnessDir - the resolved `{HARNESS_DIR}` (null when none resolved).
171
+ * @param sessionId - the session whose snapshot is requested.
172
+ * @returns the newest stored entry, or the explicit unavailable state.
173
+ */
174
+ export declare function readEngineStatusSnapshot(harnessDir: string | null, sessionId: string): EngineStatusSnapshotRead;
175
+ /**
176
+ * Persist one emission: append the entry for `sessionId`, prune (age + per
177
+ * session cap + the global byte ceiling), and atomically replace the file — the
178
+ * whole read-modify-write under the directory write lock.
179
+ *
180
+ * Contained by design: a lock timeout, a missing/unwritable directory, a failed
181
+ * replace, or an existing store this build does not understand returns
182
+ * `{kind:'degraded', reason}` (the advisory emission path must never abort the
183
+ * step it observes, and must never destroy what it cannot read). The in-memory
184
+ * payload is unaffected either way.
185
+ * @param harnessDir - the resolved `{HARNESS_DIR}` (null when none resolved).
186
+ * @param input - the emission's session identity + payload.
187
+ * @returns written (with the entry count, the evicted-bucket count and — once
188
+ * per store — the oversize warning) or the degraded reason.
189
+ */
190
+ export declare function writeEngineStatusSnapshot(harnessDir: string | null, input: EngineStatusSnapshotWriteInput): EngineStatusSnapshotWrite;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The ONE declaration of the engine-status wire address, shared by both halves
3
+ * of the channel: the host half composes the `/api` typert endpoint descriptor
4
+ * from these literals, and the browser half calls the same address through
5
+ * `connection.rpc.call(...)`.
6
+ *
7
+ * WHY a separate module: the two halves live in two bundle graphs (the host
8
+ * runs from `dist/index.js`, the panel from the closure-factory
9
+ * `dist/client.js`), and a rename on either side used to leave both suites
10
+ * green while the panel silently degraded to `transport-error` — each half's
11
+ * spec pinned only its own copy of the literals. Importing one module makes the
12
+ * rename impossible to land half-done, and `engine-status-wire.spec.ts` pins the
13
+ * descriptor the host registers against the address the client calls.
14
+ *
15
+ * CLIENT-SAFE BY CONSTRUCTION: no imports, no `node:` builtins, no side effects
16
+ * — only string literals and types. The client bundle's purity gate rejects
17
+ * non-inline-safe `@deepseek-ai/*` value imports; this module has nothing to
18
+ * inline but the two constants.
19
+ *
20
+ * @module @mstar-harness/dsh/engine-status-wire
21
+ */
22
+ /** The gateway channel the endpoint is served on (the host's shared `/api`). */
23
+ export declare const ENGINE_STATUS_CHANNEL = "/api";
24
+ /** The endpoint path on that channel (namespace + method of the descriptor). */
25
+ export declare const ENGINE_STATUS_ENDPOINT = "mstar/engineStatus";
26
+ /** Wire namespace of the invocation (the cordis service key mirrors it). */
27
+ export declare const MSTAR_ENGINE_STATUS_NAMESPACE = "mstar";
28
+ /** Wire method of the invocation → `/api/mstar/engineStatus`. */
29
+ export declare const MSTAR_ENGINE_STATUS_METHOD = "engineStatus";
@@ -305,6 +305,15 @@ export declare class HarnessResolver {
305
305
  }
306
306
  /** The workspace root of one agent — the session cwd (structural read; never trusts the runtime shape). */
307
307
  export declare function sessionCwdOf(agent: unknown): string | undefined;
308
+ /**
309
+ * The stable session id of one agent — `session.header.id` (structural read).
310
+ *
311
+ * The SAME identity a later reader asserts when it asks the host endpoint for
312
+ * a session's engine-status snapshot: without a real id there is nothing to key
313
+ * a stored snapshot by, so an agent stub answers undefined and the write site
314
+ * skips the persist instead of inventing a key.
315
+ */
316
+ export declare function sessionHeaderIdOf(agent: unknown): string | undefined;
308
317
  /** The tool-execution actor of one fs-intent event, when it carries an agent. */
309
318
  export declare function actorAgentOf(actor: object | undefined): unknown;
310
319
  /**
@@ -1,15 +1,15 @@
1
1
  import { type Context } from '@deepseek-ai/cordis';
2
2
  import { type UserMessage } from '@deepseek-ai/dsh-llm';
3
3
  import type { PreStepDecision } from '@deepseek-ai/dsh-agent';
4
- import type { MstarEngineStatusSource } from '../types.ts';
4
+ import type { MstarEngineStatusPayload } from '../types.ts';
5
5
  import { HarnessResolver } from './_shared.ts';
6
6
  /** Default catalog cache refresh interval (ms) — see Config `catalogTtlMs`. */
7
7
  export declare const DEFAULT_CATALOG_TTL_MS = 60000;
8
8
  /** Catalog cache key for the explicit-`harnessDir` app-wide entry (one entry for every session). */
9
9
  export declare const EXPLICIT_CACHE_KEY = "\0explicit";
10
- /** One TTL cache entry: the unified source plus the build timestamp. */
10
+ /** One TTL cache entry: the unified payload plus the build timestamp. */
11
11
  export interface CatalogCacheEntry {
12
- sources: MstarEngineStatusSource;
12
+ payload: MstarEngineStatusPayload;
13
13
  builtAt: number;
14
14
  }
15
15
  /**
@@ -27,7 +27,7 @@ export interface CatalogCacheEntry {
27
27
  export interface CatalogInvalidation {
28
28
  /**
29
29
  * Register `key` as the cache key of `harnessDir` — called by
30
- * `catalogSourcesFor` on cache hit AND build, and pre-registered by the
30
+ * `catalogPayloadFor` on cache hit AND build, and pre-registered by the
31
31
  * entry at apply for the explicit-config boot entry (a ledger record
32
32
  * between apply and the first pre-step must still invalidate the
33
33
  * pre-seeded entry). A null harness dir (no `{HARNESS_DIR}` resolved) has
@@ -47,15 +47,15 @@ export interface CatalogInvalidation {
47
47
  /** Create the apply-scoped invalidation bound to ONE catalog cache (entry-internal wiring — see {@link CatalogInvalidation}). */
48
48
  export declare function createCatalogInvalidation(cache: Map<string, CatalogCacheEntry>): CatalogInvalidation;
49
49
  /**
50
- * Build the unified catalog source for one harness dir (boot for the
50
+ * Build the unified catalog payload for one harness dir (boot for the
51
51
  * explicit config, first-use per workspace otherwise, then TTL-refreshed —
52
- * see `catalogSourcesFor`). Logs the manifest fallback once per build — a
52
+ * see `catalogPayloadFor`). Logs the manifest fallback once per build — a
53
53
  * '0.0.0' version would watermark every catalog row wrongly, so the
54
54
  * fallback is never silent.
55
55
  * @param ctx - registrant context (logger for the manifest fallback).
56
56
  * @param harnessDir - the resolved `{HARNESS_DIR}` (null when none found).
57
57
  */
58
- export declare function buildCatalogSources(ctx: Context, harnessDir: string | null): MstarEngineStatusSource;
58
+ export declare function buildCatalogPayload(ctx: Context, harnessDir: string | null): MstarEngineStatusPayload;
59
59
  /**
60
60
  * Advisory `agent/pre-step` waterfall listener (agent
61
61
  * catalog): delegates through `next()` (never `reject` — that would block the
@@ -35,7 +35,7 @@
35
35
  * compass soft/hard flip lands on the next assembly without
36
36
  * re-registration, in zero-config and explicit-config deployments alike.
37
37
  * - The context provider reuses the catalog's unified machine-summary
38
- * source (`buildCatalogSources` — the SAME builder the engine-status
38
+ * payload (`buildCatalogPayload` — the SAME builder the engine-status
39
39
  * pre-step catalog row uses) and projects the SLIM digest: the version watermark
40
40
  * ALWAYS, plus ONE `workflow … | plans: …` line only when the active set
41
41
  * selects a lifecycle (`state.selection.kind === 'active'`). Harness dir
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ import { DshHostAdapter } from './gates/adapter.ts';
16
16
  import type { DispatchGateAdvisory } from './gates/dispatch.ts';
17
17
  export { DshMstar } from './service.ts';
18
18
  export type { DshMstarOptions } from './service.ts';
19
- export type { MstarEngineStatusSource, MstarHarnessState, MstarIterationGateView, AgentFlowEventView, AgentFlowSummaryRow, AgentFlowView, WorkflowSelectionView, } from './types.ts';
19
+ export type { MstarEngineStatusSource, MstarEngineStatusPayload, MstarHarnessState, MstarIterationGateView, AgentFlowEventView, AgentFlowSummaryRow, AgentFlowView, WorkflowSelectionView, } from './types.ts';
20
20
  export { AGENT_FLOW_FILE, AGENT_FLOW_MAX_EVENTS, SETTLE_SEAM, readAgentFlow, recordDispatch, recordSettle, recordWorkflowVerdict, } from './gates/agent-flow.ts';
21
21
  export type { AgentFlowEvent, DispatchVerdict, SettleOutcome, WorkflowGateMode, WorkflowVerdict, WorkflowVerdictInput, } from './gates/agent-flow.ts';
22
22
  export { Config, HarnessResolver, skillLocalConfig } from './gates/_shared.ts';