@vostride/agent-qa-agent-local 0.2.2 → 0.2.4
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 +78 -0
- package/dist/index.cjs +452 -600
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +299 -1197
- package/dist/index.d.ts +299 -1197
- package/dist/index.js +401 -561
- package/dist/index.js.map +1 -1
- package/package.json +12 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { EvidenceBlobReaderPort, JobStorePort, ConfigReaderPort, JobModelCapability, StartedRun, ConfigFilesPortLike, ConfigValidatePortLike, ConfigScaffoldContentPortLike, FunctionDeps, CapabilityCatalogPort, LiveViewPort, RunDetailReaderPort, ClockPort, JobIdSource, JobKindRegistry, PostRunJobCapabilities, ReconcileStrategy, ChatLanguageModel, ChatTokenAccounting, FunctionRegistry, ChatStateSnapshot, AgentJobQueue, KnowledgeReaderPort, KnowledgeReviewPort, RunInvocationPort, RunsReaderPort, JobStoreFence, RecoverAbandonedClaimsOutcome, RunNextJobOutcome, PersistencePort } from '@vostride/agent-qa-agent';
|
|
2
2
|
import { TokenAccounting } from '@vostride/agent-qa-model';
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import * as _vostride_agent_qa_schema from '@vostride/agent-qa-schema';
|
|
4
|
+
import { ModelCapabilities, RecordedRetrievalRung, ScopeKey, RecordId, ReadTrace, RunEventEnvelope, RunsStartInput, RunSession, RunId, EvidenceBlobLookup, EvidenceBlobPresence, QuarantineAppliedEntry, RunNotification, ExecutionContext, FunctionCaller, MaskFn, FeedbackPort, FeedbackReadsPort, TestEditPatchSet, TestFileWrite, ChatSessionEvent, ArtifactRef, GateReceipt, GateReceiptRecordOutcome, PromotionOutcome, JobKind, MarkReceipt, MarkAddress, SessionLogPort, OpenedChatSession } from '@vostride/agent-qa-schema';
|
|
5
5
|
import { ScreenshotCompressorLogger } from '@vostride/agent-qa-runner-local';
|
|
6
|
-
export { BuildOrdinalReservationError, latestBuildOrdinal, reserveBuildOrdinalForProducts, resolveBuildTag } from '@vostride/agent-qa-runner-local';
|
|
7
|
-
import {
|
|
6
|
+
export { BuildOrdinalReservationError, HANDOFF_FILE, RUNS_SUBDIR, latestBuildOrdinal, loadCompletedRunHandoff, purgeActionCache, reserveBuildOrdinalForProducts, resolveBuildTag } from '@vostride/agent-qa-runner-local';
|
|
7
|
+
import { PlatformAdapter, Planner, Verifier, ActionPlanCache, WorkingMemoryPort, StorageStatePort, ScreenshotCompressor, KnowledgeHintReader, RecordLedger, ConfigDigests, MemberRunConfig, HookDefinition, SandboxRunnerOptions, SecretStore, SecretRedactorPort, MemberEventSink, EvidenceArtifactStorePort, PlannerConfig, LoopLogger, EventLogPort, HandoffStorePort, RunArtifactStorePort, PostVerdictPort, NonActionToolMap, MemberTestRunContext, TestResult, MemberTestExecutor, MemberTest, RunConfig } from '@vostride/agent-qa-runner';
|
|
8
8
|
export { BaselineProbeResult, ConfigDigests, MemberTestExecutor, PostVerdictOutcome, PostVerdictPort, PostVerdictStepInput, RunConfig, RunMemberDescriptor, mapVerdictToExitCode } from '@vostride/agent-qa-runner';
|
|
9
9
|
export { runSafetyScope } from '@vostride/agent-qa-safety-local';
|
|
10
10
|
import { planMarkEvidence, projectMarkEvidenceOutcome, canaryOutcomeObservationId } from '@vostride/agent-qa-knowledge-local/reader';
|
|
11
11
|
export { QUARANTINE_CLASS_DISPOSITIONS, QUARANTINE_FLOOR_ELIGIBILITY, QuarantineDisposition, QuarantineFloorEligibility } from '@vostride/agent-qa-knowledge-local/reader';
|
|
12
|
-
import { ExplicitReviewRequest,
|
|
12
|
+
import { ExplicitReviewRequest, ExplicitReviewDelegate, ServedRecordFacts, appendMarkEvidence, triageMark, servedIdsOn, procedureReadOn, applyFeedback, CreateLocalKnowledgeStoreConfig, openKnowledgeReader, drainQueue, foldRunOutcomes, reconcileRunOutcomesProjection, enqueueCurationCandidateProjection, readCanonicalBundleAnchors, RUN_OUTCOMES_PROJECTION_VERSION, acquireWriterLease, refreshWriterLeaseAuthority, releaseLease, rebuildIndex, purgeRecord, resolvePurgeAffectedSet, purgeAffectedSetFingerprint, rollbackCampaign, rollbackCurationJob, resolveRollbackAffectedSet, rollbackAffectedSetFingerprint, heartbeatLease, readWriterLease, isLeaseStale, deriveWriterLeaseFreshness, countPendingCurationJobs, countRemainingCurationWork, inspectDrainableCurationWork, listQueuedCandidates, acquireEmbedder, runMaintenanceTail, readEmbedderWorkerRegistration, embedderWorkerProcessIsAlive, embedderWorkerSocketPath, probeEmbedderWorkerSocket, verifyEmbedderWorkerIncarnation, resolveProcessIncarnation, EmbedderWorkerRegistration, removeEmbedderWorkerRegistration, classifyIndexFace, foldRetrievalRung, indexDbPath, resolveEmbedderCapability, EntityIndexSweepReport, ExplicitReviewResult } from '@vostride/agent-qa-knowledge-local';
|
|
13
13
|
export { AcquireEmbedderOutcome, AcquireWriterLeaseOutcome, ApplyFeedbackInput, AuthorOutcome, AuthoringTestRef, CurationCandidateProjection, CurationJobView, CurationProjectionArtifactSource, CuratorAuthor, DRAIN_BUDGET_MS, EMBEDDER_WORKER_REGISTRATION_FILE, EMBEDDER_WORKER_START_TIMEOUT_MS, EMBEDDER_WORKER_TERM_GRACE_MS, ENTITY_INDEX_SWEEP_INTERVAL_MS, EmbedderWorkerTimeoutError, EnqueueCurationCandidateProjectionOutcome, ExplicitReviewDelegate, ExplicitReviewDelegation, ExplicitReviewRequest, ExplicitReviewResult, HeartbeatLeaseOutcome, IndexFace, LeaseOperationOptions, MarkTriage, NeighborRecord, OpenServingKnowledgeReaderConfig, PurgeAffectedSet, PurgeReceipt, ReadEmbedderWorkerRegistrationOutcome, ReadWriterLeaseOutcome, RebuildReport, ReleaseLeaseOutcome, RollbackAffectedSet, RollbackCampaignInput, RollbackCurationJobInput, RollbackReport, ServedRecordFacts, WriterLease, WriterLeaseAuthority, WriterLeaseFreshness } from '@vostride/agent-qa-knowledge-local';
|
|
14
|
+
import { z } from 'zod';
|
|
14
15
|
|
|
15
16
|
/** Provisional share of usable model context reserved for the frozen Channel-1 brief. */
|
|
16
17
|
declare const BRIEF_FRACTION = 0.05;
|
|
@@ -44,78 +45,14 @@ interface ComputeKnowledgeBudgetsInput {
|
|
|
44
45
|
qaRulesTokens: number;
|
|
45
46
|
workingContextTokens: number;
|
|
46
47
|
}
|
|
47
|
-
/**
|
|
48
|
-
* Derive every learned-knowledge budget beside model token accounting. The raw fraction is
|
|
49
|
-
* floored before any floor/ceiling clamp, preserving D-02's exact boundary behavior. The reader
|
|
50
|
-
* and provider-neutral loop receive only the resulting plain numbers.
|
|
51
|
-
*/
|
|
52
48
|
declare function computeKnowledgeBudgets(input: ComputeKnowledgeBudgetsInput): KnowledgeBudgets;
|
|
53
|
-
/**
|
|
54
|
-
* Provisional D-09 predicate pinned by Phase 380 research. Channel 2 is absent when the model
|
|
55
|
-
* cannot call tools, is text-only, or has too little context; Channels 1 and 3 remain available.
|
|
56
|
-
*/
|
|
57
49
|
declare function memoryToolGate(capabilities: ModelCapabilities): boolean;
|
|
58
|
-
/** Apply D-17's weak-model cap reduction through the exact D-09 gate predicate. */
|
|
59
50
|
declare function scaledRecordCap(capabilities: ModelCapabilities): number;
|
|
60
51
|
|
|
61
|
-
/** Inputs the composition root resolves when opening the run-scoped knowledge reader. */
|
|
62
|
-
interface ConstructKnowledgeReaderInput {
|
|
63
|
-
resolveTrustPriors?: () => TrustPriorTable | undefined;
|
|
64
|
-
knowledgeRoot: string;
|
|
65
|
-
product?: string;
|
|
66
|
-
/** Known containing scopes for a member (the suite scope on prepared-suite runs). */
|
|
67
|
-
parentScopes?: readonly ScopeKey[];
|
|
68
|
-
asOfBuild: number;
|
|
69
|
-
recordCap: number;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Freeze Channel 1 at the composition root. The budget is deliberately absent from the key:
|
|
73
|
-
* budgets are run-fixed, while canonical `[tier,key]` material gives one immutable memo entry per
|
|
74
|
-
* scope. All other reader methods remain live pass-throughs for Channels 2, 3, and canary output.
|
|
75
|
-
*
|
|
76
|
-
* KREV-02 · D-13: the memo holds the WHOLE composite, so a repeat serve returns the trace captured
|
|
77
|
-
* at the moment the brief was actually assembled — not a fresh trace describing the cache hit.
|
|
78
|
-
* That is the deliberate choice and it is what makes the why-verb answer about *then*: a step that
|
|
79
|
-
* replans four times against one frozen brief was served that brief once, and the attribution that
|
|
80
|
-
* explains its lines is the one from that single serve. A "hit"-flavoured trace would describe the
|
|
81
|
-
* memo rather than the retrieval, and there would be no honest rank or score to put in it. The
|
|
82
|
-
* value type is written out rather than inferred so this stays a decision instead of a side effect
|
|
83
|
-
* of `ReturnType`; `knowledge-budgets.test.ts` pins that a repeat carries the original trace.
|
|
84
|
-
*/
|
|
85
|
-
declare function createFrozenKnowledgeReader(reader: KnowledgeHintReader): KnowledgeHintReader;
|
|
86
|
-
/**
|
|
87
|
-
* Construct the run-scoped reader through the physically read-only package subpath, then freeze
|
|
88
|
-
* its Channel-1 brief for the lifetime of the run.
|
|
89
|
-
*/
|
|
90
|
-
declare function constructKnowledgeReader(input: ConstructKnowledgeReaderInput): KnowledgeHintReader;
|
|
91
|
-
|
|
92
52
|
/** Mirror of schema's ExecutionContext union (safety-local's detectExecutionContext returns it). */
|
|
93
53
|
type RunExecutionContext = 'local-interactive' | 'local-headless' | 'ci' | 'cloud';
|
|
94
|
-
/**
|
|
95
|
-
* The provider-substrate model handle, named through the runner's own config rather than through
|
|
96
|
-
* the substrate package. It is the identical type — the runner types both model slots with it —
|
|
97
|
-
* and taking it this way keeps a provider-substrate edge off a package whose declared external
|
|
98
|
-
* dependency set is empty and whose whole point is that it installs nothing (JOBQ-02).
|
|
99
|
-
*/
|
|
100
54
|
type RunLanguageModel = MemberRunConfig['plannerModel'];
|
|
101
55
|
type KnowledgeAccounting = Pick<TokenAccounting, 'estimate' | 'getCeilings'>;
|
|
102
|
-
/**
|
|
103
|
-
* 407 D-13/D-17 — the shape of THE retrieval-rung resolver, declared structurally here and
|
|
104
|
-
* INJECTED rather than imported.
|
|
105
|
-
*
|
|
106
|
-
* knowledge-local's main entry has exactly ONE importer in this workspace by ratified rule
|
|
107
|
-
* (385 D-14/SC5, enforced at file granularity by `findKnowledgeWriterSingletonOffenders`), and
|
|
108
|
-
* that importer is `compose-local-agent.ts` — the local composition root. `resolveRetrievalRung`
|
|
109
|
-
* lives on the main entry deliberately (407-03: it opens an index probe and may load a model, so
|
|
110
|
-
* it is not `./reader` material), so naming it from this file would have made a second importer
|
|
111
|
-
* and quietly retired the invariant. The seam keeps the singleton intact while leaving exactly
|
|
112
|
-
* one implementation in the tree: `compose-local-agent.ts` re-exports the real resolver as
|
|
113
|
-
* `resolveHostRetrievalRung`, and both CLI doors pass THAT.
|
|
114
|
-
*
|
|
115
|
-
* It is REQUIRED, not optional-with-a-default. A default would be a second place the production
|
|
116
|
-
* resolver could be chosen from, and an omission at a new door would show up as a run with no
|
|
117
|
-
* rung — a banner that silently says nothing — rather than as a compile error.
|
|
118
|
-
*/
|
|
119
56
|
type RetrievalRungResolver = (options: {
|
|
120
57
|
knowledgeRoot: string;
|
|
121
58
|
agentQaRoot?: string;
|
|
@@ -123,13 +60,6 @@ type RetrievalRungResolver = (options: {
|
|
|
123
60
|
interface RunKnowledgeComposition {
|
|
124
61
|
reader: KnowledgeHintReader;
|
|
125
62
|
budgets: KnowledgeBudgets;
|
|
126
|
-
/**
|
|
127
|
-
* 407 D-13 — the HOST's retrieval ladder at THIS run's serve time, started here and awaited
|
|
128
|
-
* exactly once by the first step's evidence recorder. It is a promise rather than a value
|
|
129
|
-
* because the resolver's embedder probe can cost a model load, and overlapping that with run
|
|
130
|
-
* start keeps it off the critical path (T-407-16). Never re-probed per step: a run's rung is a
|
|
131
|
-
* fact about when it was served, not a live indicator of the machine.
|
|
132
|
-
*/
|
|
133
63
|
retrievalRung: Promise<RecordedRetrievalRung>;
|
|
134
64
|
recordLedger: RecordLedger;
|
|
135
65
|
nonActionTools?: NonActionToolMap;
|
|
@@ -137,7 +67,6 @@ interface RunKnowledgeComposition {
|
|
|
137
67
|
drainMemoryReadTraces?: () => ReadTrace[];
|
|
138
68
|
}
|
|
139
69
|
interface OpenRunKnowledgeCompositionInput {
|
|
140
|
-
resolveTrustPriors?: ConstructKnowledgeReaderInput['resolveTrustPriors'];
|
|
141
70
|
knowledgeRoot: string;
|
|
142
71
|
product?: string;
|
|
143
72
|
scope: ScopeKey;
|
|
@@ -148,17 +77,7 @@ interface OpenRunKnowledgeCompositionInput {
|
|
|
148
77
|
accounting: KnowledgeAccounting;
|
|
149
78
|
qaRulesText: string;
|
|
150
79
|
workingContextText: string;
|
|
151
|
-
/**
|
|
152
|
-
* 407 D-13 — the hosted runtime root (`<configDir>/.agent-qa`) the embedder probe discovers its
|
|
153
|
-
* worker under. Absent falls back to the acquirer's own rule, so a caller that does not know the
|
|
154
|
-
* root still gets an honest answer rather than an error.
|
|
155
|
-
*/
|
|
156
80
|
agentQaRoot?: string;
|
|
157
|
-
/**
|
|
158
|
-
* 407 D-17 — the injected rung resolver. Production callers pass `resolveHostRetrievalRung`
|
|
159
|
-
* (the composition root's binding of THE one knowledge-local resolver); tests pass a fake and
|
|
160
|
-
* never touch the host. See {@link RetrievalRungResolver} for why it is injected and required.
|
|
161
|
-
*/
|
|
162
81
|
resolveRetrievalRung: RetrievalRungResolver;
|
|
163
82
|
}
|
|
164
83
|
/**
|
|
@@ -174,86 +93,29 @@ interface RunDigestMemberInput {
|
|
|
174
93
|
testFileContent: string;
|
|
175
94
|
suiteFileContent?: string;
|
|
176
95
|
}
|
|
177
|
-
/**
|
|
178
|
-
* The per-member cache pair AND the run-level handoff pair, both produced by the SINGLE call
|
|
179
|
-
* below (D-20). The cache-key threading consumes `perMember[i]`; the handoff header carries
|
|
180
|
-
* `runLevel`. Because both draw from one mint, run identity and handoff identity cannot fork.
|
|
181
|
-
*/
|
|
182
96
|
interface RunConfigDigests {
|
|
183
97
|
runLevel: ConfigDigests;
|
|
184
98
|
perMember: ConfigDigests[];
|
|
185
99
|
}
|
|
186
|
-
/**
|
|
187
|
-
* Mint the run's config digests ONCE (D-20; RESEARCH A1 pinning).
|
|
188
|
-
*
|
|
189
|
-
* - Per-member cache pair:
|
|
190
|
-
* suiteConfigDigest = sha256hex16(configContent + '\n' + (suiteFileContent ?? ''))
|
|
191
|
-
* testConfigDigest = sha256hex16(testFileContent)
|
|
192
|
-
* - Run-level handoff pair:
|
|
193
|
-
* suiteConfigDigest = sha256hex16(ordered DISTINCT per-member suite digests joined by '\n')
|
|
194
|
-
* testConfigDigest = sha256hex16(ordered per-member test digests joined by '\n')
|
|
195
|
-
* A single-member run collapses the run-level pair to the member's values.
|
|
196
|
-
*
|
|
197
|
-
* Both consumers (per-member cache, run-level handoff) draw from this one call — identities
|
|
198
|
-
* cannot fork. This is the ONLY digest computation in the composition layer.
|
|
199
|
-
*/
|
|
200
100
|
declare function computeRunConfigDigests(input: {
|
|
201
101
|
configContent: string;
|
|
202
102
|
members: readonly RunDigestMemberInput[];
|
|
203
103
|
}): RunConfigDigests;
|
|
204
|
-
/**
|
|
205
|
-
* Resolve the run's execution context via safety-local's canonical `detectExecutionContext`
|
|
206
|
-
* (RESEARCH Q1.4 recommendation (a) — already tested; an explicit override wins). Carried into
|
|
207
|
-
* `RunConfig.executionContext` and the handoff header.
|
|
208
|
-
*/
|
|
209
104
|
declare function resolveRunExecutionContext(override?: RunExecutionContext): RunExecutionContext;
|
|
210
105
|
/** The durable run ports the shell wires behind `RunConfig.ports` (event log + handoff + artifact). */
|
|
211
106
|
interface RunPersistencePorts {
|
|
212
107
|
eventLog: EventLogPort;
|
|
213
108
|
handoffStore: HandoffStorePort;
|
|
214
109
|
runArtifactStore: RunArtifactStorePort;
|
|
215
|
-
/**
|
|
216
|
-
* CASS-02 run-scoped decision-screenshot store (Plan 13). Constructed once here from the SAME
|
|
217
|
-
* persistence root + runId as the other adapters; the shell hands this exact instance to every
|
|
218
|
-
* member so Plan 12's live-decision producer persists into one durable, run-addressable namespace.
|
|
219
|
-
*/
|
|
220
110
|
evidenceArtifacts: EvidenceArtifactStorePort;
|
|
221
|
-
/**
|
|
222
|
-
* 403-13 (WR-06, LIVE-03): where a live-frame VIEWER's fault is reported. Declared here as well
|
|
223
|
-
* as on the runner's `RunPorts`, because `assembleCliRun` spreads THIS interface into
|
|
224
|
-
* `RunConfig.ports` — a member declared on only one side is invisible in the type across that
|
|
225
|
-
* hop. Non-durable and off the bus by construction; the run's transcript never records a viewer.
|
|
226
|
-
*/
|
|
227
111
|
onSubscriberFault?: (code: string, message: string) => void;
|
|
228
|
-
/**
|
|
229
|
-
* 404-01 (D-05/D-10): the host-composed post-verdict step the shell awaits between `verdict` and
|
|
230
|
-
* `runFinished`. Declared here for the SAME reason `onSubscriberFault` is — `assembleCliRun`
|
|
231
|
-
* spreads THIS interface into `RunConfig.ports`, so a member declared on only one side of that
|
|
232
|
-
* hop is invisible in the type and would silently never reach `startRun`.
|
|
233
|
-
*
|
|
234
|
-
* It is NOT built by `buildRunPorts`: this package's runner seam names no queue and no writer
|
|
235
|
-
* lease, and inventing a second spelling of either here is what D-05 exists to prevent. The core
|
|
236
|
-
* threads whatever the HOST handed it (`RunInvocationCoreOptions.postVerdict`) and nothing else.
|
|
237
|
-
*/
|
|
238
112
|
postVerdict?: PostVerdictPort;
|
|
239
113
|
}
|
|
240
|
-
/**
|
|
241
|
-
* Construct the runner-local persistence ports rooted at the run's `.agent-qa` runtime dir (the
|
|
242
|
-
* FsActionCache rooting idiom). `FsEventLog`/`FsHandoffStore`/`FsRunArtifactStore`/
|
|
243
|
-
* `FsEvidenceArtifactStore` all write under the SAME `<configDir>/.agent-qa/runs/<slug(runId)>/…`
|
|
244
|
-
* family (D-08 — one self-contained run dir).
|
|
245
|
-
*/
|
|
246
114
|
declare function buildRunPorts(input: {
|
|
247
115
|
configDir: string;
|
|
248
116
|
runId: string;
|
|
249
117
|
}): RunPersistencePorts;
|
|
250
|
-
/**
|
|
251
|
-
* Construct the D-08/Q10 screenshot compressor at the composition root (sharp's host-adapter home).
|
|
252
|
-
* The runner-local `SharpScreenshotCompressor` is injected into every member's runner loop via
|
|
253
|
-
* `RunSuiteConfig.compressor` / `RunTestConfig.compressor` — core no longer constructs one.
|
|
254
|
-
*/
|
|
255
118
|
declare function buildScreenshotCompressor(logger?: ScreenshotCompressorLogger): ScreenshotCompressor;
|
|
256
|
-
/** Resolve D-16 build-tag precedence without reading ambient process state. */
|
|
257
119
|
declare function resolveBuildTagSetting(input: {
|
|
258
120
|
flag?: string;
|
|
259
121
|
env?: string;
|
|
@@ -261,42 +123,11 @@ declare function resolveBuildTagSetting(input: {
|
|
|
261
123
|
buildTag?: string;
|
|
262
124
|
};
|
|
263
125
|
}): string | undefined;
|
|
264
|
-
/**
|
|
265
|
-
* Advance the per-product buildOrdinal counter under the same `.agent-qa` root (D-18), then
|
|
266
|
-
* record D-14/D-16's first-seen tag mapping beside it when supplied. Both files are lock-free,
|
|
267
|
-
* best-effort runtime truth; the resolved ordinal rides `RunConfig.buildOrdinal` into the handoff.
|
|
268
|
-
*/
|
|
269
126
|
declare function resolveRunBuildOrdinal(input: {
|
|
270
127
|
configDir: string;
|
|
271
128
|
product: string;
|
|
272
129
|
buildTag?: string;
|
|
273
130
|
}): Promise<number>;
|
|
274
|
-
/**
|
|
275
|
-
* The ONE exclusive lane every suite member declares (402-02, D-09). The runner's bounded member
|
|
276
|
-
* pool never runs two members of the same lane concurrently, and the suite path needs that for two
|
|
277
|
-
* independent reasons, either of which alone would be sufficient:
|
|
278
|
-
*
|
|
279
|
-
* 1. Every member of a suite drives the ONE `PlatformAdapter` its suite set up — one browser, one
|
|
280
|
-
* page. Two members on it at once would interleave navigations and clicks on a shared surface.
|
|
281
|
-
* D-09 requires each concurrent member its own browser/CDP handle; the suite path does not
|
|
282
|
-
* supply that today, so it does not get concurrency today.
|
|
283
|
-
* 2. `createSuiteLifecycle` admits ONE ACTIVE SUITE at a time. Two suites live at once is a
|
|
284
|
-
* lifecycle violation, not a scheduling preference.
|
|
285
|
-
*
|
|
286
|
-
* A single lane string (rather than one lane per suite) is what encodes BOTH: it serializes within
|
|
287
|
-
* a suite and across suites. When a producer starts handing each member its own session AND the
|
|
288
|
-
* lifecycle admits concurrent suites, this becomes a per-suite key — or disappears — and the shell
|
|
289
|
-
* needs no argument re-litigated for that to be safe.
|
|
290
|
-
*
|
|
291
|
-
* STATUS 2026-08-24 (402-02): reason (2) is CLOSED — `createSuiteLifecycle` below is now a
|
|
292
|
-
* once-latch with member reference counting, so two members of one suite merge into one setup and
|
|
293
|
-
* a boundary crossed while members are live is a named error rather than a mid-flight teardown.
|
|
294
|
-
* Reason (1) is OPEN and is what still holds the lane: `suiteConfig.adapter` is per-SUITE, so
|
|
295
|
-
* within-suite concurrency would still put two tests on one browser page. Giving each suite member
|
|
296
|
-
* its own session is a change to what a suite MEANS (suite setup navigates once and members
|
|
297
|
-
* inherit that page state, per-test hooks run against it, auth state is captured from it) and is
|
|
298
|
-
* not this plan's to make. Do not drop this lane until that is decided.
|
|
299
|
-
*/
|
|
300
131
|
declare const SUITE_LIFECYCLE_LANE = "suite-lifecycle";
|
|
301
132
|
/** The setup/teardown pair a suite runs when it first becomes active / when it is torn down. */
|
|
302
133
|
interface SuiteLifecycleHooks {
|
|
@@ -305,22 +136,10 @@ interface SuiteLifecycleHooks {
|
|
|
305
136
|
/** Suite-level teardown: teardown hooks + auth-state capture (when all passed) + adapter.cleanup. */
|
|
306
137
|
teardown(): Promise<void>;
|
|
307
138
|
}
|
|
308
|
-
/**
|
|
309
|
-
* One member's hold on the active suite (402-02). Held from the moment `ensureReady` admits the
|
|
310
|
-
* member until the member settles; the suite cannot be torn down while any hold is outstanding.
|
|
311
|
-
*/
|
|
312
139
|
interface SuiteMemberLease {
|
|
313
140
|
/** Drop this member's hold. Idempotent — a double release never double-decrements. */
|
|
314
141
|
release(): void;
|
|
315
142
|
}
|
|
316
|
-
/**
|
|
317
|
-
* Thrown when `ensureReady` is asked for a suite while a DIFFERENT suite still has live members
|
|
318
|
-
* (402-02). This is the one-active-suite invariant made loud. The alternative — tearing the live
|
|
319
|
-
* suite down to make room — closes the browser out from under a test that is still running in it,
|
|
320
|
-
* and does so silently. The shell's exclusive lane (`SUITE_LIFECYCLE_LANE`) means no shipped
|
|
321
|
-
* composition can reach this, so it reads as an assertion rather than a runtime condition; that is
|
|
322
|
-
* exactly the point of naming it instead of assuming it.
|
|
323
|
-
*/
|
|
324
143
|
declare class SuiteBoundaryWhileLiveError extends Error {
|
|
325
144
|
readonly activeSuiteKey: string;
|
|
326
145
|
readonly requestedSuiteKey: string;
|
|
@@ -342,30 +161,6 @@ interface SuiteLifecycle {
|
|
|
342
161
|
/** Tear down the last active suite (if any). Called once at run end after `session.done`. */
|
|
343
162
|
finalize(): Promise<void>;
|
|
344
163
|
}
|
|
345
|
-
/**
|
|
346
|
-
* A lazy, CONCURRENCY-SAFE suite-lifecycle manager (the Q1.2 "pre/post-run composition" rows,
|
|
347
|
-
* redesigned for the 402-02 member pool). A wholly SKIPPED suite never sets up — the shell only
|
|
348
|
-
* invokes the executor (hence `ensureReady`) for non-skipped members, so a suite whose members are
|
|
349
|
-
* all fail-fast/cancel skips is never touched.
|
|
350
|
-
*
|
|
351
|
-
* WHAT CHANGED AND WHY. The pre-402 version read the active key, awaited `hooks.setup()`, and THEN
|
|
352
|
-
* assigned the key — three steps with awaits between them. Under a `for` loop that is fine because
|
|
353
|
-
* only one member is ever inside it. Under a pool, two members of one suite both observe "no active
|
|
354
|
-
* suite" and both run setup: two browsers for one suite, and the second teardown handle silently
|
|
355
|
-
* overwriting the first, so the first suite's browser is never closed. The fix is not a lock; it is
|
|
356
|
-
* to make the state transition SYNCHRONOUS and let the promise be the shared thing:
|
|
357
|
-
*
|
|
358
|
-
* - the once-latch: `activeKey`, `activeTeardown` and `activeSetup` are all assigned in the same
|
|
359
|
-
* synchronous region, BEFORE any await, so there is no window in which a second member can
|
|
360
|
-
* observe the pre-setup state. Every later member of the suite awaits `activeSetup` itself.
|
|
361
|
-
* - member reference counting: the count is incremented before awaiting setup, so a concurrent
|
|
362
|
-
* boundary crossing sees the hold. Teardown fires at a BOUNDARY (or at `finalize`) and only
|
|
363
|
-
* when the count is zero — never merely because it hit zero, which would tear the suite down
|
|
364
|
-
* and set it back up between every pair of members.
|
|
365
|
-
* - a failed setup poisons the suite: the rejected latch is kept and re-thrown to every later
|
|
366
|
-
* member, so setup is attempted exactly once and no member half-starts against a suite that
|
|
367
|
-
* never came up. Such a suite is never torn down — nothing came up to take down.
|
|
368
|
-
*/
|
|
369
164
|
declare function createSuiteLifecycle(): SuiteLifecycle;
|
|
370
165
|
/**
|
|
371
166
|
* One prepared suite member: its suite key + lifecycle hooks (setup runs on the first member of
|
|
@@ -376,32 +171,10 @@ declare function createSuiteLifecycle(): SuiteLifecycle;
|
|
|
376
171
|
interface SuiteMemberBinding {
|
|
377
172
|
suiteKey: string;
|
|
378
173
|
hooks: SuiteLifecycleHooks;
|
|
379
|
-
/**
|
|
380
|
-
* 403 D-05: the suite's ONE adapter, read only for its live-stream declaration. Present so the
|
|
381
|
-
* executor can register the capability AFTER `ensureReady` has resolved the suite's `setup()`
|
|
382
|
-
* (which is where `adapter.setup()` runs, so `this.page` exists) and BEFORE the first step.
|
|
383
|
-
*/
|
|
384
174
|
adapter?: PlatformAdapter;
|
|
385
175
|
run(ctx: MemberTestRunContext): Promise<TestResult>;
|
|
386
176
|
}
|
|
387
|
-
/**
|
|
388
|
-
* Declare (or withdraw) a member's live stream on the shell-provided context (403 D-05), by the one
|
|
389
|
-
* selection rule `liveStreamFor` (428 D-11/D-12). A continuous stream is registered with the
|
|
390
|
-
* labelled 1s snapshot producer over `screenshot()` as its fallback, which the hub starts when the
|
|
391
|
-
* stream fails to start. An adapter with no continuous stream but a `screenshot()` registers the
|
|
392
|
-
* snapshot producer itself; an adapter whose own stream is already a snapshot registers that alone;
|
|
393
|
-
* an adapter with neither registers `undefined` and its handle reads `{ kind: 'none' }`.
|
|
394
|
-
* The `ctx.registerLiveStream?.()` call is itself optional so a composition that predates the port
|
|
395
|
-
* is a no-op rather than a crash.
|
|
396
|
-
*/
|
|
397
177
|
declare function registerAdapterLiveStream(ctx: MemberTestRunContext, adapter: PlatformAdapter | undefined): void;
|
|
398
|
-
/**
|
|
399
|
-
* Build the injected `MemberTestExecutor` (D-01). Per member the closure looks up the prepared
|
|
400
|
-
* binding by the shell-derived `testIndex` (array position — authoritative), calls
|
|
401
|
-
* `lifecycle.ensureReady(...)` to lazily set up / cross-boundary tear down the member's suite,
|
|
402
|
-
* then runs the member behind `executeSuiteMember`. Wrapping ONE audited function instead of
|
|
403
|
-
* replicating the loop body.
|
|
404
|
-
*/
|
|
405
178
|
declare function buildSuiteMemberExecutor(input: {
|
|
406
179
|
lifecycle: SuiteLifecycle;
|
|
407
180
|
bindings: readonly SuiteMemberBinding[];
|
|
@@ -410,9 +183,6 @@ declare function buildSuiteMemberExecutor(input: {
|
|
|
410
183
|
* `filePath` is the member's own file. A suite-patched test carries no `url` (the suite owns nav), so
|
|
411
184
|
* `runMemberTest` skips the per-test navigate for suite members. */
|
|
412
185
|
declare function toMemberTest(test: any, filePath: string): MemberTest;
|
|
413
|
-
/** Everything both executor closures resolve at the composition root and hand to
|
|
414
|
-
* {@link buildMemberRunConfig}. The adapter-backed injected handlers are constructed here from
|
|
415
|
-
* `adapter` + `secretStore` so the two sites never drift (Pitfall 8). */
|
|
416
186
|
interface BuildMemberRunConfigInput {
|
|
417
187
|
adapter: PlatformAdapter;
|
|
418
188
|
planner: Planner;
|
|
@@ -422,7 +192,6 @@ interface BuildMemberRunConfigInput {
|
|
|
422
192
|
storageState?: StorageStatePort;
|
|
423
193
|
compressor?: ScreenshotCompressor;
|
|
424
194
|
knowledgeReader?: KnowledgeHintReader;
|
|
425
|
-
/** 407 D-13 — the composed rung, carried through untouched to the loop's evidence recorder. */
|
|
426
195
|
knowledgeRetrievalRung?: Promise<RecordedRetrievalRung>;
|
|
427
196
|
knowledgeBudgets?: KnowledgeBudgets;
|
|
428
197
|
knowledgeAsOfBuild?: number;
|
|
@@ -445,7 +214,6 @@ interface BuildMemberRunConfigInput {
|
|
|
445
214
|
sink: MemberEventSink;
|
|
446
215
|
testIndex: number;
|
|
447
216
|
abortSignal: AbortSignal;
|
|
448
|
-
/** CASS-02 run-scoped evidence store the shell threads onto the member ctx (Plan 13). */
|
|
449
217
|
evidenceArtifacts?: EvidenceArtifactStorePort;
|
|
450
218
|
captureScreenshots?: boolean;
|
|
451
219
|
accessibility?: MemberRunConfig['accessibility'];
|
|
@@ -470,11 +238,6 @@ interface BuildMemberRunConfigInput {
|
|
|
470
238
|
/** The member's own file, for the core-parity fileUpload path resolver. */
|
|
471
239
|
filePath: string;
|
|
472
240
|
}
|
|
473
|
-
/**
|
|
474
|
-
* Assemble the {@link MemberRunConfig} `runMemberTest` slots behind, wiring the adapter-backed
|
|
475
|
-
* injected handlers (runJS/appium/a11y/failure-shot), the store-neutral secret resolver, and the
|
|
476
|
-
* fileUpload path resolver — reproducing core's `runTest` per-test behavior on runner soil (D-05).
|
|
477
|
-
*/
|
|
478
241
|
declare function buildMemberRunConfig(input: BuildMemberRunConfigInput): MemberRunConfig;
|
|
479
242
|
|
|
480
243
|
/** A bus subscriber a host attaches: an envelope `handler` plus an optional post-run `flush`. */
|
|
@@ -487,176 +250,44 @@ interface AttachableRunSession {
|
|
|
487
250
|
subscribe(fromSeq: number | undefined, handler: (envelope: RunEventEnvelope) => void): () => void;
|
|
488
251
|
}
|
|
489
252
|
|
|
490
|
-
/**
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
*/
|
|
499
|
-
type RunTargetClass = 'local' | 'shared' | 'production' | undefined;
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* The request fields this seam refuses, and the reason is not the one the CLI host had.
|
|
503
|
-
*
|
|
504
|
-
* `createCliRunExecution` refused these because the `run` COMMAND had no argv to express them
|
|
505
|
-
* (`local-agent-host.ts`). This core can express both — and honouring either would be the defect
|
|
506
|
-
* RESEARCH Pitfall 7 names:
|
|
507
|
-
*
|
|
508
|
-
* `executionContext` — the context a run records comes from the composition that owns the door
|
|
509
|
-
* (D-07) and from nowhere else. The FIELD survives on the contract as the label a run RECORDS,
|
|
510
|
-
* and it is refused here until some door has a use for recording a label that differs from the
|
|
511
|
-
* context it was started in.
|
|
512
|
-
*
|
|
513
|
-
* `scope` — resolves from the config's own target/product resolution. Accepting an override
|
|
514
|
-
* would let a caller address one product's run ledger while running another's.
|
|
515
|
-
*
|
|
516
|
-
* Read OFF the request rather than enumerated positively, so a field added to `RunsStartInput`
|
|
517
|
-
* with no plan for carrying it shows up here as a refusal instead of as a silent drop.
|
|
518
|
-
*/
|
|
519
|
-
declare const REFUSED_RUN_REQUEST_FIELDS: readonly ["scope", "executionContext"];
|
|
520
|
-
/**
|
|
521
|
-
* The request named a field this seam refuses, so the request is refused rather than reshaped.
|
|
522
|
-
*
|
|
523
|
-
* The successor to `UnsupportedRunRequestError` (cli `local-agent-host.ts`), which dies with the
|
|
524
|
-
* spawn port in 401-05. Same class of refusal, different rationale: that one could not express the
|
|
525
|
-
* fields, this one declines to.
|
|
526
|
-
*/
|
|
527
|
-
declare class RunRequestFieldRefusedError extends Error {
|
|
528
|
-
readonly refusedFields: readonly string[];
|
|
529
|
-
constructor(refusedFields: readonly string[]);
|
|
253
|
+
/** Inputs the composition root resolves when opening the run-scoped knowledge reader. */
|
|
254
|
+
interface ConstructKnowledgeReaderInput {
|
|
255
|
+
knowledgeRoot: string;
|
|
256
|
+
product?: string;
|
|
257
|
+
/** Known containing scopes for a member (the suite scope on prepared-suite runs). */
|
|
258
|
+
parentScopes?: readonly ScopeKey[];
|
|
259
|
+
asOfBuild: number;
|
|
260
|
+
recordCap: number;
|
|
530
261
|
}
|
|
262
|
+
declare function createFrozenKnowledgeReader(reader: KnowledgeHintReader): KnowledgeHintReader;
|
|
531
263
|
/**
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
* A DECISION, NOT A FAULT, and it joins `RunRequestFieldRefusedError` under the same rule: the
|
|
535
|
-
* caller asked for something this seam declines, and says so by name before anything happens.
|
|
536
|
-
*
|
|
537
|
-
* WHY IT IS ASKED HERE AND NOT IN THE SCHEMA. `packages/schema` owns PATH-SAFETY on the id — the
|
|
538
|
-
* id becomes a directory name and that is judgeable with no dependencies — but it may not name
|
|
539
|
-
* `@vostride/agent-qa-ids` and must not re-spell the canonical id shape. So "is this an id this
|
|
540
|
-
* system would have minted" is asked here, through a predicate supplied beside `mintRunId` and for
|
|
541
|
-
* `mintRunId`'s stated reason: a locally invented answer would be a second spelling of a run's
|
|
542
|
-
* identity. Measured pre-fix: `runId: 'not-a-minted-id'` was acknowledged, and `runId: ''` ran a
|
|
543
|
-
* whole run into a shared `runs/default/` directory before the op reported `RunNotRecordedError`.
|
|
264
|
+
* Construct the run-scoped reader through the physically read-only package subpath, then freeze
|
|
265
|
+
* its Channel-1 brief for the lifetime of the run.
|
|
544
266
|
*/
|
|
267
|
+
declare function constructKnowledgeReader(input: ConstructKnowledgeReaderInput): KnowledgeHintReader;
|
|
268
|
+
|
|
545
269
|
declare class RunIdNotMintedError extends Error {
|
|
546
270
|
readonly runId: string;
|
|
547
271
|
constructor(runId: string);
|
|
548
272
|
}
|
|
549
|
-
/**
|
|
550
|
-
* The request named a run id that already belongs to a run (2026-08-23, 401-20 · CR-04).
|
|
551
|
-
*
|
|
552
|
-
* WHAT A COLLISION COSTS, measured rather than reasoned about. Pre-fix, a second `runs.start`
|
|
553
|
-
* naming a completed run's id APPENDED seven more envelopes to that run's `events.jsonl`
|
|
554
|
-
* (2111 → 4221 bytes), OVERWROTE its `handoff.json`, and added a second row to its
|
|
555
|
-
* `execution_audit.jsonl` — and then acknowledged the caller with the victim's own id. The
|
|
556
|
-
* acknowledgment law makes that worse rather than better: `runs.start` reads every ack field back
|
|
557
|
-
* off the run's durable record specifically so a host cannot fabricate one, and a colliding id
|
|
558
|
-
* satisfies that read with a PRIOR run's record. So the refusal has to land before the record is
|
|
559
|
-
* touched at all — which is why it sits in the identity step, above assembly.
|
|
560
|
-
*
|
|
561
|
-
* THE TEST IS THE RUN'S OWN DIRECTORY, derived through `runDirFor` — the same composition the
|
|
562
|
-
* run's ports use — because every artifact a collision could tamper with lives inside it.
|
|
563
|
-
* Asking after `handoff.json` alone would let a run that crashed before writing one be silently
|
|
564
|
-
* appended to.
|
|
565
|
-
*/
|
|
566
273
|
declare class RunIdAlreadyInUseError extends Error {
|
|
567
274
|
readonly runId: string;
|
|
568
275
|
constructor(runId: string);
|
|
569
276
|
}
|
|
570
|
-
/**
|
|
571
|
-
* This run was refused before it started.
|
|
572
|
-
*
|
|
573
|
-
* Since 432-13 the one producer is the production refusal (`refuseProductionWithoutOptIn`): its
|
|
574
|
-
* reason is the plain sentence naming the target and the config line. 2026-10-01 (432-19, D-15):
|
|
575
|
-
* it carries no remedy list, because the remedy vocabulary left with the execution gate.
|
|
576
|
-
* `neutralReason` is the same sentence; the dashboard and run-service doors read that member to
|
|
577
|
-
* tell a run denial from any other rejection, and a door renders it and never composes its own.
|
|
578
|
-
*/
|
|
579
|
-
declare class RunDeniedError extends Error {
|
|
580
|
-
readonly runId: string;
|
|
581
|
-
readonly reason: string;
|
|
582
|
-
readonly neutralReason: string;
|
|
583
|
-
constructor(runId: string, reason: string);
|
|
584
|
-
}
|
|
585
|
-
/**
|
|
586
|
-
* What one resolution of this request's targets answers (401-14).
|
|
587
|
-
*
|
|
588
|
-
* THE CLASS AND THE NAMES COME BACK TOGETHER because they are two renderings of ONE pass over the
|
|
589
|
-
* run's members: `targetClass` is the most-restrictive fold over them, `targetNames` the declared
|
|
590
|
-
* names of the members it folded over. A door that answered them from two passes could refuse on
|
|
591
|
-
* one reading of the config while the run it describes came from another.
|
|
592
|
-
*/
|
|
593
|
-
interface RunTargetDeclaration {
|
|
594
|
-
/** The DECLARED class of the run's members — a config read, never a probe (D-06). */
|
|
595
|
-
readonly targetClass: RunTargetClass;
|
|
596
|
-
/**
|
|
597
|
-
* The distinct declared target names, in first-appearance member order.
|
|
598
|
-
*
|
|
599
|
-
* DISPLAY-ONLY (T-401-G3b). Members that declare no target contribute nothing, which is how an
|
|
600
|
-
* all-undeclared run arrives here as an empty list rather than as a list of invented names.
|
|
601
|
-
*/
|
|
602
|
-
readonly targetNames: readonly string[];
|
|
603
|
-
/**
|
|
604
|
-
* The members' targets DECLARED `environment: production`, in first-appearance member order
|
|
605
|
-
* (432-03, D-18). Repeats are allowed; the refusal names each target once.
|
|
606
|
-
*
|
|
607
|
-
* REQUIRED, so a door that forgets it does not compile. It comes from the SAME resolution as
|
|
608
|
-
* `targetClass` and `targetNames`, which is what keeps a mixed run from hiding a production member
|
|
609
|
-
* behind its siblings.
|
|
610
|
-
*/
|
|
611
|
-
readonly productionTargetNames: readonly string[];
|
|
612
|
-
/**
|
|
613
|
-
* The config's top-level `allowProduction`, read from the same config the targets resolved
|
|
614
|
-
* against. Only the literal `true` opts in; absence and `false` do not. No request field and no
|
|
615
|
-
* CLI flag reaches this.
|
|
616
|
-
*/
|
|
617
|
-
readonly allowProduction?: boolean;
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
* Refuse a run that drives a production target the config has not opted into (432-03, D-18).
|
|
621
|
-
*
|
|
622
|
-
* A production CLASS with no names still refuses, so a producer that folded the class but lost the
|
|
623
|
-
* names fails closed. The refusal is a plain `RunDeniedError` carrying the sentence from
|
|
624
|
-
* `buildProductionRefusal`.
|
|
625
|
-
*
|
|
626
|
-
* EXPORTED because a producer that must acquire a device or an adapter before the core runs (the
|
|
627
|
-
* suite half) calls it first, so production is refused before that acquisition too.
|
|
628
|
-
*/
|
|
629
|
-
declare function refuseProductionWithoutOptIn(runId: string, declaration: Pick<RunTargetDeclaration, 'productionTargetNames' | 'allowProduction'> & {
|
|
630
|
-
readonly targetClass?: RunTargetClass;
|
|
631
|
-
}): void;
|
|
632
|
-
/**
|
|
633
|
-
* The identity refusals, asked against the run's own directory (401-20, CR-04).
|
|
634
|
-
*
|
|
635
|
-
* EXPORTED for the same producers `refuseProductionWithoutOptIn` is: a door that refuses production
|
|
636
|
-
* ahead of the core asks these first, so a duplicate or unminted id keeps its own refusal on every
|
|
637
|
-
* path.
|
|
638
|
-
*/
|
|
639
|
-
declare function refuseUnavailableRunId(input: {
|
|
640
|
-
readonly configDir: string;
|
|
641
|
-
readonly runId: string;
|
|
642
|
-
readonly isMintedRunId: (value: string) => boolean;
|
|
643
|
-
}): void;
|
|
644
277
|
/** What the assembler is handed: everything the core resolved, and nothing it did not. */
|
|
645
278
|
interface RunAssemblyContext {
|
|
646
279
|
/** The run's identity, already resolved. The core starts the run under THIS id and no other. */
|
|
647
280
|
readonly runId: string;
|
|
648
|
-
/** The caller's request,
|
|
281
|
+
/** The caller's request, its run id already checked. */
|
|
649
282
|
readonly request: RunsStartInput;
|
|
650
283
|
/** The context the door carried — the same value, so a run cannot record a different one. */
|
|
651
284
|
readonly executionContext: RunExecutionContext;
|
|
652
|
-
/** The durable ports, rooted at `<configDir>/.agent-qa
|
|
285
|
+
/** The durable ports, rooted at `<configDir>/.agent-qa`, the evidence check's root. */
|
|
653
286
|
readonly ports: RunPersistencePorts;
|
|
654
287
|
/** `dirname(agentQaRoot)` — the project directory the config sits in. */
|
|
655
288
|
readonly configDir: string;
|
|
656
289
|
/** The config file this run resolves against (request override honoured). */
|
|
657
290
|
readonly configPath: string;
|
|
658
|
-
/** The declared class the door resolved. Handed over so an assembler need not re-resolve it. */
|
|
659
|
-
readonly targetClass: RunTargetClass;
|
|
660
291
|
}
|
|
661
292
|
/**
|
|
662
293
|
* Build the `RunConfig` the runner shell starts.
|
|
@@ -677,29 +308,7 @@ interface RunInvocationCoreOptions {
|
|
|
677
308
|
readonly configPath: string;
|
|
678
309
|
/** The project's runtime root, i.e. `<configDir>/.agent-qa`. */
|
|
679
310
|
readonly agentQaRoot: string;
|
|
680
|
-
/**
|
|
681
|
-
* The context this door's runs are started in and record (D-07).
|
|
682
|
-
*
|
|
683
|
-
* CALLER-RESOLVED, NEVER SNIFFED. The CLI resolves its TTY posture, the daemon carries
|
|
684
|
-
* `local-headless`, CI passes its own. A core that detected this itself would be answering a
|
|
685
|
-
* question about the machine when the question is about the door.
|
|
686
|
-
*/
|
|
687
311
|
readonly executionContext: RunExecutionContext;
|
|
688
|
-
/**
|
|
689
|
-
* Resolve what this request's targets DECLARE (D-06; names added 401-14).
|
|
690
|
-
*
|
|
691
|
-
* INJECTED BECAUSE THE CONFIG LIVES BEHIND THE DOOR, not because any of it is negotiable. Target
|
|
692
|
-
* resolution needs the CLI's `resolveTarget`/`AgentQaConfig` vocabulary, which this package may
|
|
693
|
-
* not name. `undefined` is undeclared, which is not production.
|
|
694
|
-
*
|
|
695
|
-
* ONE RESOLUTION, ALL FIELDS, AND THAT IS THE POINT OF THE SHAPE. The class, the names, the
|
|
696
|
-
* production members and the opt-in come back from one pass, so the production refusal is asked
|
|
697
|
-
* about the members the run will actually drive.
|
|
698
|
-
*
|
|
699
|
-
* Must not touch the target, and must not probe. A resolver that read a URL would put a network
|
|
700
|
-
* call before the production refusal, which is the one ordering this file exists to hold.
|
|
701
|
-
*/
|
|
702
|
-
readonly resolveTargetDeclaration: (request: RunsStartInput) => RunTargetDeclaration | Promise<RunTargetDeclaration>;
|
|
703
312
|
/** Build the `RunConfig`. Called ONLY once every refusal has passed. */
|
|
704
313
|
readonly assembleRun: RunAssembler;
|
|
705
314
|
/**
|
|
@@ -710,62 +319,18 @@ interface RunInvocationCoreOptions {
|
|
|
710
319
|
* spelling of a run's identity. Every shipped door already holds `generateRunId`.
|
|
711
320
|
*/
|
|
712
321
|
readonly mintRunId: () => string;
|
|
713
|
-
/**
|
|
714
|
-
* Is this a run id this system would have minted? (2026-08-23, 401-20 · CR-04)
|
|
715
|
-
*
|
|
716
|
-
* REQUIRED, WITH NO DEFAULT AND NO FALLBACK, for exactly `mintRunId`'s reason and one more. The
|
|
717
|
-
* canonical predicate lives in `@vostride/agent-qa-ids`, which this package does not depend on,
|
|
718
|
-
* and a locally invented shape check would be a second spelling of a run's identity — the same
|
|
719
|
-
* argument that made minting an option. The extra reason is that an OPTIONAL predicate with a
|
|
720
|
-
* permissive fallback is this defect wearing a type: every composition that forgot it would be
|
|
721
|
-
* back to accepting any string, and the build would say nothing. A composition that omits this
|
|
722
|
-
* does not compile.
|
|
723
|
-
*
|
|
724
|
-
* It answers about the SHAPE only. Whether the id is free is this file's own question, asked
|
|
725
|
-
* against the run's own directory.
|
|
726
|
-
*/
|
|
727
322
|
readonly isMintedRunId: (value: string) => boolean;
|
|
728
|
-
/**
|
|
729
|
-
* Notified with the started session, synchronously, before the core awaits it (D-09's bridge
|
|
730
|
-
* hook). Subscribers attach here; the bus replays from seq 1, so nothing is missed.
|
|
731
|
-
*/
|
|
732
323
|
readonly onSession?: (session: RunSession) => void;
|
|
733
|
-
/**
|
|
734
|
-
* Build this run's post-verdict step (404 D-05/D-10) — the durable `analyze-run` enqueue plus
|
|
735
|
-
* ONE writer-lease consult, awaited by the shell between `verdict` and `runFinished`, whose
|
|
736
|
-
* answer becomes `runFinished.disposition`.
|
|
737
|
-
*
|
|
738
|
-
* HOST-COMPOSED, CORE-THREADED, and both halves are load-bearing. It is host-composed because
|
|
739
|
-
* the step speaks queue and writer-lease vocabulary this package's runner seam may not name —
|
|
740
|
-
* the same argument that made `mintRunId` an option rather than a local. It is threaded HERE
|
|
741
|
-
* rather than left to each door because the enqueue is precisely what the `runs.start` door and
|
|
742
|
-
* the daemon door forgot: a door that supplies no factory gets a run whose wire honestly reads
|
|
743
|
-
* `detached`, and a door that supplies one cannot then forget to wire it in.
|
|
744
|
-
*
|
|
745
|
-
* Called ONCE per run, after every refusal has passed and the persistence ports exist, so a
|
|
746
|
-
* refused run never composes one. Absent ⇒ no `postVerdict` member reaches `RunConfig.ports` at all
|
|
747
|
-
* (conditional spread, never an `undefined` field), and the shell reports `detached` with no
|
|
748
|
-
* warning — which is the truth about a host from which nothing will be drained.
|
|
749
|
-
*/
|
|
750
324
|
readonly postVerdict?: (input: {
|
|
751
325
|
readonly runId: string;
|
|
752
326
|
readonly configDir: string;
|
|
753
327
|
}) => PostVerdictPort;
|
|
754
|
-
/**
|
|
328
|
+
/**
|
|
329
|
+
* The door's own code, awaited once the request and its run id are allowed and before any port.
|
|
330
|
+
* A door opens its run record and loads its plugins here.
|
|
331
|
+
*/
|
|
755
332
|
readonly afterRefusal?: () => Promise<void>;
|
|
756
333
|
}
|
|
757
|
-
/**
|
|
758
|
-
* The one in-process run execution core.
|
|
759
|
-
*
|
|
760
|
-
* Returns a `RunExecutionPort` (the shape `createLocalRunInvocation` binds `runs.start` over), so
|
|
761
|
-
* the op's evidence check — read the run's own event log back, refuse an empty one — applies to
|
|
762
|
-
* this seam unchanged.
|
|
763
|
-
*
|
|
764
|
-
* NO DEFENSIVE CATCH ANYWHERE (D-03). A run that crashes hard takes its host with it, on purpose:
|
|
765
|
-
* crash-through surfaces bugs instead of absorbing them, and the runner's budget/abort machinery
|
|
766
|
-
* is the orderly containment. The only `throw`s this file introduces are the two refusals above,
|
|
767
|
-
* which are decisions rather than faults.
|
|
768
|
-
*/
|
|
769
334
|
declare function createRunInvocationCore(options: RunInvocationCoreOptions): {
|
|
770
335
|
execute(request: RunsStartInput): Promise<{
|
|
771
336
|
runId: RunId;
|
|
@@ -777,27 +342,7 @@ interface CreateEvidenceBlobReaderInput {
|
|
|
777
342
|
readonly agentQaRoot: string;
|
|
778
343
|
}
|
|
779
344
|
declare function lookupEvidenceBlob(input: CreateEvidenceBlobReaderInput, runId: string, sha: string): EvidenceBlobLookup;
|
|
780
|
-
/**
|
|
781
|
-
* THE SAME RULE, MINUS THE BYTES (Phase 406, D-17) — presence for a whole run's artifact refs.
|
|
782
|
-
*
|
|
783
|
-
* WHY NOT `lookupEvidenceBlob(...).status`: a run page annotates every ref it is about to render,
|
|
784
|
-
* and the read arm loads a screenshot into memory to reach the status it then discards. This
|
|
785
|
-
* shaping walks the identical three-way split — malformed sha, unknown run, then the store's own
|
|
786
|
-
* answer — and asks the store to STAT instead of read. The two arms above `runDirectoryExists`
|
|
787
|
-
* are shared code, not a copy, so `found` here and `found` there are the same claim.
|
|
788
|
-
*/
|
|
789
345
|
declare function statEvidenceBlob(input: CreateEvidenceBlobReaderInput, runId: string, sha: string): EvidenceBlobPresence;
|
|
790
|
-
/**
|
|
791
|
-
* The op's PORT over {@link lookupEvidenceBlob}.
|
|
792
|
-
*
|
|
793
|
-
* BOTH MEMBERS ARE BOUND HERE (406, D-17): this host holds run directories, so it can honestly
|
|
794
|
-
* answer the optional presence member, and an op reading it gets `present` for every ref rather
|
|
795
|
-
* than the omitted key a host without local storage would leave.
|
|
796
|
-
*
|
|
797
|
-
* ASYNC EVEN THOUGH THE STORE IS NOT, because the port is the shape a host that does not hold its
|
|
798
|
-
* blobs on a local disk would also have to satisfy — and a synchronous contract is one such a host
|
|
799
|
-
* could never implement without lying about it. The local answer is simply already resolved.
|
|
800
|
-
*/
|
|
801
346
|
declare function createEvidenceBlobReader(input: CreateEvidenceBlobReaderInput): EvidenceBlobReaderPort;
|
|
802
347
|
/**
|
|
803
348
|
* The analysis job's shaping: the bytes, or nothing, with the two absences collapsed.
|
|
@@ -817,18 +362,6 @@ interface RunQuarantineSnapshotInput {
|
|
|
817
362
|
now: string;
|
|
818
363
|
warn?: (message: string) => void;
|
|
819
364
|
}
|
|
820
|
-
/**
|
|
821
|
-
* Resolve the entries this run will apply: active (`'quarantined'`) and belonging to this run's
|
|
822
|
-
* product. Expired entries are deliberately EXCLUDED — a lapsed entry's test fails builds again
|
|
823
|
-
* (D-11) — and released entries are gone.
|
|
824
|
-
*
|
|
825
|
-
* Measured consequence worth knowing at THIS seam, because this is where the exclusion is decided:
|
|
826
|
-
* for a test still crossing the threshold that is exactly ONE red build. The snapshot below is
|
|
827
|
-
* taken at run start (entry lapsed ⇒ not applied ⇒ red), and that same run's post-run fold
|
|
828
|
-
* re-enters it with a fresh full-lifetime deadline before the next run takes its own snapshot. No
|
|
829
|
-
* human is scheduled into that loop at any point, and nothing bounds the repetition
|
|
830
|
-
* (measured 2026-08-06).
|
|
831
|
-
*/
|
|
832
365
|
declare function resolveRunQuarantineSnapshot(input: RunQuarantineSnapshotInput): readonly QuarantineAppliedEntry[];
|
|
833
366
|
|
|
834
367
|
/**
|
|
@@ -857,7 +390,7 @@ interface LogicalDump {
|
|
|
857
390
|
readonly checkpoints: readonly LogicalDumpCheckpoint[];
|
|
858
391
|
}
|
|
859
392
|
|
|
860
|
-
/** One chain-terminal notification row, with its payload guarded on the way out
|
|
393
|
+
/** One chain-terminal notification row, with its payload guarded on the way out. */
|
|
861
394
|
interface JobStoreNotification {
|
|
862
395
|
readonly runId: string;
|
|
863
396
|
readonly payload: RunNotification;
|
|
@@ -865,68 +398,13 @@ interface JobStoreNotification {
|
|
|
865
398
|
}
|
|
866
399
|
interface SqliteJobStore extends JobStorePort {
|
|
867
400
|
close(): void;
|
|
868
|
-
/**
|
|
869
|
-
* The chain-terminal notifications this database holds, ordered by run.
|
|
870
|
-
*
|
|
871
|
-
* On the implementation rather than the neutral port, beside `logicalDump`, and for the
|
|
872
|
-
* same reason: the port is the ENGINE's vocabulary and the engine never reads a
|
|
873
|
-
* notification — it writes one, once, as part of ending a job. Every reader of these rows
|
|
874
|
-
* is a surface, and 388 D-14 routes surfaces through the function layer, not through here.
|
|
875
|
-
*
|
|
876
|
-
* The payload is parsed through the schema guard rather than handed back as text: the
|
|
877
|
-
* column is bytes another build could have written, and a row that lost a stage cannot be
|
|
878
|
-
* allowed to travel as a `RunNotification`.
|
|
879
|
-
*/
|
|
880
401
|
listNotifications(): Promise<readonly JobStoreNotification[]>;
|
|
881
|
-
/**
|
|
882
|
-
* The D-03 comparison basis, in full: every table this database holds plus a digest per
|
|
883
|
-
* checkpoint file.
|
|
884
|
-
*
|
|
885
|
-
* Kept beside `dumpState()` rather than replacing it, because the two answer different
|
|
886
|
-
* questions and collapsing them would weaken both. `dumpState()` is the typed, engine-facing
|
|
887
|
-
* projection of the job rows and it is part of the neutral port. This one is the storage
|
|
888
|
-
* implementation's own full-state instrument: it knows about the checkpoint directory and
|
|
889
|
-
* about tables the port has no vocabulary for, and it is the thing a crash comparison holds
|
|
890
|
-
* up against another run.
|
|
891
|
-
*/
|
|
892
402
|
logicalDump(): Promise<LogicalDump>;
|
|
893
403
|
/** The same dump as one comparable string. Byte equality here is state equality. */
|
|
894
404
|
dumpLogicalState(): Promise<string>;
|
|
895
405
|
}
|
|
896
406
|
|
|
897
|
-
/**
|
|
898
|
-
* 407 D-13/D-17 — THE retrieval-rung resolver, bound at the one edge that may name the writer
|
|
899
|
-
* entry (385 D-14/SC5) and handed to `openRunKnowledgeComposition` by every run door.
|
|
900
|
-
*
|
|
901
|
-
* The binding exists so there is exactly ONE resolver in the tree with exactly ONE importer of
|
|
902
|
-
* the package that owns it. `run-composition.ts` declares the seam's shape structurally and takes
|
|
903
|
-
* the function as a required input rather than importing it — naming knowledge-local's main entry
|
|
904
|
-
* from a second file would retire the singleton the arch gate enforces, and the fix would look
|
|
905
|
-
* like relaxing the gate.
|
|
906
|
-
*
|
|
907
|
-
* Typed as {@link RetrievalRungResolver} rather than by its own signature, so the pass-through
|
|
908
|
-
* that reaches the CLI is the narrow two-root contract the doors actually use — the embedder
|
|
909
|
-
* `probes` seam and the preferred profile stay knowledge-local's business.
|
|
910
|
-
*/
|
|
911
407
|
declare const resolveHostRetrievalRung: RetrievalRungResolver;
|
|
912
|
-
/**
|
|
913
|
-
* 407 D-18/D-20 — the READ-ONLY knowledge probes a diagnostic grades a host with.
|
|
914
|
-
*
|
|
915
|
-
* `doctor` needs the two axes SEPARATELY, not just the folded word: its `Knowledge store` row is
|
|
916
|
-
* about the index face, its `Embedder` row is about the capability outcome, and only its third row
|
|
917
|
-
* is the fold. {@link resolveHostRetrievalRung} above hands back the fold alone, so a surface that
|
|
918
|
-
* had only that would have to re-derive the other two — which is a second fold in everything but
|
|
919
|
-
* name, and exactly what D-17's one-resolver rule exists to prevent.
|
|
920
|
-
*
|
|
921
|
-
* Published as its own frozen table rather than folded into {@link LOCAL_DAEMON_CAPABILITIES}
|
|
922
|
-
* because every member here is a READ. Nothing in it acquires a lease, spawns a worker, downloads
|
|
923
|
-
* an artifact or writes to the knowledge root, and a caller that holds this object cannot mutate
|
|
924
|
-
* the thing it is reporting on. That is the whole mitigation for T-407-19: the boundary is the
|
|
925
|
-
* shape of the capability, not a promise in a doc comment at the call site.
|
|
926
|
-
*
|
|
927
|
-
* `foldRetrievalRung` rides along for the same reason the resolver does — one fold table in one
|
|
928
|
-
* package, reached through the one edge that may name the writer entry (385 D-14/SC5).
|
|
929
|
-
*/
|
|
930
408
|
interface LocalKnowledgeProbeCapabilities {
|
|
931
409
|
readonly classifyIndexFace: typeof classifyIndexFace;
|
|
932
410
|
readonly foldRetrievalRung: typeof foldRetrievalRung;
|
|
@@ -950,13 +428,6 @@ interface LocalDaemonCapabilities {
|
|
|
950
428
|
readonly releaseLease: typeof releaseLease;
|
|
951
429
|
readonly readWriterLease: typeof readWriterLease;
|
|
952
430
|
readonly isLeaseStale: typeof isLeaseStale;
|
|
953
|
-
/**
|
|
954
|
-
* CR-01/CR-08: the one three-valued freshness verdict — fresh, reclaimable, or unknown.
|
|
955
|
-
*
|
|
956
|
-
* Any surface that classifies a holder as recoverable must read this and not the lease file
|
|
957
|
-
* alone, and must name what it does with `unknown` rather than inheriting a boolean it never
|
|
958
|
-
* chose. An authority state that cannot be read is not evidence that nobody holds it.
|
|
959
|
-
*/
|
|
960
431
|
readonly deriveWriterLeaseFreshness: typeof deriveWriterLeaseFreshness;
|
|
961
432
|
readonly countPendingCurationJobs: typeof countPendingCurationJobs;
|
|
962
433
|
readonly countRemainingCurationWork: typeof countRemainingCurationWork;
|
|
@@ -970,7 +441,6 @@ interface LocalDaemonCapabilities {
|
|
|
970
441
|
readonly embedderWorkerProcessIsAlive: typeof embedderWorkerProcessIsAlive;
|
|
971
442
|
readonly embedderWorkerSocketPath: typeof embedderWorkerSocketPath;
|
|
972
443
|
readonly probeEmbedderWorkerSocket: typeof probeEmbedderWorkerSocket;
|
|
973
|
-
/** CR-05: no surface may signal a registered worker pid without this verdict returning 'match'. */
|
|
974
444
|
readonly verifyEmbedderWorkerIncarnation: typeof verifyEmbedderWorkerIncarnation;
|
|
975
445
|
readonly resolveProcessIncarnation: typeof resolveProcessIncarnation;
|
|
976
446
|
readonly removeEmbedderWorkerRegistration: (agentQaRoot: string, expected: EmbedderWorkerRegistration) => ReturnType<typeof removeEmbedderWorkerRegistration>;
|
|
@@ -996,7 +466,7 @@ interface LocalKnowledgeMaintenanceCapabilities {
|
|
|
996
466
|
readonly resolveRollbackAffectedSet: typeof resolveRollbackAffectedSet;
|
|
997
467
|
readonly rollbackAffectedSetFingerprint: typeof rollbackAffectedSetFingerprint;
|
|
998
468
|
}
|
|
999
|
-
interface ReceiptWriterInput extends Pick<CreateLocalKnowledgeStoreConfig, 'knowledgeRoot' | 'executionContext' | '
|
|
469
|
+
interface ReceiptWriterInput extends Pick<CreateLocalKnowledgeStoreConfig, 'knowledgeRoot' | 'executionContext' | 'sourceBuildOrdinal' | 'sourceRunId'> {
|
|
1000
470
|
/** The caller already holds this authority; these capabilities never acquire a lease. */
|
|
1001
471
|
lease: {
|
|
1002
472
|
leaseId: string;
|
|
@@ -1021,10 +491,6 @@ declare function readFeedbackRecord(input: {
|
|
|
1021
491
|
interface LocalCurationCapabilities {
|
|
1022
492
|
readonly readFeedbackRecord: typeof readFeedbackRecord;
|
|
1023
493
|
readonly appendMarkEvidence: typeof appendMarkEvidence;
|
|
1024
|
-
/**
|
|
1025
|
-
* 2026-09-15, 423 D-16/D-17: the lease-free planning half appendMarkEvidence executes, so a
|
|
1026
|
-
* consequence preview names every confirm/overturn effect without the writer. Reads only.
|
|
1027
|
-
*/
|
|
1028
494
|
readonly planMarkEvidence: typeof planMarkEvidence;
|
|
1029
495
|
readonly projectMarkEvidenceOutcome: typeof projectMarkEvidenceOutcome;
|
|
1030
496
|
readonly triageMark: typeof triageMark;
|
|
@@ -1037,25 +503,9 @@ interface LocalCurationCapabilities {
|
|
|
1037
503
|
readonly openKnowledgeReader: typeof openKnowledgeReader;
|
|
1038
504
|
readonly drainQueue: typeof drainQueue;
|
|
1039
505
|
readonly foldRunOutcomes: typeof foldRunOutcomes;
|
|
1040
|
-
/**
|
|
1041
|
-
* THE mechanism a version bump rides (393 CR-02). The per-run receipt below carries the
|
|
1042
|
-
* version, but invalidating receipts only re-runs folds that answer 'already-applied' on the
|
|
1043
|
-
* durable marker — so the refold a bump promises happens through THIS capability, as a rebuild
|
|
1044
|
-
* of the derived family, and nowhere else.
|
|
1045
|
-
*
|
|
1046
|
-
* It is invoked at exactly two sites, one per supported host (393 round 6, CR-02-daemon): once
|
|
1047
|
-
* per CLI curation-tail sweep, and once per daemon lease acquisition. Both, because the CLI
|
|
1048
|
-
* tail is unreachable whenever a standing daemon takes the hand-off — a promise true of one
|
|
1049
|
-
* host is, on the other host, a projection that never converges.
|
|
1050
|
-
*/
|
|
1051
506
|
readonly reconcileRunOutcomesProjection: typeof reconcileRunOutcomesProjection;
|
|
1052
507
|
readonly enqueueCurationCandidateProjection: typeof enqueueCurationCandidateProjection;
|
|
1053
508
|
readonly readCanonicalBundleAnchors: typeof readCanonicalBundleAnchors;
|
|
1054
|
-
readonly readCanonicalBundleStateDigests: typeof readCanonicalBundleStateDigests;
|
|
1055
|
-
readonly readCanaryPostureFacts: typeof canaryPostureFactsFor;
|
|
1056
|
-
readonly readStandingGateReceipts: typeof standingReceiptDigestsFor;
|
|
1057
|
-
readonly readLowerTrustShares: typeof lowerTrustSharesFor;
|
|
1058
|
-
/** 418 D-07: reuse the writer's observation identity through the existing CLI bridge. */
|
|
1059
509
|
readonly canaryOutcomeObservationId: typeof canaryOutcomeObservationId;
|
|
1060
510
|
/**
|
|
1061
511
|
* Component of the tail's receipt: a bump refolds runs already receipted at the old version.
|
|
@@ -1072,51 +522,15 @@ declare const LOCAL_CURATION_CAPABILITIES: LocalCurationCapabilities;
|
|
|
1072
522
|
* skipped so one bad run never hides every other run.
|
|
1073
523
|
*/
|
|
1074
524
|
declare function createRunsReader(agentQaRoot: string): RunsReaderPort;
|
|
1075
|
-
|
|
1076
|
-
* The knowledge READ port, served through the PHYSICALLY read-only `/reader` package entry.
|
|
1077
|
-
*
|
|
1078
|
-
* The five read verbs live in `knowledge-review-reader.ts`, which is registered in the arch
|
|
1079
|
-
* reader carve-out's pinned file list and therefore CANNOT name the writer-gated entry. This
|
|
1080
|
-
* file can (it also binds the curator), so keeping the verbs here would have put them in the
|
|
1081
|
-
* one place in the workspace where a write import is legal — separation by discipline instead
|
|
1082
|
-
* of by rule. What stays here is the half that genuinely belongs to a composition root: the
|
|
1083
|
-
* D-01 sighting site, which mints into the durable addressing ledger and so must live where
|
|
1084
|
-
* the writer entry may be named.
|
|
1085
|
-
*
|
|
1086
|
-
* The knowledge ROOT arrives as a host-supplied resolver rather than being derived here: deciding
|
|
1087
|
-
* which configuration file is in force, layering an environment over it and choosing whether to
|
|
1088
|
-
* load and execute auth plugins are three decisions a daemon makes differently from a terminal,
|
|
1089
|
-
* and by the plan-08 dissection rule a thing a headless host would substitute is a port.
|
|
1090
|
-
*/
|
|
1091
|
-
declare function createKnowledgeReader(resolveKnowledgeRoot: () => Promise<string> | string, sightMemoryEntities?: SightMemoryEntities, resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>, resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors']): KnowledgeReaderPort;
|
|
525
|
+
declare function createKnowledgeReader(resolveKnowledgeRoot: () => Promise<string> | string, sightMemoryEntities?: SightMemoryEntities): KnowledgeReaderPort;
|
|
1092
526
|
interface CreateKnowledgeReviewInput {
|
|
1093
|
-
readonly resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors'];
|
|
1094
|
-
readonly resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>;
|
|
1095
527
|
readonly agentQaRoot: string;
|
|
1096
528
|
readonly resolveKnowledgeRoot: () => Promise<string> | string;
|
|
1097
|
-
/**
|
|
1098
|
-
* The writer lease this host ALREADY holds, when it is the holder (D-18).
|
|
1099
|
-
*
|
|
1100
|
-
* The daemon's half of the routing rule. A holder cannot acquire its own lease a second time, so
|
|
1101
|
-
* it hands the authority it owns to the change; supplying this is mutually exclusive with
|
|
1102
|
-
* supplying a delegate, and a host that supplies both is a host claiming to be two places.
|
|
1103
|
-
*/
|
|
1104
529
|
readonly resolveWriterAuthority?: () => {
|
|
1105
530
|
readonly leaseId: string;
|
|
1106
531
|
readonly epoch: number;
|
|
1107
532
|
} | undefined;
|
|
1108
|
-
/**
|
|
1109
|
-
* 432-12 (D-05): how a direct change reaches a live writer-lease holder. The holder receives the
|
|
1110
|
-
* validated request and the change's stable identity, bounded; the lease is never taken. Absent,
|
|
1111
|
-
* a held lease refuses the change by name. Exclusive with {@link resolveWriterAuthority}: a holder
|
|
1112
|
-
* never delegates. The daemon supplies none, which is why its own changes cannot recurse.
|
|
1113
|
-
*/
|
|
1114
533
|
readonly knowledgeChangeDelegate?: ExplicitReviewDelegate;
|
|
1115
|
-
/**
|
|
1116
|
-
* 432-12: the context a direct change is recorded under. Absent means the process resolver, the
|
|
1117
|
-
* default every registry in this composition already reads. The context is recorded as-is; an
|
|
1118
|
-
* explicit change applies in every context (D-04/D-08).
|
|
1119
|
-
*/
|
|
1120
534
|
readonly resolveExecutionContext?: () => ExecutionContext;
|
|
1121
535
|
}
|
|
1122
536
|
/**
|
|
@@ -1139,8 +553,6 @@ interface ApplyKnowledgeChangeInput {
|
|
|
1139
553
|
readonly opId: string;
|
|
1140
554
|
/** The caller's actual context, recorded as-is. An explicit change applies in every context. */
|
|
1141
555
|
readonly executionContext: ExecutionContext;
|
|
1142
|
-
readonly resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors'];
|
|
1143
|
-
readonly resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>;
|
|
1144
556
|
/**
|
|
1145
557
|
* How this host reaches a live writer-lease holder. The holder receives exactly the validated
|
|
1146
558
|
* request and identity, bounded; the lease is never taken. Absent, a held lease refuses by name.
|
|
@@ -1152,10 +564,6 @@ interface ApplyKnowledgeChangeInput {
|
|
|
1152
564
|
readonly epoch: number;
|
|
1153
565
|
};
|
|
1154
566
|
}
|
|
1155
|
-
/**
|
|
1156
|
-
* Apply one explicit knowledge change through the direct writer (432-06), with this host's short-id
|
|
1157
|
-
* resolver. Nothing is filed: the change is committed, or it is refused by type.
|
|
1158
|
-
*/
|
|
1159
567
|
declare function applyKnowledgeChange(input: ApplyKnowledgeChangeInput): Promise<ExplicitReviewResult>;
|
|
1160
568
|
interface CreateEntityDirectoryInput {
|
|
1161
569
|
readonly agentQaRoot: string;
|
|
@@ -1172,53 +580,10 @@ interface SweepEntityIndexOutcome extends EntityIndexSweepReport {
|
|
|
1172
580
|
/** How many renderings gained a vector this sweep. Zero on a floor host, by design. */
|
|
1173
581
|
readonly embedded: number;
|
|
1174
582
|
}
|
|
1175
|
-
/**
|
|
1176
|
-
* The daemon's maintenance-cadence sweep over the D-06 projection.
|
|
1177
|
-
*
|
|
1178
|
-
* Three properties, and each is a deliberate refusal rather than an omission:
|
|
1179
|
-
*
|
|
1180
|
-
* - it takes NO writer lease. Everything it writes lives in the entity index's own file, and
|
|
1181
|
-
* a projection that needed the lease could not be maintained by a host that does not hold
|
|
1182
|
-
* one — which is every one-shot CLI process.
|
|
1183
|
-
* - it never writes the addressing ledger. It READS the ledger to know what exists (D-02: the
|
|
1184
|
-
* ledger is the durable truth, not a projection) and writes only the rendering of it.
|
|
1185
|
-
* - it embeds only what a host can already embed. `acquireEmbedder` with no download is the
|
|
1186
|
-
* same ladder the retrieval legs ride: ready means the dense rung joins the resolver on this
|
|
1187
|
-
* host, and anything else leaves the projection lexical-only rather than blocking the sweep.
|
|
1188
|
-
*/
|
|
1189
583
|
declare function sweepEntityIndexProjection(input: SweepEntityIndexInput): Promise<SweepEntityIndexOutcome>;
|
|
1190
|
-
/**
|
|
1191
|
-
* The host's run-execution capability: run this request to completion, and say which run it was.
|
|
1192
|
-
*
|
|
1193
|
-
* A PORT rather than shared code, by the plan-08 dissection rule. Would a headless drainer
|
|
1194
|
-
* execute a suite the way a terminal host does? It would substitute — the process model
|
|
1195
|
-
* (in-process, a child, a worker pool), the signal handling, the reporters and the exit
|
|
1196
|
-
* discipline are all decisions the host owns and answers differently. What crosses into the
|
|
1197
|
-
* composition is the type; what stays with the host is the orchestration.
|
|
1198
|
-
*
|
|
1199
|
-
* The verb resolves the IDENTITY of the run and nothing else. Anything richer would be the
|
|
1200
|
-
* host telling the composition what happened, and the whole point of the binding below is
|
|
1201
|
-
* that the composition does not take the host's word for it.
|
|
1202
|
-
*/
|
|
1203
584
|
interface RunExecutionPort {
|
|
1204
|
-
/**
|
|
1205
|
-
* 2026-10-01 (432-18, D-15): the optional `gate` argument (401-08, D-08) carried the standing
|
|
1206
|
-
* approvals in force — the durable ledger's answer unioned with any dispatch-scoped grant — to a
|
|
1207
|
-
* run gate behind the port. The run gate went in 432-13 and the ledger and the dispatch overlay
|
|
1208
|
-
* go in 432-18, so a host is handed the request and nothing else.
|
|
1209
|
-
*/
|
|
1210
585
|
execute(request: RunsStartInput): Promise<StartedRun>;
|
|
1211
586
|
}
|
|
1212
|
-
/**
|
|
1213
|
-
* The run this host reported did not leave a durable event log behind.
|
|
1214
|
-
*
|
|
1215
|
-
* The composition's evidence check, and the reason `runs.start` cannot be satisfied by a host
|
|
1216
|
-
* that returns a plausible run id without running anything. The v49 bus writes `runStarted`
|
|
1217
|
-
* before anything else can happen, so a run that began at all has a non-empty log; an empty
|
|
1218
|
-
* one means no run took place under that id. Read through {@link buildRunPorts} — the same
|
|
1219
|
-
* `FsEventLog` family the runner appends with — so what is inspected is the run's own record
|
|
1220
|
-
* rather than a path this file re-derives.
|
|
1221
|
-
*/
|
|
1222
587
|
declare class RunProducedNoEventsError extends Error {
|
|
1223
588
|
readonly runId: string;
|
|
1224
589
|
constructor(runId: string);
|
|
@@ -1253,15 +618,6 @@ interface ParsedDraftDescriptor {
|
|
|
1253
618
|
readonly testId: string;
|
|
1254
619
|
readonly filePath: string;
|
|
1255
620
|
readonly testName: string;
|
|
1256
|
-
/**
|
|
1257
|
-
* The parsed test's `target`. REQUIRED, exactly as `ParsedDraftLike.target` and
|
|
1258
|
-
* `TestDefinitionSchema` require it (394-37, WR-04).
|
|
1259
|
-
*
|
|
1260
|
-
* A mirror that dropped it would hand `packages/agent` a draft whose target the compile stage
|
|
1261
|
-
* cannot check against the vocabulary it just served — and the cost of not checking is paid as
|
|
1262
|
-
* real child gate runs on a name `resolveTarget` throws on, against a key no repair patch may
|
|
1263
|
-
* edit.
|
|
1264
|
-
*/
|
|
1265
621
|
readonly target: string;
|
|
1266
622
|
readonly steps: readonly string[];
|
|
1267
623
|
/**
|
|
@@ -1272,14 +628,6 @@ interface ParsedDraftDescriptor {
|
|
|
1272
628
|
readonly context?: string;
|
|
1273
629
|
readonly contentDigest: string;
|
|
1274
630
|
}
|
|
1275
|
-
/**
|
|
1276
|
-
* What a host can say about a caller-supplied draft path.
|
|
1277
|
-
*
|
|
1278
|
-
* Four refusal arms and one success, because `packages/agent` is `storageNeutral` and genuinely
|
|
1279
|
-
* cannot answer any of them: it can neither stat a path nor know where the workspace ends. The op
|
|
1280
|
-
* turns each arm into its own NAMED error, so the refusal a caller catches is declared beside the
|
|
1281
|
-
* capability while the syscall stays with the host that owns a filesystem (T-393-01).
|
|
1282
|
-
*/
|
|
1283
631
|
type DraftParseOutcome = {
|
|
1284
632
|
readonly kind: 'parsed';
|
|
1285
633
|
readonly draft: ParsedDraftDescriptor;
|
|
@@ -1293,89 +641,18 @@ type DraftParseOutcome = {
|
|
|
1293
641
|
readonly kind: 'unparsable';
|
|
1294
642
|
readonly reason: string;
|
|
1295
643
|
};
|
|
1296
|
-
/** One authored suite test as TEXT, for gate 3's degraded lane (D-16). */
|
|
1297
644
|
interface SuiteTextEntry {
|
|
1298
645
|
readonly filePath: string;
|
|
1299
646
|
readonly testName: string;
|
|
1300
647
|
readonly stepsText: readonly string[];
|
|
1301
648
|
}
|
|
1302
|
-
/**
|
|
1303
|
-
* The host's authoring capability: parse ONE draft, and enumerate the authored-test universe.
|
|
1304
|
-
*
|
|
1305
|
-
* BOTH VERBS OR NEITHER, and the bundling is a report rather than a convenience. A host that
|
|
1306
|
-
* supplied only the parse would bind a capability whose gate-3 text lane is permanently empty —
|
|
1307
|
-
* evidence-less suite tests would silently stop joining the comparison, and a draft would look
|
|
1308
|
-
* novel purely because whatever it duplicates has never been run. That is D-16's unsafe direction
|
|
1309
|
-
* arrived at by omission, and the only way to make it un-omittable is to make the two arrive
|
|
1310
|
-
* together.
|
|
1311
|
-
*
|
|
1312
|
-
* Both verbs live at the HOST because both need `parseTestFile` from `@vostride/agent-qa-core`,
|
|
1313
|
-
* which neither this package nor `agent` may import (the FUNC-02 firewall) — the parse-at-host
|
|
1314
|
-
* precedent `cli/src/curation/authoring-test-discovery.ts` established.
|
|
1315
|
-
*/
|
|
1316
649
|
interface DraftAuthoringPort {
|
|
1317
650
|
parseDraft(filePath: string): Promise<DraftParseOutcome>;
|
|
1318
651
|
suiteTextCorpus(): Promise<readonly SuiteTextEntry[]>;
|
|
1319
|
-
/**
|
|
1320
|
-
* 394-33 · WR-07: the names a `target` may legally take in this project.
|
|
1321
|
-
*
|
|
1322
|
-
* ON THIS PORT for the reason `deriveDefaultScope` is: both hosts build their authoring
|
|
1323
|
-
* capability from ONE factory, so a verb that lives here is reached by the CLI `fn` surface and
|
|
1324
|
-
* the chat/daemon host without a second binding either could forget. A vocabulary served by only
|
|
1325
|
-
* one of the two hosts would make "does stage 3 guess at `target`" depend on which surface a
|
|
1326
|
-
* person happened to author from.
|
|
1327
|
-
*
|
|
1328
|
-
* IT ENUMERATES AND NEVER REFUSES — the opposite posture to `deriveDefaultScope` right below it,
|
|
1329
|
-
* which throws when the answer is not unique. There is no such thing as an ambiguous list, and a
|
|
1330
|
-
* project declaring no targets has an honest empty answer rather than a failure.
|
|
1331
|
-
*/
|
|
1332
652
|
configuredTargetNames(): Promise<readonly string[]>;
|
|
1333
|
-
/**
|
|
1334
|
-
* 394-26 · WINDOWS 110: which scope this project authors for, when the caller named none.
|
|
1335
|
-
*
|
|
1336
|
-
* ON THIS PORT rather than beside it, and that placement is the guarantee. Both hosts build
|
|
1337
|
-
* their authoring capability from one factory, so a verb that lives here is reached by the CLI
|
|
1338
|
-
* `fn` surface and the chat/daemon host without a second binding either could forget — which is
|
|
1339
|
-
* what makes "there is ONE derivation" a fact about the wiring rather than a convention.
|
|
1340
|
-
*
|
|
1341
|
-
* IT THROWS RATHER THAN ANSWERING `undefined` when the project has no unique product: the host
|
|
1342
|
-
* is the only side that knows which candidates it saw, and a refusal that cannot name them
|
|
1343
|
-
* leaves an author with no way to write the `scope` that would have worked.
|
|
1344
|
-
*/
|
|
1345
653
|
deriveDefaultScope(): Promise<ScopeKey>;
|
|
1346
|
-
/**
|
|
1347
|
-
* 394 D-01 · WTST-01: PARSE the compiled draft, then WRITE it to the shelf — in that order, as
|
|
1348
|
-
* one verb, joining for exactly the reason the two above bundle.
|
|
1349
|
-
*
|
|
1350
|
-
* ONE VERB AND NOT TWO, because the order is the mitigation (T-394-06). Model-authored YAML is
|
|
1351
|
-
* the one input on the authoring path that no schema at the op boundary can vet, and separate
|
|
1352
|
-
* verbs would let a caller write first and discover the parse failure afterwards — with bytes
|
|
1353
|
-
* already on this workspace's disk. Here an unparsable draft answers `unparsable` having
|
|
1354
|
-
* created nothing at all.
|
|
1355
|
-
*
|
|
1356
|
-
* THE DIGEST IS THE HOST'S, over the bytes it is writing, and it is the caller's only
|
|
1357
|
-
* addressing: the shelf path is minted from it, so nothing the model emitted reaches the
|
|
1358
|
-
* filesystem as a path component. `DraftRef.contentDigest`'s whole promise — a later edit
|
|
1359
|
-
* cannot inherit an earlier receipt — is only true while the digest is over what was stored.
|
|
1360
|
-
*/
|
|
1361
654
|
stageDraft(contents: string): Promise<DraftStageOutcome>;
|
|
1362
|
-
/**
|
|
1363
|
-
* 394-06 D-09/D-20: apply an RFC-6902 patch set to a staged draft and stage the result.
|
|
1364
|
-
*
|
|
1365
|
-
* AT THE HOST for the same reason its two neighbours are: `applyPatchSetToTestDoc` needs the
|
|
1366
|
-
* yaml CST from `@vostride/agent-qa-core`, which neither this package nor `agent` may import.
|
|
1367
|
-
* It answers the same `DraftStageOutcome`, so a patch that renders an unrunnable document is
|
|
1368
|
-
* refused with the shelf untouched rather than written and discovered later.
|
|
1369
|
-
*/
|
|
1370
655
|
applyPatchesToDraft(draft: ParsedDraftDescriptor, patchSet: TestEditPatchSet): Promise<DraftStageOutcome>;
|
|
1371
|
-
/**
|
|
1372
|
-
* 432 D-06/D-07: write a staged draft's bytes to its test path — the direct final-test writer.
|
|
1373
|
-
*
|
|
1374
|
-
* AT THE HOST for its neighbours' reason: the workspace identity mint lives in
|
|
1375
|
-
* `@vostride/agent-qa-core`. The host checks the boundary and that the target still holds the
|
|
1376
|
-
* bytes the caller read (absent for a new test), writes through a sibling temp and a rename, runs
|
|
1377
|
-
* no git, and answers `not-written` with its reason whenever the bytes did not land.
|
|
1378
|
-
*/
|
|
1379
656
|
publishDraft(request: DraftPublishRequest): Promise<TestFileWrite>;
|
|
1380
657
|
}
|
|
1381
658
|
/** One draft to write: its shelf path, its target, and what the target held when it was read. */
|
|
@@ -1401,13 +678,6 @@ type DraftStageOutcome = {
|
|
|
1401
678
|
/** Wall-clock in the one format every store column and dump row is written in. */
|
|
1402
679
|
declare const SYSTEM_CLOCK: ClockPort;
|
|
1403
680
|
declare const DIGEST_JOB_ID_SOURCE: JobIdSource;
|
|
1404
|
-
/**
|
|
1405
|
-
* The durable half of the host, opened on demand.
|
|
1406
|
-
*
|
|
1407
|
-
* `store` is the concrete sqlite store rather than the neutral port: the host that opened the
|
|
1408
|
-
* database is the one entitled to close it and to take the D-03 logical dump, and both verbs live
|
|
1409
|
-
* on the implementation. Nothing else in the package publishes it.
|
|
1410
|
-
*/
|
|
1411
681
|
interface LocalAgentJobs {
|
|
1412
682
|
readonly queue: AgentJobQueue;
|
|
1413
683
|
readonly store: SqliteJobStore;
|
|
@@ -1440,15 +710,8 @@ declare class LocalAgentClosedError extends Error {
|
|
|
1440
710
|
constructor(agentQaRoot: string);
|
|
1441
711
|
}
|
|
1442
712
|
interface LocalAgentHost {
|
|
1443
|
-
/** The
|
|
713
|
+
/** The function registry with every seed capability bound over local storage. */
|
|
1444
714
|
readonly registry: FunctionRegistry;
|
|
1445
|
-
/**
|
|
1446
|
-
* The live chat session composed beside the registry (392 plan 08).
|
|
1447
|
-
*
|
|
1448
|
-
* Present on EVERY host, because the turn engine is (D-24) — a host whose chat session were
|
|
1449
|
-
* optional would make `agent.ask` bound and its state absent, which is two answers to whether
|
|
1450
|
-
* this host can hold a conversation.
|
|
1451
|
-
*/
|
|
1452
715
|
readonly chat: LocalAgentChatSession;
|
|
1453
716
|
/** The knowledge-writer powers this host grants — the same frozen object for every host. */
|
|
1454
717
|
readonly curation: LocalCurationCapabilities;
|
|
@@ -1468,419 +731,324 @@ interface LocalAgentHost {
|
|
|
1468
731
|
/** Close whatever was opened and join an open already in flight. Idempotent. */
|
|
1469
732
|
close(): Promise<void>;
|
|
1470
733
|
}
|
|
1471
|
-
/**
|
|
1472
|
-
* What a host's curation binding does with candidate prose (388-10, UF-388-01 / D-11).
|
|
1473
|
-
*
|
|
1474
|
-
* A closed union, REQUIRED wherever `postRun` is supplied: a host that cannot say what its
|
|
1475
|
-
* fold does with candidate prose has not been reviewed for UF-388-01, and the typechecker is
|
|
1476
|
-
* what makes that review mandatory rather than customary.
|
|
1477
|
-
*
|
|
1478
|
-
* - `'masker-active'` — the fold has the declared-secret mask bound (441-01 decision 10), or the
|
|
1479
|
-
* binding never reaches candidate emission at all.
|
|
1480
|
-
* - `'no-masker'` — the binding folds with NO declared mask. A statement about DISCLOSURE, not
|
|
1481
|
-
* about capability: the fold would run, but its prose masking would degrade to a pass-through,
|
|
1482
|
-
* so a host declaring this may not claim the kind that runs it.
|
|
1483
|
-
*/
|
|
1484
734
|
type CandidateProsePosture = 'masker-active' | 'no-masker';
|
|
1485
|
-
/**
|
|
1486
|
-
* The chain kinds a host of each posture MAY NOT CLAIM — one table, no second spelling.
|
|
1487
|
-
*
|
|
1488
|
-
* A `Record` over the union rather than a condition, deliberately: this phase's named defect
|
|
1489
|
-
* class is a guard whose input domain is written in prose while the code ranges over a
|
|
1490
|
-
* subset, and a total `Record` stops compiling the day a third posture is added. The queue's
|
|
1491
|
-
* `unclaimableKinds` is derived from this table and from nothing else.
|
|
1492
|
-
*/
|
|
1493
735
|
declare const UNCLAIMABLE_BY_PROSE_POSTURE: Record<CandidateProsePosture, readonly JobKind[]>;
|
|
1494
736
|
interface ComposeLocalAgentInput {
|
|
1495
737
|
readonly mask: MaskFn;
|
|
1496
|
-
/** Immutable neutral data resolved by the host, reused until recomposition. */
|
|
1497
|
-
readonly resolveTrustPriors?: CreateLocalKnowledgeStoreConfig['resolveTrustPriors'];
|
|
1498
738
|
readonly feedback?: FeedbackPort;
|
|
1499
|
-
/**
|
|
1500
|
-
* 423 D-19/D-16: read-only mark history and consequence preview; absent leaves runs.marks.history
|
|
1501
|
-
* and runs.mark.preview unbound by name, and a port without `preview` leaves only the preview unbound.
|
|
1502
|
-
*/
|
|
1503
739
|
readonly feedbackReads?: FeedbackReadsPort;
|
|
1504
|
-
/** DATA across the wall: host preparation may await; candidate evaluation is synchronous. */
|
|
1505
|
-
readonly resolvePromotionPosture?: () => Promise<ResolvePromotionPosture | undefined>;
|
|
1506
740
|
/** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */
|
|
1507
741
|
readonly agentQaRoot: string;
|
|
1508
|
-
/**
|
|
1509
|
-
* Masked configuration reads. Injected because flattening and masking a resolved configuration
|
|
1510
|
-
* needs the host's own loader — its file layering, its environment, its plugin policy — and the
|
|
1511
|
-
* masking decision is a disclosure boundary the host owns (T-384-07 / T-384-17).
|
|
1512
|
-
*/
|
|
1513
742
|
readonly config: ConfigReaderPort;
|
|
1514
743
|
/** Resolves the knowledge root this invocation serves from. See `createKnowledgeReader`. */
|
|
1515
744
|
readonly knowledgeRoot: () => Promise<string> | string;
|
|
1516
|
-
/**
|
|
1517
|
-
* The model a job may author with (D-10, plan 05).
|
|
1518
|
-
*
|
|
1519
|
-
* A required factory. REQUIRED because the queue's own `model` option is required and not
|
|
1520
|
-
* defaultable — an optional capability means a queue can be built with none, and the only place
|
|
1521
|
-
* to discover that is inside an author callback far from the composition that forgot it. A
|
|
1522
|
-
* FACTORY because `jobs()` is deferred, and resolving a provider handle costs a configuration
|
|
1523
|
-
* read and an auth resolution that a host listing the registry must not pay.
|
|
1524
|
-
*
|
|
1525
|
-
* It is called at most once, when the queue is opened. `agent-local` never constructs a model:
|
|
1526
|
-
* its ownership contract forbids provider invocation, so the handle arrives already built and no
|
|
1527
|
-
* provider name is named here.
|
|
1528
|
-
*/
|
|
1529
745
|
readonly model: () => JobModelCapability | Promise<JobModelCapability>;
|
|
1530
|
-
/**
|
|
1531
|
-
* How this host executes a run (D-16). OPTIONAL, and the optionality is the reporting
|
|
1532
|
-
* mechanism rather than a convenience: a host that supplies it lists `runs.start` as
|
|
1533
|
-
* `bound` and can run it; a host that does not lists the same capability as `unbound` and
|
|
1534
|
-
* refuses it by name. Not every composition can start a run — a listing, a read-only
|
|
1535
|
-
* surface, 386's daemon before it wires an executor — and D-09 requires that to be a
|
|
1536
|
-
* visible state rather than a call that fails somewhere far from the composition.
|
|
1537
|
-
*/
|
|
1538
746
|
readonly runExecution?: RunExecutionPort;
|
|
1539
|
-
/**
|
|
1540
|
-
* How this host parses a draft and enumerates its authored suite (393 D-01), on the exact
|
|
1541
|
-
* optional-operation idiom `runExecution` above uses.
|
|
1542
|
-
*
|
|
1543
|
-
* OPTIONAL, and — like its neighbour — the optionality is the reporting mechanism rather than a
|
|
1544
|
-
* convenience. `authoring.draft.verify` is bound only where this AND `runExecution` are both
|
|
1545
|
-
* present, because a host that cannot parse a test file and a host that cannot start a run are
|
|
1546
|
-
* both hosts that cannot verify a draft. Either one missing lists the capability `unbound` BY
|
|
1547
|
-
* NAME, which is the honest answer; the alternative is a receipt whose four booleans were
|
|
1548
|
-
* computed from no runs at all, and a refusal wearing a verdict's clothes is the one answer that
|
|
1549
|
-
* could get a draft kept on the strength of nothing.
|
|
1550
|
-
*
|
|
1551
|
-
* Host-supplied for the reason `mintQuarantineIdentityPath` is: it needs `parseTestFile` and the
|
|
1552
|
-
* CHECKOUT ROOT, and neither this package nor `agent` may name `@vostride/agent-qa-core`.
|
|
1553
|
-
*/
|
|
1554
747
|
readonly draftAuthoring?: DraftAuthoringPort;
|
|
1555
|
-
/**
|
|
1556
|
-
* 395-01 D-03/D-17 · CFGM-01/04: the committed config file SET as RAW BYTES, plus the
|
|
1557
|
-
* comment-preserving field edit over them.
|
|
1558
|
-
*
|
|
1559
|
-
* Host-supplied because the edit is `yaml`'s Document API, and neither this package nor `agent`
|
|
1560
|
-
* may name that dependency under their ownership contracts. The CLI host already depends on it and already owns the file format.
|
|
1561
|
-
*/
|
|
1562
748
|
readonly configFiles?: ConfigFilesPortLike;
|
|
1563
|
-
/**
|
|
1564
|
-
* 395-01 CFGM-01: whole-config validation, run BEFORE a proposal surfaces.
|
|
1565
|
-
*
|
|
1566
|
-
* Host-supplied because `AgentQaConfigSchema` lives in `@vostride/agent-qa-core`, which neither
|
|
1567
|
-
* this package nor `agent` may name — the `mintQuarantineIdentityPath` arrangement exactly.
|
|
1568
|
-
*/
|
|
1569
749
|
readonly configValidate?: ConfigValidatePortLike;
|
|
1570
|
-
/**
|
|
1571
|
-
* 395-08 D-04 · CFGM-05: the shared scaffold CONTENT, rendered by the host that owns it.
|
|
1572
|
-
*
|
|
1573
|
-
* A SEPARATE OPTIONAL BINDING. The substance lives beside
|
|
1574
|
-
* `init`'s own write path in `packages/cli`, which neither this package nor `packages/agent` may
|
|
1575
|
-
* import; its absence leaves `config.project.scaffold` — and only that op — unbound, which is the
|
|
1576
|
-
* honest catalogue answer for a host that can edit a configuration but cannot create one.
|
|
1577
|
-
*/
|
|
1578
750
|
readonly scaffoldContent?: ConfigScaffoldContentPortLike;
|
|
1579
|
-
/**
|
|
1580
|
-
* 2026-09-30, 432-07 D-05/D-07: the direct config writer. Host-supplied because its transaction
|
|
1581
|
-
* is the dashboard's config file transaction, shared per path with the dashboard's own writes.
|
|
1582
|
-
*/
|
|
1583
751
|
readonly configWrite?: FunctionDeps['configWrite'];
|
|
1584
|
-
/**
|
|
1585
|
-
* 2026-08-17 (398 D-09 / D-11 · XPLN-02): the four host halves `agent.explain` needs — the
|
|
1586
|
-
* committed capability catalog as data, the model's citation over it, and the two coverage hooks.
|
|
1587
|
-
*
|
|
1588
|
-
* Host-supplied for the reason `scaffoldContent` is, and the boundary is harder here rather than
|
|
1589
|
-
* softer: the artifact is read by `loadCapabilityCatalog` in `packages/cli`, which walks the
|
|
1590
|
-
* package root and touches `fs`, and this package is host-neutral. The citation call needs the
|
|
1591
|
-
* model the chat host already composed through `createModel`, which is a resolution neither this
|
|
1592
|
-
* package nor `packages/agent` may perform. The coverage append is a file write.
|
|
1593
|
-
*
|
|
1594
|
-
* OPTIONAL, and the absence is the report. A composition that omits it lists `agent.explain`
|
|
1595
|
-
* `unbound` BY NAME rather than degrading to a model-only answer — which is the one behaviour
|
|
1596
|
-
* XPLN-02 exists to forbid, and the one that would be hardest to notice, because an explain
|
|
1597
|
-
* answering from model memory still sounds exactly like an explain.
|
|
1598
|
-
*/
|
|
1599
752
|
readonly capabilityCatalog?: CapabilityCatalogPort;
|
|
1600
|
-
/**
|
|
1601
|
-
* 403 D-03: the live-view mint seam `runs.liveurl` binds through, handed straight through from
|
|
1602
|
-
* the host — this composition decides nothing about it.
|
|
1603
|
-
*
|
|
1604
|
-
* OPTIONAL because the absence is a genuine host fact and not a degradation: a host serving no
|
|
1605
|
-
* HTTP origin has no URL it could honestly mint, so the op lists `unbound` BY NAME rather than
|
|
1606
|
-
* returning a link that resolves to nothing.
|
|
1607
|
-
*/
|
|
1608
753
|
readonly liveView?: LiveViewPort;
|
|
1609
|
-
/**
|
|
1610
|
-
* 405 D-03: the durable run-detail projection read `runs.detail` binds through, handed straight
|
|
1611
|
-
* through from the host — this composition decides nothing about it and constructs no database.
|
|
1612
|
-
*
|
|
1613
|
-
* OPTIONAL because a host may have no projection to read, and then `runs.detail` lists `unbound`
|
|
1614
|
-
* BY NAME. The CLI host binds a reader over the configured or default runs database path whenever
|
|
1615
|
-
* its config parses (a read before that file exists answers not recorded in the runs database);
|
|
1616
|
-
* the dashboard passes its own handle.
|
|
1617
|
-
*/
|
|
1618
754
|
readonly runDetail?: RunDetailReaderPort;
|
|
1619
|
-
/**
|
|
1620
|
-
* 432-12 (D-05): how a direct knowledge change reaches the writer-lease holder when one is alive,
|
|
1621
|
-
* as an OPTIONAL operation on the input bag rather than a new production seam (the 386-41 D-2
|
|
1622
|
-
* idiom): `agent-local` cannot name a socket and does not. The CLI host injects a closure
|
|
1623
|
-
* over `invokeViaDaemon` that invokes the change op there with the same identity; the daemon's
|
|
1624
|
-
* own composition injects nothing, because it holds the lease.
|
|
1625
|
-
*/
|
|
1626
755
|
readonly knowledgeChangeDelegate?: ExplicitReviewDelegate;
|
|
1627
|
-
/** The writer lease a leaseholding host already owns
|
|
756
|
+
/** The writer lease a leaseholding host already owns. See `createKnowledgeReview`. */
|
|
1628
757
|
readonly resolveWriterAuthority?: () => {
|
|
1629
758
|
readonly leaseId: string;
|
|
1630
759
|
readonly epoch: number;
|
|
1631
760
|
} | undefined;
|
|
1632
|
-
/**
|
|
1633
|
-
* Mints the durable workspace-relative identity the quarantine ledger keys `filePath` on
|
|
1634
|
-
* (390-12 / D-01). Core's `workspaceRelativeIdentityPath`, pre-bound by the host to its own
|
|
1635
|
-
* config directory.
|
|
1636
|
-
*
|
|
1637
|
-
* Host-supplied for the same reason `resolveWriterAuthority` one field up is: the CHECKOUT ROOT is
|
|
1638
|
-
* a fact only a host knows. Neither this composition nor the verbs beneath it can discover it, and
|
|
1639
|
-
* a layer that guessed would mint identities against the wrong root.
|
|
1640
|
-
*
|
|
1641
|
-
* REQUIRED, and — unlike its neighbour — not conditionally spread. The optionality of the writer
|
|
1642
|
-
* authority is a real report about a real difference between hosts: one holds the lease, one does
|
|
1643
|
-
* not. There is no host that can legitimately lack a checkout root, so an absent mint is not a
|
|
1644
|
-
* posture, it is exactly the unvalidated pass-through that let the write verbs author permanently
|
|
1645
|
-
* unreadable lines into a committed artifact. It belongs at compile time, at the composition that
|
|
1646
|
-
* forgot it.
|
|
1647
|
-
*/
|
|
1648
761
|
readonly mintQuarantineIdentityPath: (filePath: string) => string;
|
|
1649
762
|
readonly clock?: ClockPort;
|
|
1650
763
|
readonly idSource?: JobIdSource;
|
|
1651
|
-
/** The kind registry the queue dispatches through. Defaults to the
|
|
764
|
+
/** The kind registry the queue dispatches through. Defaults to the real declarations. */
|
|
1652
765
|
readonly jobKinds?: JobKindRegistry;
|
|
1653
|
-
/**
|
|
1654
|
-
* What the post-run chain's real handlers may do (388 D-01), on the optional-operation
|
|
1655
|
-
* idiom `runExecution` and `applyDelegate` already use.
|
|
1656
|
-
*
|
|
1657
|
-
* OPTIONAL, and the optionality is the report rather than a convenience: a host that
|
|
1658
|
-
* supplies it dispatches the REAL analyze-run and curate-memory bodies, and a host that
|
|
1659
|
-
* does not keeps the scripted stand-ins. Only `curateRun` is asked for — the handoff read
|
|
1660
|
-
* is built here, from `agentQaRoot`, because it is a path derivation this package already
|
|
1661
|
-
* owns and a caller-supplied one would be a second layout to keep in step with the writer's.
|
|
1662
|
-
*
|
|
1663
|
-
* `curateRun` is the caller's because it is not a local concern at all: it needs the writer
|
|
1664
|
-
* lease, a knowledge root and the v51 drain, and the CLI's run tail is where all three
|
|
1665
|
-
* already meet (plan 02 binds it).
|
|
1666
|
-
*/
|
|
1667
766
|
readonly postRun?: {
|
|
1668
767
|
readonly curateRun: PostRunJobCapabilities['curateRun'];
|
|
1669
|
-
/**
|
|
1670
|
-
* REQUIRED beside the binding it describes: a `postRun` that omits it must stop
|
|
1671
|
-
* typechecking, because the posture is the UF-388-01 review of this binding and an
|
|
1672
|
-
* unreviewed binding is exactly what let the daemon fold unmasked. See
|
|
1673
|
-
* `CandidateProsePosture` for what each member does and does not certify.
|
|
1674
|
-
*/
|
|
1675
768
|
readonly candidateProse: CandidateProsePosture;
|
|
1676
|
-
/**
|
|
1677
|
-
* The 422 D-13 proposal stage's staging port, passed straight through.
|
|
1678
|
-
*
|
|
1679
|
-
* OPTIONAL beside a REQUIRED `curateRun`, and the asymmetry is the contract: without
|
|
1680
|
-
* `curateRun` there is no real fold and therefore no real chain, whereas a host that binds
|
|
1681
|
-
* no staging port still runs the third stage — it stages nothing, records no counts, and
|
|
1682
|
-
* the terminal says exactly that. Passed through rather than built here for the same reason
|
|
1683
|
-
* `curateRun` is: the adversarial staging is not a local concern, and this package may not
|
|
1684
|
-
* name the seam it lives behind.
|
|
1685
|
-
*/
|
|
1686
|
-
readonly stageAdversarialProposal?: PostRunJobCapabilities['stageAdversarialProposal'];
|
|
1687
|
-
/**
|
|
1688
|
-
* The 422 D-14 Gate-1 leg's four ports, passed straight through (422-09).
|
|
1689
|
-
*
|
|
1690
|
-
* NEUTRAL FORWARDING, and the neutrality is the contract rather than a style note: every one
|
|
1691
|
-
* of these needs a committed corpus, a screening run and a writer this package may not name,
|
|
1692
|
-
* and a version of this file that could construct them could not be this file. What crosses
|
|
1693
|
-
* here is four closures and a number; what stays on the other side is every fact about where
|
|
1694
|
-
* they read from.
|
|
1695
|
-
*
|
|
1696
|
-
* Each is OPTIONAL and each is spread on presence, because a host that binds none is the
|
|
1697
|
-
* shipped posture — the stage runs, screens nothing, and says so by omitting the member.
|
|
1698
|
-
*/
|
|
1699
|
-
readonly runReplayGate?: PostRunJobCapabilities['runReplayGate'];
|
|
1700
|
-
readonly listBundles?: PostRunJobCapabilities['listBundles'];
|
|
1701
|
-
readonly gateReceiptsFor?: PostRunJobCapabilities['gateReceiptsFor'];
|
|
1702
|
-
readonly readProposeCorpusPosture?: PostRunJobCapabilities['readProposeCorpusPosture'];
|
|
1703
|
-
/**
|
|
1704
|
-
* 2026-09-13, 422 D-19, gap plan 422-27: the host's durable per-run evaluation-root
|
|
1705
|
-
* posture, forwarded as a neutral closure. Absence leaves the handler's fail-closed
|
|
1706
|
-
* default in force; this composition neither resolves nor interprets the posture.
|
|
1707
|
-
*/
|
|
1708
|
-
readonly readMisdirectionRootPosture?: PostRunJobCapabilities['readMisdirectionRootPosture'];
|
|
1709
|
-
/**
|
|
1710
|
-
* The operator's per-job Gate-1 bound, as a FACTORY resolved once at queue open.
|
|
1711
|
-
*
|
|
1712
|
-
* A factory on the exact `model` / `analysisTokenBudget` idiom, for the same reason those are:
|
|
1713
|
-
* reading it needs a configuration read, and paying for one at composition would charge every
|
|
1714
|
-
* host that only lists the registry. The capability itself is plain data — a number the
|
|
1715
|
-
* handler reads and never a reader it calls.
|
|
1716
|
-
*/
|
|
1717
|
-
readonly proposeGate1MaxPerJob?: () => Promise<number | undefined> | number | undefined;
|
|
1718
769
|
};
|
|
1719
|
-
/**
|
|
1720
|
-
* D-01's TokenAccounting substrate for the analyze-run author (389 plan 06). OPTIONAL
|
|
1721
|
-
* and host-resolved: both production hosts derive it from the SAME model-profile
|
|
1722
|
-
* resolution as the job model itself (one source of truth, no second config surface —
|
|
1723
|
-
* 386 D-15), and `composeLocalAgent` only passes the resolved value through. A FACTORY
|
|
1724
|
-
* on the exact `model` idiom — resolution may need a configuration read, and it is paid
|
|
1725
|
-
* once, at queue open, never by a host that only lists the registry. A factory that
|
|
1726
|
-
* answers `undefined` composes the plan-04 no-ladder posture: packs travel whole.
|
|
1727
|
-
*/
|
|
1728
770
|
readonly analysisTokenBudget?: () => Promise<PostRunJobCapabilities['analysisTokenBudget']> | PostRunJobCapabilities['analysisTokenBudget'];
|
|
1729
|
-
/**
|
|
1730
|
-
* The host's execution context for this composition (400-01, D-05).
|
|
1731
|
-
*
|
|
1732
|
-
* 2026-10-02 (432-39, D-12): it reaches the knowledge review, which records a direct change under
|
|
1733
|
-
* it, and nothing else here; the registry option it was also forwarded to is deleted, because no
|
|
1734
|
-
* op decides in a context. The history below explains why it is injected per composition.
|
|
1735
|
-
*
|
|
1736
|
-
* INJECTED RATHER THAN PINNED ON THE PROCESS, and that is the whole reason this field exists.
|
|
1737
|
-
* The registry accepted a `resolveExecutionContext` from 384 until 432-39; what it did NOT have
|
|
1738
|
-
* was a way for a host to supply one, so the only lever a host had was
|
|
1739
|
-
* `setActiveExecutionContextResolver` — a PROCESS GLOBAL. Reaching for it changes the answer
|
|
1740
|
-
* for everything composed in that process, including compositions the host does not own, and a
|
|
1741
|
-
* host that forgot to restore it leaks its posture into every later caller. The dashboard door
|
|
1742
|
-
* is the first host that has to state a posture per composition rather than per process
|
|
1743
|
-
* (D-01/D-05: the browser confirm channel is what makes the context interactive, and it is a
|
|
1744
|
-
* property of a server, not of the machine), so the injected form is what it binds.
|
|
1745
|
-
*
|
|
1746
|
-
* ABSENT MEANS THE SHIPPED AMBIENT RESOLVER, unchanged: the knowledge review's own default reads
|
|
1747
|
-
* safety's process resolver, so every existing host composes exactly as it did before. This is
|
|
1748
|
-
* a passthrough and nothing here decides what a context MEANS. (432-19: `requiresFailClosed`, the
|
|
1749
|
-
* gate's reading of a context, is deleted; the four-member vocabulary stays.)
|
|
1750
|
-
*/
|
|
1751
771
|
readonly resolveExecutionContext?: () => ExecutionContext;
|
|
1752
|
-
/**
|
|
1753
|
-
* Notified AFTER one session event has been appended to its log (400-01, D-03).
|
|
1754
|
-
*
|
|
1755
|
-
* AN OBSERVER, AND EVERY WORD OF THAT IS THE CONTRACT. It is called with an event that is
|
|
1756
|
-
* ALREADY ON THE FILE — after `append` resolves, never before and never instead — so a host
|
|
1757
|
-
* pushing these somewhere cannot show a person an event the durable log does not carry. It
|
|
1758
|
-
* cannot append, cannot rewrite and cannot refuse: the return value is discarded and a throw is
|
|
1759
|
-
* swallowed at the notify site, because a surface's push channel failing must not fail the turn
|
|
1760
|
-
* that produced the event.
|
|
1761
|
-
*
|
|
1762
|
-
* WHY THIS AND NOT A HOST-SUPPLIED `SessionLogPort`. The obvious alternative — let a host wrap
|
|
1763
|
-
* or replace the log — is exactly what D-04 forbids: sessions belong to the agent, not to a
|
|
1764
|
-
* surface, and a replaceable log is a second store one conversation at a time. This seam widens
|
|
1765
|
-
* nothing. The log stays the single producer and the single writer; what a host gets is a
|
|
1766
|
-
* carbon copy of what was written.
|
|
1767
|
-
*
|
|
1768
|
-
* The SESSION ID travels with the event because the event itself carries only a `turnId` — the
|
|
1769
|
-
* grammar's exact-key guard means it never will carry more (Pitfall 4), so the fact a subscriber
|
|
1770
|
-
* needs is supplied beside the record rather than smuggled into it.
|
|
1771
|
-
*/
|
|
1772
772
|
readonly observeSessionEvent?: (sessionId: string, event: ChatSessionEvent) => void;
|
|
1773
|
-
/**
|
|
1774
|
-
* The turn engine's reconciliation strategy (392 D-16).
|
|
1775
|
-
*
|
|
1776
|
-
* AN INTERNAL COMPOSITION OPTION, and every word of that is load-bearing. It is here so the
|
|
1777
|
-
* mutation proof can assemble the REAL host twice — override on, override off — and read the
|
|
1778
|
-
* difference off a named compound scenario, which is the only differential that measures what
|
|
1779
|
-
* production actually wires (Pitfall 3, the produced-not-literal law).
|
|
1780
|
-
*
|
|
1781
|
-
* IT IS NOT, AND MUST NEVER BECOME, CONFIG-REACHABLE. No field of `AgentQaConfig` names it and
|
|
1782
|
-
* none may: the deterministic override is the mechanism that stops a model's plan from beating
|
|
1783
|
-
* a proven mapping, so a production knob that switched it off would be a supported way to
|
|
1784
|
-
* disable a safety property. Absent, the shipped strategy is used — which is what makes the
|
|
1785
|
-
* absence the safe default rather than an unconfigured state.
|
|
1786
|
-
*/
|
|
1787
773
|
readonly chatReconcile?: ReconcileStrategy;
|
|
1788
|
-
/**
|
|
1789
|
-
* The model stage 2 plans with, ALREADY BUILT by the host through `createModel` (CHAT-06).
|
|
1790
|
-
*
|
|
1791
|
-
* A model OBJECT and never a model id: the SDK's own type also admits an id it resolves by
|
|
1792
|
-
* constructing a client, which would put a provider client behind chat without the masking
|
|
1793
|
-
* middleware and the profile resolution `createModel` owns. The type closes that door here.
|
|
1794
|
-
*
|
|
1795
|
-
* ABSENT IS A REAL POSTURE, NOT AN UNCONFIGURED ONE. A host with no model bound is HEADLESS: any
|
|
1796
|
-
* clause the deterministic table cannot resolve fails the turn closed by name (D-08), which is
|
|
1797
|
-
* the correct behaviour rather than a degraded one. That is also why no planner is stubbed in —
|
|
1798
|
-
* a stub answering "I could not plan that" would say the same words about an entirely different
|
|
1799
|
-
* fact, that a model was asked and declined.
|
|
1800
|
-
*/
|
|
1801
774
|
readonly chatModel?: ChatLanguageModel;
|
|
1802
|
-
/**
|
|
1803
|
-
* The accounting instance chat's degrade pass measures against (CHAT-04, plan 06).
|
|
1804
|
-
*
|
|
1805
|
-
* HOST-RESOLVED and passed through untouched, on `analysisTokenBudget`'s precedent and for its
|
|
1806
|
-
* reason: the ceilings must come from the SAME capability resolution as the chat model itself,
|
|
1807
|
-
* or a session would compact against a window the model does not have. This composition adds no
|
|
1808
|
-
* knob of its own and cannot construct one — `agent-local` reaches no provider.
|
|
1809
|
-
*
|
|
1810
|
-
* Absent ⇒ no degrade pass runs and the `compaction` seat stays empty, which is the posture
|
|
1811
|
-
* every host had before a model was bound.
|
|
1812
|
-
*/
|
|
1813
775
|
readonly chatAccounting?: ChatTokenAccounting;
|
|
1814
|
-
/**
|
|
1815
|
-
* How this host resolves a model NAMED by `/model <name>` (D-04, plan 08).
|
|
1816
|
-
*
|
|
1817
|
-
* Supplied by the host for the same reason `chatModel` is, and enforced by the same rule: the
|
|
1818
|
-
* chat subtree may not construct a model, so a session-scoped switch has to arrive as a
|
|
1819
|
-
* capability the composition was handed. Absent ⇒ `/model` still records the session's declared
|
|
1820
|
-
* model and emits its `model_change` (the header, the prompt and the drift check all follow it),
|
|
1821
|
-
* and no new client is resolved — the honest behaviour for a host that composed one model.
|
|
1822
|
-
*/
|
|
1823
776
|
readonly chatModelFor?: (name: string) => ChatLanguageModel | Promise<ChatLanguageModel>;
|
|
1824
|
-
/**
|
|
1825
|
-
* Where a chat session PRINTS a mid-turn artifact a person reads (395-13, D-14).
|
|
1826
|
-
*
|
|
1827
|
-
* A PLAIN FUNCTION: printing needs nothing from this composition. The surface is handed text and
|
|
1828
|
-
* writes it. (432-16 deleted the `chatConfirm` factory that used to sit beside it.)
|
|
1829
|
-
*
|
|
1830
|
-
* PASSED THROUGH UNTOUCHED to the turn engine's `present`. Absent ⇒ the engine renders nothing
|
|
1831
|
-
* mid-turn, which is every host that is not a REPL — and no gate, receipt or session row moves.
|
|
1832
|
-
*/
|
|
1833
777
|
readonly chatPresent?: (text: string) => void | Promise<void>;
|
|
1834
778
|
}
|
|
1835
|
-
/**
|
|
1836
|
-
* The live chat session a host holds beside the registry (plan 08, RESEARCH Open Q2).
|
|
1837
|
-
*
|
|
1838
|
-
* Exposed because two of its facts have no other route to a surface: the state a REPL renders
|
|
1839
|
-
* from, and the ability to close an interrupted turn honestly. Everything else a conversation does
|
|
1840
|
-
* goes through `agent.ask` like every other capability (D-24).
|
|
1841
|
-
*/
|
|
1842
779
|
interface LocalAgentChatSession {
|
|
1843
|
-
/**
|
|
1844
|
-
* The live state of ONE conversation, or `undefined` for a session this host has not opened
|
|
1845
|
-
* (392 plan 13, CR-02).
|
|
1846
|
-
*
|
|
1847
|
-
* A LOOKUP RATHER THAN A CONTAINER, because the facts inside it — the turn in flight, the
|
|
1848
|
-
* conversation, the model in force, what `/pin` denies, whether `/quit` was typed — are facts
|
|
1849
|
-
* about a session and never about a host. A composition serving two conversations that handed
|
|
1850
|
-
* out one container was answering both of them with whichever turn wrote last, which is what
|
|
1851
|
-
* let a planner read the wrong history (CR-02) and a pin outlive its session (W-03).
|
|
1852
|
-
*
|
|
1853
|
-
* `undefined` is the honest answer for an id nobody here is holding, and reading NEVER creates
|
|
1854
|
-
* a scope: a surface asking about a session cannot bring one into being by asking.
|
|
1855
|
-
*/
|
|
1856
780
|
stateFor(sessionId: string): ChatStateSnapshot | undefined;
|
|
1857
|
-
/**
|
|
1858
|
-
* Write the explicit `aborted` event for the turn in flight, and fsync (D-19's graceful arm).
|
|
1859
|
-
*
|
|
1860
|
-
* A no-op between turns, deliberately: an `aborted` row for a turn that already carries its
|
|
1861
|
-
* `turn_complete` would make the repair on the next open trim a turn that finished.
|
|
1862
|
-
*/
|
|
1863
781
|
abortActiveTurn(): Promise<void>;
|
|
1864
782
|
}
|
|
1865
|
-
/** Compose the local agent host. */
|
|
1866
|
-
/**
|
|
1867
|
-
* The two callers chat mints, one per stage (392, RESEARCH Pitfall 1 / 391 D-06).
|
|
1868
|
-
*
|
|
1869
|
-
* IDENTICAL BUT FOR `origin`. `FunctionCaller.origin` answers "did a person decide this", and inside
|
|
1870
|
-
* ONE turn both answers occur: a person typing a canonical alias decided that call, and a model
|
|
1871
|
-
* planning one did not. The receipts a turn logs record that origin per clause.
|
|
1872
|
-
*
|
|
1873
|
-
* `surface` is `'chat'` on both and is ATTRIBUTION ONLY. Nothing in the function layer may branch
|
|
1874
|
-
* on it (`invoke.ts:28-29`).
|
|
1875
|
-
*
|
|
1876
|
-
* 2026-10-01 (432-20/432-21, D-12): no scope set and no safe-mode flag. `CHAT_STAGE_SCOPES`, the
|
|
1877
|
-
* whole closed scope union both stages held, is deleted: every caller can call every operation, and
|
|
1878
|
-
* the human-origin restriction the origin split once protected is deleted with `requiresHumanOrigin`.
|
|
1879
|
-
*/
|
|
1880
783
|
declare const CHAT_RESOLVER_CALLER: FunctionCaller;
|
|
1881
784
|
declare const CHAT_PLANNER_CALLER: FunctionCaller;
|
|
1882
785
|
declare function composeLocalAgent(input: ComposeLocalAgentInput): LocalAgentHost;
|
|
1883
786
|
|
|
787
|
+
declare const MARKS_LEDGER_FILE = "marks.jsonl";
|
|
788
|
+
declare const MARKS_LEDGER_LOCK_FILE = "marks.jsonl.lock";
|
|
789
|
+
/** A run's one unfinished mark, beside its ledger. */
|
|
790
|
+
declare const MARK_INTENT_FILE = "mark-intent.json";
|
|
791
|
+
declare const intentSchema: z.ZodObject<{
|
|
792
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
793
|
+
mark: z.ZodObject<{
|
|
794
|
+
runSlug: z.ZodString;
|
|
795
|
+
kind: z.ZodEnum<{
|
|
796
|
+
"false-fail": "false-fail";
|
|
797
|
+
"false-pass": "false-pass";
|
|
798
|
+
"confirmed-bug": "confirmed-bug";
|
|
799
|
+
}>;
|
|
800
|
+
origin: z.ZodLiteral<"user">;
|
|
801
|
+
ordinal: z.ZodNumber;
|
|
802
|
+
markedAt: z.ZodNumber;
|
|
803
|
+
note: z.ZodOptional<z.ZodString>;
|
|
804
|
+
rootCause: z.ZodOptional<z.ZodObject<{
|
|
805
|
+
class: z.ZodEnum<{
|
|
806
|
+
unknown: "unknown";
|
|
807
|
+
environment: "environment";
|
|
808
|
+
timeout: "timeout";
|
|
809
|
+
test_bug: "test_bug";
|
|
810
|
+
app_bug: "app_bug";
|
|
811
|
+
flake: "flake";
|
|
812
|
+
config_error: "config_error";
|
|
813
|
+
llm_error: "llm_error";
|
|
814
|
+
}>;
|
|
815
|
+
producer: z.ZodString;
|
|
816
|
+
}, z.core.$strict>>;
|
|
817
|
+
isRerun: z.ZodOptional<z.ZodLiteral<true>>;
|
|
818
|
+
disposition: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
819
|
+
kind: z.ZodLiteral<"quarantined">;
|
|
820
|
+
class: z.ZodEnum<{
|
|
821
|
+
environment: "environment";
|
|
822
|
+
timeout: "timeout";
|
|
823
|
+
flake: "flake";
|
|
824
|
+
}>;
|
|
825
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
826
|
+
kind: z.ZodLiteral<"applied">;
|
|
827
|
+
fix: z.ZodEnum<{
|
|
828
|
+
fact: "fact";
|
|
829
|
+
caution: "caution";
|
|
830
|
+
"procedure-hint": "procedure-hint";
|
|
831
|
+
"test-edit": "test-edit";
|
|
832
|
+
}>;
|
|
833
|
+
change: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
834
|
+
kind: z.ZodLiteral<"knowledge">;
|
|
835
|
+
changeId: z.ZodString;
|
|
836
|
+
recordIds: z.ZodArray<z.ZodString>;
|
|
837
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
838
|
+
kind: z.ZodLiteral<"test-file">;
|
|
839
|
+
filePath: z.ZodString;
|
|
840
|
+
contentDigest: z.ZodString;
|
|
841
|
+
}, z.core.$strict>], "kind">;
|
|
842
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
843
|
+
kind: z.ZodLiteral<"no-draftable-fix">;
|
|
844
|
+
checked: z.ZodObject<{
|
|
845
|
+
servedRecords: z.ZodNumber;
|
|
846
|
+
procedureReads: z.ZodNumber;
|
|
847
|
+
assertionDrift: z.ZodBoolean;
|
|
848
|
+
rootCause: z.ZodOptional<z.ZodEnum<{
|
|
849
|
+
unknown: "unknown";
|
|
850
|
+
environment: "environment";
|
|
851
|
+
timeout: "timeout";
|
|
852
|
+
test_bug: "test_bug";
|
|
853
|
+
app_bug: "app_bug";
|
|
854
|
+
flake: "flake";
|
|
855
|
+
config_error: "config_error";
|
|
856
|
+
llm_error: "llm_error";
|
|
857
|
+
}>>;
|
|
858
|
+
}, z.core.$strict>;
|
|
859
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
860
|
+
kind: z.ZodLiteral<"confirmed-bug">;
|
|
861
|
+
confirmedRecords: z.ZodNumber;
|
|
862
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
863
|
+
kind: z.ZodLiteral<"not-applied">;
|
|
864
|
+
fix: z.ZodEnum<{
|
|
865
|
+
fact: "fact";
|
|
866
|
+
caution: "caution";
|
|
867
|
+
"procedure-hint": "procedure-hint";
|
|
868
|
+
"test-edit": "test-edit";
|
|
869
|
+
}>;
|
|
870
|
+
reason: z.ZodEnum<{
|
|
871
|
+
"policy-materialize-refused": "policy-materialize-refused";
|
|
872
|
+
"target-not-found": "target-not-found";
|
|
873
|
+
"outside-workspace": "outside-workspace";
|
|
874
|
+
}>;
|
|
875
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
876
|
+
kind: z.ZodLiteral<"drafted">;
|
|
877
|
+
fix: z.ZodEnum<{
|
|
878
|
+
fact: "fact";
|
|
879
|
+
caution: "caution";
|
|
880
|
+
"procedure-hint": "procedure-hint";
|
|
881
|
+
"test-edit": "test-edit";
|
|
882
|
+
}>;
|
|
883
|
+
proposalId: z.ZodString;
|
|
884
|
+
proposalKind: z.ZodEnum<{
|
|
885
|
+
knowledge: "knowledge";
|
|
886
|
+
"test-draft": "test-draft";
|
|
887
|
+
}>;
|
|
888
|
+
}, z.core.$strict>], "kind">;
|
|
889
|
+
evidence: z.ZodObject<{
|
|
890
|
+
confirmed: z.ZodNumber;
|
|
891
|
+
overturned: z.ZodNumber;
|
|
892
|
+
}, z.core.$strict>;
|
|
893
|
+
supersedes: z.ZodOptional<z.ZodString>;
|
|
894
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
895
|
+
testIndex: z.ZodNumber;
|
|
896
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
897
|
+
stepIndex: z.ZodOptional<z.ZodNumber>;
|
|
898
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
899
|
+
markId: z.ZodString;
|
|
900
|
+
}, z.core.$strict>;
|
|
901
|
+
stage: z.ZodEnum<{
|
|
902
|
+
applied: "applied";
|
|
903
|
+
evidence: "evidence";
|
|
904
|
+
prepared: "prepared";
|
|
905
|
+
}>;
|
|
906
|
+
operationId: z.ZodUUID;
|
|
907
|
+
plan: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
908
|
+
fix: z.ZodEnum<{
|
|
909
|
+
fact: "fact";
|
|
910
|
+
caution: "caution";
|
|
911
|
+
"procedure-hint": "procedure-hint";
|
|
912
|
+
}>;
|
|
913
|
+
target: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
914
|
+
grain: z.ZodLiteral<"record">;
|
|
915
|
+
recordId: z.ZodString;
|
|
916
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
917
|
+
grain: z.ZodLiteral<"bundle">;
|
|
918
|
+
shortId: z.ZodString;
|
|
919
|
+
}, z.core.$strict>], "grain">;
|
|
920
|
+
deltas: z.ZodArray<z.ZodType<_vostride_agent_qa_schema.Delta, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.Delta, unknown>>>;
|
|
921
|
+
wording: z.ZodEnum<{
|
|
922
|
+
model: "model";
|
|
923
|
+
floor: "floor";
|
|
924
|
+
}>;
|
|
925
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
926
|
+
markId: z.ZodString;
|
|
927
|
+
feedbackSource: z.ZodObject<{
|
|
928
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
929
|
+
testIndex: z.ZodNumber;
|
|
930
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
931
|
+
stepIndex: z.ZodOptional<z.ZodNumber>;
|
|
932
|
+
kind: z.ZodEnum<{
|
|
933
|
+
"false-fail": "false-fail";
|
|
934
|
+
"false-pass": "false-pass";
|
|
935
|
+
"confirmed-bug": "confirmed-bug";
|
|
936
|
+
}>;
|
|
937
|
+
}, z.core.$strict>;
|
|
938
|
+
runTraceRef: z.ZodObject<{
|
|
939
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
940
|
+
runSlug: z.ZodString;
|
|
941
|
+
}, z.core.$strict>;
|
|
942
|
+
kind: z.ZodLiteral<"knowledge">;
|
|
943
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
944
|
+
fix: z.ZodLiteral<"test-edit">;
|
|
945
|
+
testRef: z.ZodString;
|
|
946
|
+
intent: z.ZodString;
|
|
947
|
+
wording: z.ZodEnum<{
|
|
948
|
+
model: "model";
|
|
949
|
+
floor: "floor";
|
|
950
|
+
}>;
|
|
951
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
952
|
+
markId: z.ZodString;
|
|
953
|
+
feedbackSource: z.ZodObject<{
|
|
954
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
955
|
+
testIndex: z.ZodNumber;
|
|
956
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
957
|
+
stepIndex: z.ZodOptional<z.ZodNumber>;
|
|
958
|
+
kind: z.ZodEnum<{
|
|
959
|
+
"false-fail": "false-fail";
|
|
960
|
+
"false-pass": "false-pass";
|
|
961
|
+
"confirmed-bug": "confirmed-bug";
|
|
962
|
+
}>;
|
|
963
|
+
}, z.core.$strict>;
|
|
964
|
+
runTraceRef: z.ZodObject<{
|
|
965
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
966
|
+
runSlug: z.ZodString;
|
|
967
|
+
}, z.core.$strict>;
|
|
968
|
+
kind: z.ZodLiteral<"test-edit">;
|
|
969
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
970
|
+
checked: z.ZodObject<{
|
|
971
|
+
servedRecords: z.ZodNumber;
|
|
972
|
+
procedureReads: z.ZodNumber;
|
|
973
|
+
assertionDrift: z.ZodBoolean;
|
|
974
|
+
rootCause: z.ZodOptional<z.ZodEnum<{
|
|
975
|
+
unknown: "unknown";
|
|
976
|
+
environment: "environment";
|
|
977
|
+
timeout: "timeout";
|
|
978
|
+
test_bug: "test_bug";
|
|
979
|
+
app_bug: "app_bug";
|
|
980
|
+
flake: "flake";
|
|
981
|
+
config_error: "config_error";
|
|
982
|
+
llm_error: "llm_error";
|
|
983
|
+
}>>;
|
|
984
|
+
}, z.core.$strict>;
|
|
985
|
+
schemaVersion: z.ZodLiteral<2>;
|
|
986
|
+
markId: z.ZodString;
|
|
987
|
+
feedbackSource: z.ZodObject<{
|
|
988
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
989
|
+
testIndex: z.ZodNumber;
|
|
990
|
+
testId: z.ZodOptional<z.ZodString>;
|
|
991
|
+
stepIndex: z.ZodOptional<z.ZodNumber>;
|
|
992
|
+
kind: z.ZodEnum<{
|
|
993
|
+
"false-fail": "false-fail";
|
|
994
|
+
"false-pass": "false-pass";
|
|
995
|
+
"confirmed-bug": "confirmed-bug";
|
|
996
|
+
}>;
|
|
997
|
+
}, z.core.$strict>;
|
|
998
|
+
runTraceRef: z.ZodObject<{
|
|
999
|
+
runId: z.ZodType<_vostride_agent_qa_schema.RunId, unknown, z.core.$ZodTypeInternals<_vostride_agent_qa_schema.RunId, unknown>>;
|
|
1000
|
+
runSlug: z.ZodString;
|
|
1001
|
+
}, z.core.$strict>;
|
|
1002
|
+
kind: z.ZodLiteral<"no-draftable-fix">;
|
|
1003
|
+
}, z.core.$strict>], "kind">>;
|
|
1004
|
+
}, z.core.$strict>;
|
|
1005
|
+
type MarkIntent = z.infer<typeof intentSchema>;
|
|
1006
|
+
declare class MarkLedgerBusyError extends Error {
|
|
1007
|
+
constructor();
|
|
1008
|
+
}
|
|
1009
|
+
declare class MarkLedgerCorruptError extends Error {
|
|
1010
|
+
readonly line: number;
|
|
1011
|
+
constructor(line: number);
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* The run's unfinished-mark record cannot be resumed, refused by the record's own name. Nothing is
|
|
1015
|
+
* migrated or read further; the message names the file to remove, after which the run can be
|
|
1016
|
+
* marked again.
|
|
1017
|
+
*/
|
|
1018
|
+
declare class MarkIntentUnusableError extends Error {
|
|
1019
|
+
readonly intentPath: string;
|
|
1020
|
+
readonly reason: 'earlier-version' | 'unreadable' | 'mismatched';
|
|
1021
|
+
constructor(intentPath: string, reason: 'earlier-version' | 'unreadable' | 'mismatched');
|
|
1022
|
+
}
|
|
1023
|
+
/** The one latest-per-address rule, over receipts a caller has already read once. */
|
|
1024
|
+
declare function latestMarkReceiptsPerAddress(receipts: readonly MarkReceipt[]): MarkReceipt[];
|
|
1025
|
+
declare function latestMarkReceiptFor(receipts: readonly MarkReceipt[], runId: string, address: MarkAddress): MarkReceipt | undefined;
|
|
1026
|
+
declare class MarkLedgerNoRunError extends Error {
|
|
1027
|
+
constructor();
|
|
1028
|
+
}
|
|
1029
|
+
/** The per-run marks ledger under the run directory. */
|
|
1030
|
+
declare class FsMarkLedger {
|
|
1031
|
+
private readonly dir;
|
|
1032
|
+
private readonly file;
|
|
1033
|
+
private readonly lock;
|
|
1034
|
+
private readonly runId;
|
|
1035
|
+
private readonly runSlug;
|
|
1036
|
+
private inTransaction;
|
|
1037
|
+
private intentValue;
|
|
1038
|
+
constructor(config: {
|
|
1039
|
+
root: string;
|
|
1040
|
+
runId: string;
|
|
1041
|
+
});
|
|
1042
|
+
read(): MarkReceipt[];
|
|
1043
|
+
latestPerAddress(): MarkReceipt[];
|
|
1044
|
+
latestFor(address: MarkAddress): MarkReceipt | undefined;
|
|
1045
|
+
/** Private resumable state is admitted only while this run's existing lock is held. */
|
|
1046
|
+
prepareIntent(mark: MarkReceipt, operationId: string): MarkIntent;
|
|
1047
|
+
checkpointIntent(value: MarkIntent): MarkIntent;
|
|
1048
|
+
transact(fn: (nextOrdinal: number) => Promise<Omit<MarkReceipt, 'ordinal'> | undefined>): Promise<MarkReceipt | undefined>;
|
|
1049
|
+
append(record: Omit<MarkReceipt, 'ordinal'>): Promise<MarkReceipt | undefined>;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1884
1052
|
/**
|
|
1885
1053
|
* How many jobs one `resumePending` call will run before it refuses to continue.
|
|
1886
1054
|
*
|
|
@@ -1893,7 +1061,7 @@ declare const JOB_RECOVERY_MAX_RESUMED_JOBS = 64;
|
|
|
1893
1061
|
interface ComposeJobRecoveryInput {
|
|
1894
1062
|
/** The project's runtime root, i.e. `<configDir>/.agent-qa`. Absolute. */
|
|
1895
1063
|
readonly agentQaRoot: string;
|
|
1896
|
-
/** Every column and dump row this host writes is stamped from here
|
|
1064
|
+
/** Every column and dump row this host writes is stamped from here. */
|
|
1897
1065
|
readonly clock: ClockPort;
|
|
1898
1066
|
/** Ids derived from `(kind, idempotencyKey)`, so a resumed chain addresses the same rows. */
|
|
1899
1067
|
readonly idSource: JobIdSource;
|
|
@@ -1926,35 +1094,18 @@ interface JobRecoveryHost {
|
|
|
1926
1094
|
}
|
|
1927
1095
|
declare function composeJobRecovery(input: ComposeJobRecoveryInput): JobRecoveryHost;
|
|
1928
1096
|
|
|
1929
|
-
/** Directory segment under the agent-qa runtime root. Gitignored, per D-17. */
|
|
1930
1097
|
declare const CHAT_SESSIONS_SUBDIR = "sessions";
|
|
1931
|
-
/** A caller-supplied session id that could not be a path segment
|
|
1098
|
+
/** A caller-supplied session id that could not be a path segment. */
|
|
1932
1099
|
declare class InvalidChatSessionIdError extends Error {
|
|
1933
1100
|
readonly sessionId: string;
|
|
1934
1101
|
readonly name = "InvalidChatSessionIdError";
|
|
1935
1102
|
constructor(sessionId: string);
|
|
1936
1103
|
}
|
|
1937
|
-
/**
|
|
1938
|
-
* A session id that names no session.
|
|
1939
|
-
*
|
|
1940
|
-
* A REFUSAL and never a create (D-17, RESEARCH Open Q4). Creating a fresh session for a mistyped
|
|
1941
|
-
* `--session` would tell a person their history was lost when in fact it was never looked at, and
|
|
1942
|
-
* would do so in the one direction no later read can undo.
|
|
1943
|
-
*/
|
|
1944
1104
|
declare class UnknownChatSessionError extends Error {
|
|
1945
1105
|
readonly sessionId: string;
|
|
1946
1106
|
readonly name = "UnknownChatSessionError";
|
|
1947
1107
|
constructor(sessionId: string);
|
|
1948
1108
|
}
|
|
1949
|
-
/**
|
|
1950
|
-
* A session somebody is already holding open (Phase 392 plan 12, T-392-BUSY).
|
|
1951
|
-
*
|
|
1952
|
-
* A REFUSAL BY NAME rather than a second descriptor. Two handles on one file would interleave two
|
|
1953
|
-
* turns inside a single conversation — the same damage the cross-session aliasing did, one level
|
|
1954
|
-
* down — and it is exactly what a double-submit of one `sessionId` over the daemon socket asks for.
|
|
1955
|
-
* The remedy is to wait for the holder, which is why the id is on the error rather than only in
|
|
1956
|
-
* the message.
|
|
1957
|
-
*/
|
|
1958
1109
|
declare class ChatSessionBusyError extends Error {
|
|
1959
1110
|
readonly sessionId: string;
|
|
1960
1111
|
readonly name = "ChatSessionBusyError";
|
|
@@ -1987,20 +1138,6 @@ interface CreateJsonlSessionLogOptions {
|
|
|
1987
1138
|
readonly model: () => string;
|
|
1988
1139
|
/** The toolset fingerprint at open, on the same thunk reasoning as `model` above. */
|
|
1989
1140
|
readonly toolsetHash: () => string;
|
|
1990
|
-
/**
|
|
1991
|
-
* WHICH DOOR THIS LOG BELONGS TO (Phase 400 plan 03, D-04). Absent ⇒ no tag is written.
|
|
1992
|
-
*
|
|
1993
|
-
* A VALUE AND NOT A THUNK, which is the opposite of `model` and `toolsetHash` above and for the
|
|
1994
|
-
* mirror of their reason. Those are resolved lazily because a composition's model can arrive
|
|
1995
|
-
* after the log does and can drift afterwards; a surface cannot. Which door composed this host is
|
|
1996
|
-
* decided at the composition root and is a constant for the life of the process, so a thunk would
|
|
1997
|
-
* be a seam for a value to change through — and a header is written once and never rewritten,
|
|
1998
|
-
* so a changing surface has nowhere to go.
|
|
1999
|
-
*
|
|
2000
|
-
* ABSENT IS THE PRE-400 CLI-CHAT POSTURE, stated in `ChatSessionHeader.surface` and preserved
|
|
2001
|
-
* here: a host that names no surface writes a header byte-identical to the ones every build
|
|
2002
|
-
* before this one wrote.
|
|
2003
|
-
*/
|
|
2004
1141
|
readonly surface?: string;
|
|
2005
1142
|
/** Random source for the id suffix, injectable so a test can pin an id. */
|
|
2006
1143
|
readonly random?: () => number;
|
|
@@ -2011,15 +1148,6 @@ interface ChatSessionListEntry {
|
|
|
2011
1148
|
readonly createdAt: string;
|
|
2012
1149
|
/** The model in force when the session OPENED. Drift after that is `model_change` events. */
|
|
2013
1150
|
readonly model: string;
|
|
2014
|
-
/**
|
|
2015
|
-
* Event lines on the file, counted without parsing one.
|
|
2016
|
-
*
|
|
2017
|
-
* An EVENT count and not a turn count, and the difference is not a shortcut. A turn count is not
|
|
2018
|
-
* a header fact and cannot become one — the header is written once and never rewritten, which is
|
|
2019
|
-
* the property CHAT-05 asks for by name — so the only way to produce one is to parse every line
|
|
2020
|
-
* of every log, which is the work a listing exists to avoid. The line count answers "is there
|
|
2021
|
-
* anything in here" for a fraction of the cost, and `open()` answers everything else.
|
|
2022
|
-
*/
|
|
2023
1151
|
readonly eventCount: number;
|
|
2024
1152
|
}
|
|
2025
1153
|
/** One session file the listing could not read, surfaced as data rather than thrown over. */
|
|
@@ -2041,18 +1169,6 @@ interface ChatSessionListing {
|
|
|
2041
1169
|
* guard that protects a supplied one.
|
|
2042
1170
|
*/
|
|
2043
1171
|
declare function mintChatSessionId(nowIso: string, random: () => number): string;
|
|
2044
|
-
/**
|
|
2045
|
-
* Every session under one runtime root, read from headers alone (D-17).
|
|
2046
|
-
*
|
|
2047
|
-
* A DAMAGED FILE IS DATA, NOT AN EXCEPTION — the posture the grant ledger had (391; deleted in 432-18).
|
|
2048
|
-
* A corrupt neighbour costs the caller that one entry and nothing else; throwing would let a single
|
|
2049
|
-
* unreadable file hide every healthy session from the person trying to find their conversation.
|
|
2050
|
-
*
|
|
2051
|
-
* It reads through the real filesystem with no injection seam, and that absence is on purpose: the
|
|
2052
|
-
* seam beside `createJsonlSessionLogOn` exists because syscall ORDER is a durability property no
|
|
2053
|
-
* crash test can observe. A listing has no such property. What it returns is its whole contract,
|
|
2054
|
-
* and a temp directory proves that directly.
|
|
2055
|
-
*/
|
|
2056
1172
|
declare function listSessions(root: string): ChatSessionListing;
|
|
2057
1173
|
declare function createJsonlSessionLog(options: CreateJsonlSessionLogOptions): SessionLogPort;
|
|
2058
1174
|
|
|
@@ -2068,20 +1184,6 @@ interface MemorySessionLog extends SessionLogPort {
|
|
|
2068
1184
|
}
|
|
2069
1185
|
declare function createMemorySessionLog(options: CreateMemorySessionLogOptions): MemorySessionLog;
|
|
2070
1186
|
|
|
2071
|
-
/**
|
|
2072
|
-
* The local implementation of the neutral persistence port.
|
|
2073
|
-
*
|
|
2074
|
-
* 2026-07-29 (Phase 385 plan 02, D-06): this alias now covers approvals and patches ONLY.
|
|
2075
|
-
* Job rows and checkpoints left the port for the agent job queue's own store, whose verbs are
|
|
2076
|
-
* compound and transactional rather than generic CRUD, and the conversation surface left it
|
|
2077
|
-
* entirely. The alias is deliberately narrower than the package's name suggests, and saying
|
|
2078
|
-
* so here is cheaper than letting a later reader infer that anything job-shaped belongs
|
|
2079
|
-
* behind it.
|
|
2080
|
-
*
|
|
2081
|
-
* The job store itself is not on this barrel. It is reachable by relative path within the
|
|
2082
|
-
* package and is published, if at all, by the composition root — a store that any importer
|
|
2083
|
-
* can construct is a second way to open the database beside the one the host owns.
|
|
2084
|
-
*/
|
|
2085
1187
|
type LocalPersistenceStore = PersistencePort;
|
|
2086
1188
|
|
|
2087
|
-
export { type ApplyKnowledgeChangeInput, type AttachableRunSession, BRIEF_CEILING, BRIEF_FRACTION, type BuildMemberRunConfigInput, CAUTION_FRACTION, CHAT_PLANNER_CALLER, CHAT_RESOLVER_CALLER, CHAT_SESSIONS_SUBDIR, type CandidateProsePosture, ChatSessionBusyError, ChatSessionHeaderError, type ChatSessionListEntry, type ChatSessionListing, type ComposeJobRecoveryInput, type ComposeLocalAgentInput, type ComputeKnowledgeBudgetsInput, type ConstructKnowledgeReaderInput, type CreateEvidenceBlobReaderInput, type CreateJsonlSessionLogOptions, type CreateKnowledgeReviewInput, type CreateMemorySessionLogOptions, DIGEST_JOB_ID_SOURCE, type DraftAuthoringPort, type DraftParseOutcome, type DraftStageOutcome, GLOBAL_RECORD_CAP, InvalidChatSessionIdError, JOB_RECOVERY_MAX_RESUMED_JOBS, type JobRecoveryHost, type KnowledgeBudgets, LOCAL_CURATION_CAPABILITIES, LOCAL_DAEMON_CAPABILITIES, LOCAL_KNOWLEDGE_PROBES, LocalAgentClosedError, type LocalAgentHost, type LocalAgentJobs, type LocalCurationCapabilities, type LocalDaemonCapabilities, type LocalKnowledgeMaintenanceCapabilities, type LocalKnowledgeProbeCapabilities, type LocalPersistenceStore, MIN_BRIEF, MIN_CAUTION, MIN_MEMORY_TOOL_CONTEXT_WINDOW, type MemorySessionLog, type OpenRunKnowledgeCompositionInput, type ParsedDraftDescriptor, type PromoteWithReceiptsInput, READ_BODY_FRACTION,
|
|
1189
|
+
export { type ApplyKnowledgeChangeInput, type AttachableRunSession, BRIEF_CEILING, BRIEF_FRACTION, type BuildMemberRunConfigInput, CAUTION_FRACTION, CHAT_PLANNER_CALLER, CHAT_RESOLVER_CALLER, CHAT_SESSIONS_SUBDIR, type CandidateProsePosture, ChatSessionBusyError, ChatSessionHeaderError, type ChatSessionListEntry, type ChatSessionListing, type ComposeJobRecoveryInput, type ComposeLocalAgentInput, type ComputeKnowledgeBudgetsInput, type ConstructKnowledgeReaderInput, type CreateEvidenceBlobReaderInput, type CreateJsonlSessionLogOptions, type CreateKnowledgeReviewInput, type CreateMemorySessionLogOptions, DIGEST_JOB_ID_SOURCE, type DraftAuthoringPort, type DraftParseOutcome, type DraftStageOutcome, FsMarkLedger, GLOBAL_RECORD_CAP, InvalidChatSessionIdError, JOB_RECOVERY_MAX_RESUMED_JOBS, type JobRecoveryHost, type KnowledgeBudgets, LOCAL_CURATION_CAPABILITIES, LOCAL_DAEMON_CAPABILITIES, LOCAL_KNOWLEDGE_PROBES, LocalAgentClosedError, type LocalAgentHost, type LocalAgentJobs, type LocalCurationCapabilities, type LocalDaemonCapabilities, type LocalKnowledgeMaintenanceCapabilities, type LocalKnowledgeProbeCapabilities, type LocalPersistenceStore, MARKS_LEDGER_FILE, MARKS_LEDGER_LOCK_FILE, MARK_INTENT_FILE, MIN_BRIEF, MIN_CAUTION, MIN_MEMORY_TOOL_CONTEXT_WINDOW, MarkIntentUnusableError, MarkLedgerBusyError, MarkLedgerCorruptError, MarkLedgerNoRunError, type MemorySessionLog, type OpenRunKnowledgeCompositionInput, type ParsedDraftDescriptor, type PromoteWithReceiptsInput, READ_BODY_FRACTION, type RecordGateReceiptInput, type RefusedChatSessionFile, type RetrievalRungResolver, type RunAssembler, type RunAssemblyContext, type RunConfigDigests, type RunDigestMemberInput, type RunExecutionContext, type RunExecutionPort, RunIdAlreadyInUseError, RunIdNotMintedError, type RunInvocationCoreOptions, type RunKnowledgeComposition, type RunPersistencePorts, RunProducedNoEventsError, type RunQuarantineSnapshotInput, type RunSubscriberHandle, SUITE_LIFECYCLE_LANE, SYSTEM_CLOCK, SuiteBoundaryWhileLiveError, type SuiteLifecycle, type SuiteLifecycleHooks, type SuiteMemberBinding, type SuiteMemberLease, type SuiteTextEntry, type SweepEntityIndexInput, type SweepEntityIndexOutcome, UNCLAIMABLE_BY_PROSE_POSTURE, UnknownChatSessionError, WEAK_MODEL_CAP_SCALE, applyKnowledgeChange, buildMemberRunConfig, buildRunPorts, buildScreenshotCompressor, buildSuiteMemberExecutor, composeJobRecovery, composeLocalAgent, computeKnowledgeBudgets, computeRunConfigDigests, constructKnowledgeReader, createEvidenceBlobReader, createFrozenKnowledgeReader, createJsonlSessionLog, createKnowledgeReader, createKnowledgeReview, createLocalRunInvocation, createMemorySessionLog, createRunInvocationCore, createRunsReader, createSuiteLifecycle, latestMarkReceiptFor, latestMarkReceiptsPerAddress, listSessions, lookupEvidenceBlob, memoryToolGate, mintChatSessionId, openRunKnowledgeComposition, readEvidenceBlobBytes, registerAdapterLiveStream, resolveBuildTagSetting, resolveHostRetrievalRung, resolveRunBuildOrdinal, resolveRunExecutionContext, resolveRunQuarantineSnapshot, scaledRecordCap, statEvidenceBlob, sweepEntityIndexProjection, toMemberTest };
|