@rulvar/core 1.53.0 → 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +170 -2
- package/dist/index.js +735 -14
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2958,6 +2958,26 @@ type CoreEvents = {
|
|
|
2958
2958
|
* charge. Absent means every contributing turn reported exact usage.
|
|
2959
2959
|
*/
|
|
2960
2960
|
usageApprox?: boolean;
|
|
2961
|
+
/**
|
|
2962
|
+
* The semantic completion lift (RV-207 tail): present when the
|
|
2963
|
+
* workflow reported semantic completion through the completion
|
|
2964
|
+
* envelope contract: an `ok`/`exhausted` run whose result value is
|
|
2965
|
+
* an object carrying a valid `completion` literal, or an `error`
|
|
2966
|
+
* run whose typed error data carries one (the orchestrator
|
|
2967
|
+
* acceptance path emits both). Transport status says whether the
|
|
2968
|
+
* run ran; completion says whether the work is COMPLETE: an
|
|
2969
|
+
* accepted degraded run is `status: 'ok'` with `completion:
|
|
2970
|
+
* 'partial'`. Replay recomputes the same value from the re-executed
|
|
2971
|
+
* workflow, so the field is identical live and replayed. Absent
|
|
2972
|
+
* when the workflow makes no completion claim.
|
|
2973
|
+
*/
|
|
2974
|
+
completion?: "complete" | "partial" | "rejected";
|
|
2975
|
+
/**
|
|
2976
|
+
* Settled child statuses by status name, lifted from the same
|
|
2977
|
+
* envelope (or typed error data) when it carries a valid record of
|
|
2978
|
+
* nonnegative integers. Absent otherwise.
|
|
2979
|
+
*/
|
|
2980
|
+
childStatusCounts?: Record<string, number>;
|
|
2961
2981
|
} | {
|
|
2962
2982
|
type: "phase:start";
|
|
2963
2983
|
phase: string;
|
|
@@ -5313,6 +5333,48 @@ declare function hashRunArgs(args: unknown): string | undefined;
|
|
|
5313
5333
|
declare function hashRunOutput(value: unknown): string | undefined;
|
|
5314
5334
|
declare function createEngine(options: CreateEngineOptions): Engine;
|
|
5315
5335
|
//#endregion
|
|
5336
|
+
//#region src/orchestrator/claims.d.ts
|
|
5337
|
+
/**
|
|
5338
|
+
* Repeated-claim deduplication (RV-211 remainder): a PURE, deterministic
|
|
5339
|
+
* fold that removes byte-repeated claim lines across children BEFORE any
|
|
5340
|
+
* model call, so the synthesis invocation never spends context re-reading
|
|
5341
|
+
* what several children reported identically. Matching is deliberately
|
|
5342
|
+
* conservative: lines compare by whitespace-collapsed exact equality
|
|
5343
|
+
* (trim, inner runs of whitespace to one space), never fuzzily, so two
|
|
5344
|
+
* DISTINCT claims can never merge; the first occurrence survives verbatim
|
|
5345
|
+
* and every later occurrence is dropped and indexed. Empty lines are
|
|
5346
|
+
* structure, not claims: they always survive.
|
|
5347
|
+
*
|
|
5348
|
+
* Public docs: https://docs.rulvar.com/guide/orchestration-modes
|
|
5349
|
+
*/
|
|
5350
|
+
/** One claim reported more than once across the input rows. */
|
|
5351
|
+
interface RepeatedClaim {
|
|
5352
|
+
/** The first-seen line, verbatim. */
|
|
5353
|
+
claim: string;
|
|
5354
|
+
/** Reporters in input order; the first entry made the surviving copy. */
|
|
5355
|
+
nodeIds: string[];
|
|
5356
|
+
/** Total occurrences across all rows, the surviving one included. */
|
|
5357
|
+
count: number;
|
|
5358
|
+
}
|
|
5359
|
+
interface DedupedClaims {
|
|
5360
|
+
/** The input rows with every repeated line's later occurrences removed. */
|
|
5361
|
+
rows: {
|
|
5362
|
+
nodeId: string;
|
|
5363
|
+
text: string;
|
|
5364
|
+
}[];
|
|
5365
|
+
/** Claims seen more than once, in first-occurrence order. */
|
|
5366
|
+
repeated: RepeatedClaim[];
|
|
5367
|
+
}
|
|
5368
|
+
/**
|
|
5369
|
+
* Removes later occurrences of repeated claim lines across the rows and
|
|
5370
|
+
* indexes each repeated claim with its reporters. Deterministic: output
|
|
5371
|
+
* depends only on the input order and bytes.
|
|
5372
|
+
*/
|
|
5373
|
+
declare function dedupeRepeatedClaims(rows: {
|
|
5374
|
+
nodeId: string;
|
|
5375
|
+
text: string;
|
|
5376
|
+
}[]): DedupedClaims;
|
|
5377
|
+
//#endregion
|
|
5316
5378
|
//#region src/orchestrator/finish-validators.d.ts
|
|
5317
5379
|
/**
|
|
5318
5380
|
* One child as the finish validators see it (the RV-202 provenance
|
|
@@ -5945,6 +6007,12 @@ declare const DEFAULT_FINISH_MAX_REPAIRS = 1;
|
|
|
5945
6007
|
*/
|
|
5946
6008
|
declare const DEFAULT_SYNTHESIS_MAX_TURNS = 4;
|
|
5947
6009
|
/**
|
|
6010
|
+
* Default maxTurns of ONE incremental synthesis note (RV-211 remainder):
|
|
6011
|
+
* a note summarizes a single settled child into a bounded finish call,
|
|
6012
|
+
* so it needs less headroom than the full synthesis invocation.
|
|
6013
|
+
*/
|
|
6014
|
+
declare const DEFAULT_SYNTHESIS_NOTE_MAX_TURNS = 2;
|
|
6015
|
+
/**
|
|
5948
6016
|
* The opt in deterministic validation of the orchestrator finish result
|
|
5949
6017
|
* (the v1.40.0 improvement plan's RV-204 slice). Every SCHEMA valid
|
|
5950
6018
|
* finish({ result }) call first passes the configured host validators;
|
|
@@ -6075,9 +6143,71 @@ interface OrchestrateSynthesis {
|
|
|
6075
6143
|
* Admission estimate for the synthesize invocation, like
|
|
6076
6144
|
* AgentOpts.estCost: under a tight orchestrator cap the default
|
|
6077
6145
|
* reserve (full maxOutputTokens pricing) can refuse the dispatch; an
|
|
6078
|
-
* explicit estimate is the host speaking.
|
|
6146
|
+
* explicit estimate is the host speaking. In 'incremental' mode the
|
|
6147
|
+
* estimate applies to EACH note invocation.
|
|
6079
6148
|
*/
|
|
6080
6149
|
estCost?: number;
|
|
6150
|
+
/**
|
|
6151
|
+
* The synthesis shape (RV-211 remainder). Default 'single': one
|
|
6152
|
+
* post-fan-in synthesize invocation composes the final result from the
|
|
6153
|
+
* draft and the whole settled digest. 'incremental': every settled
|
|
6154
|
+
* child triggers ONE bounded synthesize-role NOTE invocation as soon
|
|
6155
|
+
* as it settles (concurrent with the still-running fan-out, which is
|
|
6156
|
+
* what moves synthesis wall time off the post-fan-in critical path),
|
|
6157
|
+
* and the FINAL result is a DETERMINISTIC reconciliation, never
|
|
6158
|
+
* another model call: an {@link IncrementalSynthesisResult} envelope
|
|
6159
|
+
* composed from the draft and the notes in spawn order. The tradeoffs
|
|
6160
|
+
* are explicit: notes are paid DURING the run, so an acceptance
|
|
6161
|
+
* rejection can no longer guarantee "a rejected run never paid for
|
|
6162
|
+
* synthesis"; and because the reconciliation has no model-composed
|
|
6163
|
+
* finish, `finishValidation` cannot bind it: configuring both is a
|
|
6164
|
+
* ConfigError at intake. A note that dies falls back to the child's
|
|
6165
|
+
* raw digest summary under a journaled per-child
|
|
6166
|
+
* 'orchestrator_synthesis_note_fallback' decision and a warn log.
|
|
6167
|
+
* Cap paths are unchanged: a capped run settles through the reserved
|
|
6168
|
+
* finalizer and never reconciles.
|
|
6169
|
+
*/
|
|
6170
|
+
mode?: "single" | "incremental";
|
|
6171
|
+
/**
|
|
6172
|
+
* Deduplicate repeated claim lines across children BEFORE any model
|
|
6173
|
+
* call (RV-211 remainder; default false, and the prompt stays byte
|
|
6174
|
+
* identical when unset). In 'single' mode the digest entering the
|
|
6175
|
+
* synthesis prompt keeps only the FIRST occurrence of every repeated
|
|
6176
|
+
* line and a REPEATED CLAIMS index (each claim with its reporters)
|
|
6177
|
+
* rides the prompt beside it. In 'incremental' mode the deterministic
|
|
6178
|
+
* reconciliation dedupes the note texts the same way and the envelope
|
|
6179
|
+
* carries the `repeatedClaims` index. Matching is whitespace-collapsed
|
|
6180
|
+
* exact line equality: nothing fuzzy ever merges two distinct claims.
|
|
6181
|
+
*/
|
|
6182
|
+
dedupeClaims?: boolean;
|
|
6183
|
+
/**
|
|
6184
|
+
* UsageLimits of ONE incremental note invocation; default
|
|
6185
|
+
* { maxTurns: 2 }. Ignored in 'single' mode.
|
|
6186
|
+
*/
|
|
6187
|
+
noteLimits?: UsageLimits;
|
|
6188
|
+
}
|
|
6189
|
+
/**
|
|
6190
|
+
* The deterministic reconciliation envelope an 'incremental' synthesis
|
|
6191
|
+
* returns as the run result (RV-211 remainder): the coordination draft
|
|
6192
|
+
* plus one section per settled child in spawn order, each carrying the
|
|
6193
|
+
* child's terminal status and its note (the note invocation's finish
|
|
6194
|
+
* output, or the child's raw digest summary when the note fell back).
|
|
6195
|
+
* With `dedupeClaims`, repeated claim lines keep their first occurrence
|
|
6196
|
+
* only and the `repeatedClaims` index lists each with its reporters.
|
|
6197
|
+
* Everything here derives from journaled state, so a resume reproduces
|
|
6198
|
+
* the envelope byte for byte with zero paid calls.
|
|
6199
|
+
*/
|
|
6200
|
+
interface IncrementalSynthesisResult {
|
|
6201
|
+
synthesis: "incremental";
|
|
6202
|
+
draft: unknown;
|
|
6203
|
+
sections: {
|
|
6204
|
+
nodeId: string;
|
|
6205
|
+
logicalTaskId: string; /** The child's terminal status. */
|
|
6206
|
+
status: string; /** The note invocation's terminal status ('ok' unless it fell back). */
|
|
6207
|
+
noteStatus: string;
|
|
6208
|
+
note: string;
|
|
6209
|
+
}[];
|
|
6210
|
+
repeatedClaims?: RepeatedClaim[];
|
|
6081
6211
|
}
|
|
6082
6212
|
declare const ORCHESTRATE_WORKFLOW_NAME = "rulvar-orchestrate";
|
|
6083
6213
|
/**
|
|
@@ -6990,6 +7120,44 @@ declare class GitWorktreeProvider implements IsolationProvider {
|
|
|
6990
7120
|
}>;
|
|
6991
7121
|
}
|
|
6992
7122
|
//#endregion
|
|
7123
|
+
//#region src/tools/research.d.ts
|
|
7124
|
+
interface RepositoryResearchToolsetOptions {
|
|
7125
|
+
/** The confining directory root; everything resolves under it. */
|
|
7126
|
+
root: string;
|
|
7127
|
+
/** Rows per list/search/evidence page; default 50. */
|
|
7128
|
+
pageSize?: number;
|
|
7129
|
+
/** Content budget of one read_file page in characters; default 4000. */
|
|
7130
|
+
readPageChars?: number;
|
|
7131
|
+
/** Files larger than this many bytes are refused; default 262144. */
|
|
7132
|
+
maxFileBytes?: number;
|
|
7133
|
+
/** Walk ceiling per call (files visited); default 20000. */
|
|
7134
|
+
maxScannedFiles?: number;
|
|
7135
|
+
/**
|
|
7136
|
+
* Extra ignored basenames (files and directories), merged over the
|
|
7137
|
+
* always-on defaults '.git' and 'node_modules'.
|
|
7138
|
+
*/
|
|
7139
|
+
ignore?: string[];
|
|
7140
|
+
/** Walk dot-entries too; default false. */
|
|
7141
|
+
includeHidden?: boolean;
|
|
7142
|
+
}
|
|
7143
|
+
/** One verified evidence entry recorded by `record_evidence`. */
|
|
7144
|
+
interface ResearchEvidenceEntry {
|
|
7145
|
+
claim: string;
|
|
7146
|
+
/** Root-relative POSIX path, verified to exist at record time. */
|
|
7147
|
+
file: string;
|
|
7148
|
+
/** 'N' or 'N-M', 1-based, verified inside the file's line count. */
|
|
7149
|
+
lines?: string;
|
|
7150
|
+
/** Verified verbatim substring of the file at record time. */
|
|
7151
|
+
quote?: string;
|
|
7152
|
+
}
|
|
7153
|
+
interface RepositoryResearchToolset {
|
|
7154
|
+
/** list_files, search_files, read_file, record_evidence, list_evidence. */
|
|
7155
|
+
tools: ToolDef[];
|
|
7156
|
+
/** Snapshot copy of the evidence collected so far, in record order. */
|
|
7157
|
+
evidence(): ResearchEvidenceEntry[];
|
|
7158
|
+
}
|
|
7159
|
+
declare function repositoryResearchToolset(options: RepositoryResearchToolsetOptions): RepositoryResearchToolset;
|
|
7160
|
+
//#endregion
|
|
6993
7161
|
//#region src/journal/scope.d.ts
|
|
6994
7162
|
/**
|
|
6995
7163
|
* Scope-path grammar (M1-T04): deterministic structural paths, independent
|
|
@@ -7756,4 +7924,4 @@ interface SandboxBridge {
|
|
|
7756
7924
|
declare const SANDBOX_AGENT_OPT_KEYS: readonly string[];
|
|
7757
7925
|
declare function createSandboxBridge(ctx: Ctx<never>, options: SandboxBridgeOptions): SandboxBridge;
|
|
7758
7926
|
//#endregion
|
|
7759
|
-
export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, type AgentInvocationRow, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, AuditRunsOptions, BUDGET_ABORT_REASON, BaseAppend, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildArtifactPage, ChildIdentityInput, ChildResultPage, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, type CriticalPath, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DerivedKey, DeriverRegistry, type DeterminismConfig, DeterminismError, type DeterminismEvents, type DeterminismMode, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, FinishValidationChild, FinishValidationInput, FinishValidationSpec, FinishValidationVerdict, FinishValidator, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, InvocationRole, type InvocationTable, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, MatchResult, McpConfig, McpToolSource, MechanicalGateProfile, MechanicalGateVerdict, type MetaLookupStore, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateAcceptance, OrchestrateOptions, OrchestrateSynthesis, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, type PhaseRow, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, RandIdentityInput, RandPayload, ReconcileOptions, ReconcileResult, RefEntryAppender, RefEntryClassification, RefusalInfo, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunAuditVerdict, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStateAudit, RunStatus, RuntimeEventSink, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, requiredFieldsValidator, requiredSectionsValidator, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
|
7927
|
+
export { AWAIT_SCHEMA, AbandonAttempt, AbandonFold, AbandonPayload, AbandonedSpendView, AbortClass, type AdaptiveEvents, AdmissionController, AdmissionDecision, AdmissionRejectedError, AdmissionStatsBefore, AdmitLineage, AdmitRejectReason, AdmitSpec, AdmitVerdict, AgentCallError, AgentError, type AgentEvents, AgentIdentityInput, type AgentInvocationRow, AgentOpts, AgentProfile, AgentProfilePermissions, AgentResult, AgentResultMeta, AgentStatus, ApproachSignatureInputs, ApprovalDecision, ApprovalIdentityInput, Artifact, AttemptOutcomeClass, AuditRunsOptions, BUDGET_ABORT_REASON, BaseAppend, BriefOpts, BudgetAccountView, BudgetDefaults, BudgetExhaustedError, BudgetExhaustionDiagnostics, BudgetHooks, BudgetReserve, type Bytes, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, CacheHint, CacheTtl, CanUseTool, CanonicalId, CanonicalIdentity, CanonicalLadderSpec, CanonicalModelSpec, ChatEvent, ChatRequest, CheckpointState, ChildArtifactPage, ChildIdentityInput, ChildResultPage, type ClaimClass, type ClaimOp, type ClaimStatus, ClaimValidationOptions, CollectOpts, CollectedTurn, CompactionConfig, CompiledPermissionChain, CompiledWorkflow, ConfigError, type CoreEvents, CostAttribution, CostAttributionFacts, CostReport, CreateEngineOptions, type CriticalPath, Ctx, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DebitResult, DeclaredLadder, DedupIndex, DedupNote, DedupedClaims, DerivedKey, DeriverRegistry, type DeterminismConfig, DeterminismError, type DeterminismEvents, type DeterminismMode, DispositionRule, DispositionTable, DonorCandidate, DonorRef, DroppedItem, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EffectiveUsageLimits, Effort, Engine, EngineDefaults, EntryKind, EntryRef, EntryStatus, ErrorClass, ErrorCode, ErrorPolicy, EscalatedResult, EscalationDecision, EscalationDecisionAbortedError, EscalationDigest, EscalationKind, EscalationLimits, EscalationOptions, EscalationReport, EscalationRequest, EventBus, type EvidenceRef, type ExplorationSummary, ExtensionAppendInput, ExtensionDispatchSpec, ExternalIdentityInput, ExternalRegistry, ExtractNecessityInput, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FailoverTarget, FailoverTrigger, FallbackField, FallbackTrigger, FileModelKnowledgeStore, FileModelKnowledgeStoreOptions, FileTranscriptStore, FinishInfo, FinishValidationChild, FinishValidationInput, FinishValidationSpec, FinishValidationVerdict, FinishValidator, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, Gate, GateAudit, type GateRecord, GitWorktreeProvider, GitWorktreeProviderOptions, GraftBoot, HashVersion, HookVerdict, INBOX_PROPOSAL_TTL_DAYS, IdentityInput, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, IncrementalSynthesisResult, InvalidResolutionError, InvocationRole, type InvocationTable, type IsolationProvider, type IsolationSpec, Issue$1 as Issue, JournalCompatSubCode, JournalCompatibilityError, JournalEntry, JournalMatcher, JournalMissError, JournalOperation, JournalOrderViolation, JournalSerializationHook, type JournalStore, type Json, JsonSchema, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, type KbProposal, type KbProposalTrigger, KeyDeriver, KeyRing, KeyedLimiter, KnowledgeCasError, type KnowledgeSnapshot, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LadderSpec, type LeasableStore, type Lease, LeaseHeldError, Ledger, LineageCounters, LineageIndex, LineageRef, LineageRelation, LineageStats, LogicalTaskId, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, MatchResult, McpConfig, McpToolSource, MechanicalGateProfile, MechanicalGateVerdict, type MetaLookupStore, type ModelCaps, ModelChoice, type ModelClaim, ModelEpochInputs, type ModelKnowledgeHandle, type ModelKnowledgeStore, ModelListConstraint, ModelRef, ModelRetry, ModelSpec, Msg, NoProgressDetector, NodeId, NodeLinkValue, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OnEscalation, OperationDisposition, OrchestrateAcceptance, OrchestrateOptions, OrchestrateSynthesis, OrchestratorBudgetSpec, OrchestratorCapConfigError, OrchestratorExtension, OrchestratorExtensionIO, OrchestratorRuntime, Out, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, Part, PendingExternal, PendingToolTurn, PermissionConfig, PermissionGate, PermissionHook, PermissionPreset, PermissionRule, PermissionVerdict, type PhaseRow, PhaseTarget, PipelineCollected, PipelineOpts, PlanInvariantError, PriceTable, PricedUsage, type Pricing, type PricingTier, type ProviderAdapter, QualityFloors, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, RandIdentityInput, RandPayload, ReconcileOptions, ReconcileResult, RefEntryAppender, RefEntryClassification, RefusalInfo, RepeatedClaim, ReplayDisposition, ReplayMode, ReplayPlanHashMismatch, Replayer, RepositoryResearchToolset, RepositoryResearchToolsetOptions, ResearchEvidenceEntry, ResolutionArbiter, ResolutionAttempt, ResolutionBy, ResolutionFold, ResolutionLayer, ResolutionOutcome, ResolutionPayload, ResolvedInvocation, ResolvedToolset, ResumeHandle, ResumeOptions, ResumePreview, ResumeReport, RetryClass, RetryPolicy, ReuseConfig, RiskRuleValue, Role, RulvarError, RulvarErrorCode, RunAgentOptions, RunAuditVerdict, RunBudget, RunEventSink, type RunFilter, RunHandle, RunInternals, type RunMeta, RunOptions, RunOutcome, RunProfile, RunStateAudit, RunStatus, RuntimeEventSink, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxBridge, SandboxBridgeOptions, SandboxError, SandboxHostToWorker, SandboxMethod, SandboxWorkerToHost, SchemaPair, SchemaSpec, SchemaValidationResult, ScopeSegment, ScriptRejected, ScriptRunner, ScrubNote, Semaphore, SerializationHook, Settled, ShellPatternRules, ShellSegment, ShellVerdict, SinglePhaseAppend, SpanMinter, SpanRegistry, SpawnAdmissionValue, SpawnAgentParams, SpawnKey, SpawnLineage, SpawnLineageOpt, SpawnOrigin, SpawnRecord, Spend, Stage, type StandardJSONSchemaV1, type StandardSchemaV1, StepIdentityInput, StructuredOutputTier, SuspendedAppend, SuspensionState, TOOL_NAME_PATTERN, type TaskClass, TaskDigest, TaskSpec, TerminalPatch, TerminationAccount, TerminationAccountSnapshot, TerminationDeniedValue, TerminationDeniedWriter, TerminationInitValue, TerminationLimits, TerminationResource, ToolCallRequest, ToolChoice, type ToolContext, ToolContextSeed, ToolContract, type ToolDef, type ToolEvents, type ToolExecutor, ToolInit, type ToolRisk, ToolRuntime, type ToolSource, type ToolSourceSession, ToolsOption, TranscriptSerializationHook, type TranscriptStore, TriggerClass, TtlState, Usage, UsageLimits, UsageSlice, VerifiedRecommendation, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, WakeBudgetBlock, WakeDigest, WakeTrigger, WireError, Workflow, WorkflowCallOpts, type WorkflowEvent, type WorkflowEventBody, WorkflowRegistry, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createHash, getRandomValues, randomUUID } from "node:crypto";
|
|
2
|
-
import { appendFileSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join, resolve, sep } from "node:path";
|
|
2
|
+
import { appendFileSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path, { dirname, join, resolve, sep } from "node:path";
|
|
4
4
|
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
5
5
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
6
6
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
7
7
|
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
8
8
|
import { ToolListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
9
9
|
import { execFile } from "node:child_process";
|
|
10
|
-
import { mkdtemp, rm } from "node:fs/promises";
|
|
10
|
+
import { mkdtemp, readFile, readdir, realpath, rm, stat } from "node:fs/promises";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { promisify } from "node:util";
|
|
13
13
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -3297,6 +3297,459 @@ var GitWorktreeProvider = class {
|
|
|
3297
3297
|
}
|
|
3298
3298
|
};
|
|
3299
3299
|
//#endregion
|
|
3300
|
+
//#region src/tools/research.ts
|
|
3301
|
+
/**
|
|
3302
|
+
* The standard repository research toolset (RV-210 remainder): paginated
|
|
3303
|
+
* list/search/read tools over a confined directory root with STABLE
|
|
3304
|
+
* keyset cursors, plus an evidence collector that verifies citations at
|
|
3305
|
+
* collection time. Design contract:
|
|
3306
|
+
*
|
|
3307
|
+
* - Responses are CANONICAL: a page is a pure function of (root
|
|
3308
|
+
* filesystem state, logical window), never of how the window was
|
|
3309
|
+
* addressed, so reading the same page through a cursor and through
|
|
3310
|
+
* fresh arguments returns byte-identical results. That is what makes
|
|
3311
|
+
* the RV-210 `maxNoNewEvidenceCalls` guard measure duplicate-page
|
|
3312
|
+
* reads correctly, and the `maxRepeatedToolSignature` guard already
|
|
3313
|
+
* denies byte-identical repeat calls: deduplication is composition,
|
|
3314
|
+
* not a marker field.
|
|
3315
|
+
* - Cursors are keyset cursors (the last path / line, not an offset), so
|
|
3316
|
+
* a page boundary never shifts when unrelated entries appear or
|
|
3317
|
+
* disappear, and every cursor embeds the query identity: replaying a
|
|
3318
|
+
* cursor against different arguments is a typed error result.
|
|
3319
|
+
* - Ordering is deterministic byte order (UTF-16 code unit sort), never
|
|
3320
|
+
* locale collation.
|
|
3321
|
+
* - The root confines everything: relative paths only, `..` escapes and
|
|
3322
|
+
* symlink escapes are typed error results, symlinked directories are
|
|
3323
|
+
* never walked.
|
|
3324
|
+
* - User-level failures (bad path, binary file, oversized file, invalid
|
|
3325
|
+
* cursor, an unverifiable citation) are RETURNED `{ error }` values,
|
|
3326
|
+
* deterministic and visible to the model; only host misconfiguration
|
|
3327
|
+
* throws (ConfigError at construction).
|
|
3328
|
+
* - Tool results are journaled at execution time, so replay never
|
|
3329
|
+
* touches the filesystem; live pages read the live tree.
|
|
3330
|
+
*
|
|
3331
|
+
* Public docs: https://docs.rulvar.com/guide/tools
|
|
3332
|
+
*/
|
|
3333
|
+
const DEFAULT_PAGE_SIZE = 50;
|
|
3334
|
+
const DEFAULT_READ_PAGE_CHARS = 4e3;
|
|
3335
|
+
const DEFAULT_MAX_FILE_BYTES = 262144;
|
|
3336
|
+
const DEFAULT_MAX_SCANNED_FILES = 2e4;
|
|
3337
|
+
const ALWAYS_IGNORED = [".git", "node_modules"];
|
|
3338
|
+
const SEARCH_SNIPPET_CHARS = 200;
|
|
3339
|
+
const BINARY_SNIFF_BYTES = 8192;
|
|
3340
|
+
const LIST_SCHEMA = {
|
|
3341
|
+
type: "object",
|
|
3342
|
+
additionalProperties: false,
|
|
3343
|
+
properties: {
|
|
3344
|
+
dir: {
|
|
3345
|
+
type: "string",
|
|
3346
|
+
description: "Root-relative directory to list; default the root."
|
|
3347
|
+
},
|
|
3348
|
+
cursor: {
|
|
3349
|
+
type: "string",
|
|
3350
|
+
description: "Opaque cursor from a previous page."
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
};
|
|
3354
|
+
const SEARCH_SCHEMA = {
|
|
3355
|
+
type: "object",
|
|
3356
|
+
additionalProperties: false,
|
|
3357
|
+
required: ["query"],
|
|
3358
|
+
properties: {
|
|
3359
|
+
query: {
|
|
3360
|
+
type: "string",
|
|
3361
|
+
minLength: 1,
|
|
3362
|
+
description: "Literal substring to find."
|
|
3363
|
+
},
|
|
3364
|
+
dir: {
|
|
3365
|
+
type: "string",
|
|
3366
|
+
description: "Root-relative directory to search; default the root."
|
|
3367
|
+
},
|
|
3368
|
+
cursor: {
|
|
3369
|
+
type: "string",
|
|
3370
|
+
description: "Opaque cursor from a previous page."
|
|
3371
|
+
}
|
|
3372
|
+
}
|
|
3373
|
+
};
|
|
3374
|
+
const READ_SCHEMA = {
|
|
3375
|
+
type: "object",
|
|
3376
|
+
additionalProperties: false,
|
|
3377
|
+
required: ["path"],
|
|
3378
|
+
properties: {
|
|
3379
|
+
path: {
|
|
3380
|
+
type: "string",
|
|
3381
|
+
minLength: 1,
|
|
3382
|
+
description: "Root-relative file path."
|
|
3383
|
+
},
|
|
3384
|
+
cursor: {
|
|
3385
|
+
type: "string",
|
|
3386
|
+
description: "Opaque cursor from a previous page."
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
};
|
|
3390
|
+
const RECORD_EVIDENCE_SCHEMA = {
|
|
3391
|
+
type: "object",
|
|
3392
|
+
additionalProperties: false,
|
|
3393
|
+
required: ["claim", "file"],
|
|
3394
|
+
properties: {
|
|
3395
|
+
claim: {
|
|
3396
|
+
type: "string",
|
|
3397
|
+
minLength: 1,
|
|
3398
|
+
description: "The claim this evidence supports."
|
|
3399
|
+
},
|
|
3400
|
+
file: {
|
|
3401
|
+
type: "string",
|
|
3402
|
+
minLength: 1,
|
|
3403
|
+
description: "Root-relative file the claim cites."
|
|
3404
|
+
},
|
|
3405
|
+
lines: {
|
|
3406
|
+
type: "string",
|
|
3407
|
+
description: "Cited line or range, 1-based: '12' or '12-40'."
|
|
3408
|
+
},
|
|
3409
|
+
quote: {
|
|
3410
|
+
type: "string",
|
|
3411
|
+
minLength: 1,
|
|
3412
|
+
description: "Verbatim quote; verified to appear in the file."
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
};
|
|
3416
|
+
const LIST_EVIDENCE_SCHEMA = {
|
|
3417
|
+
type: "object",
|
|
3418
|
+
additionalProperties: false,
|
|
3419
|
+
properties: { cursor: {
|
|
3420
|
+
type: "string",
|
|
3421
|
+
description: "Opaque cursor from a previous page."
|
|
3422
|
+
} }
|
|
3423
|
+
};
|
|
3424
|
+
function encodeCursor(payload) {
|
|
3425
|
+
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
3426
|
+
}
|
|
3427
|
+
function decodeCursor(raw) {
|
|
3428
|
+
try {
|
|
3429
|
+
return JSON.parse(Buffer.from(raw, "base64url").toString("utf8"));
|
|
3430
|
+
} catch {
|
|
3431
|
+
return;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
function isBinary(buffer) {
|
|
3435
|
+
return buffer.subarray(0, BINARY_SNIFF_BYTES).includes(0);
|
|
3436
|
+
}
|
|
3437
|
+
/** Split into lines on LF; a trailing CR per line is presentation, not content. */
|
|
3438
|
+
function splitLines(text) {
|
|
3439
|
+
return text.split("\n").map((line) => line.endsWith("\r") ? line.slice(0, -1) : line);
|
|
3440
|
+
}
|
|
3441
|
+
function repositoryResearchToolset(options) {
|
|
3442
|
+
if (typeof options.root !== "string" || options.root.length === 0) throw new ConfigError("repositoryResearchToolset root must be a non-empty string");
|
|
3443
|
+
let realRoot;
|
|
3444
|
+
try {
|
|
3445
|
+
realRoot = realpathSync(path.resolve(options.root));
|
|
3446
|
+
} catch {
|
|
3447
|
+
throw new ConfigError(`repositoryResearchToolset root '${options.root}' does not exist`);
|
|
3448
|
+
}
|
|
3449
|
+
if (!statSync(realRoot).isDirectory()) throw new ConfigError(`repositoryResearchToolset root '${options.root}' is not a directory`);
|
|
3450
|
+
for (const [name, value] of [
|
|
3451
|
+
["pageSize", options.pageSize],
|
|
3452
|
+
["readPageChars", options.readPageChars],
|
|
3453
|
+
["maxFileBytes", options.maxFileBytes],
|
|
3454
|
+
["maxScannedFiles", options.maxScannedFiles]
|
|
3455
|
+
]) if (value !== void 0 && (!Number.isSafeInteger(value) || value < 1)) throw new ConfigError(`repositoryResearchToolset ${name} must be a positive integer; got ${String(value)}`);
|
|
3456
|
+
const pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE;
|
|
3457
|
+
const readPageChars = options.readPageChars ?? DEFAULT_READ_PAGE_CHARS;
|
|
3458
|
+
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
3459
|
+
const maxScannedFiles = options.maxScannedFiles ?? DEFAULT_MAX_SCANNED_FILES;
|
|
3460
|
+
const includeHidden = options.includeHidden ?? false;
|
|
3461
|
+
const ignored = /* @__PURE__ */ new Set([...ALWAYS_IGNORED, ...options.ignore ?? []]);
|
|
3462
|
+
const evidence = [];
|
|
3463
|
+
/**
|
|
3464
|
+
* Resolves a root-relative POSIX path and confines it: absolute paths,
|
|
3465
|
+
* `..` escapes, and symlink escapes are error strings, never throws.
|
|
3466
|
+
* `mustExist` additionally resolves symlinks and re-checks containment
|
|
3467
|
+
* of the REAL path (the FileTranscriptStore traversal lesson).
|
|
3468
|
+
*/
|
|
3469
|
+
const resolveWithin = async (rel, kind) => {
|
|
3470
|
+
const normalizedInput = rel.replaceAll("\\", "/");
|
|
3471
|
+
if (path.posix.isAbsolute(normalizedInput) || path.isAbsolute(rel)) return { error: `path must be relative to the research root; got '${rel}'` };
|
|
3472
|
+
const normalized = path.posix.normalize(normalizedInput);
|
|
3473
|
+
if (normalized === ".." || normalized.startsWith("../")) return { error: `path escapes the research root: '${rel}'` };
|
|
3474
|
+
const cleaned = normalized === "." ? "" : normalized;
|
|
3475
|
+
if (kind === "file" && cleaned === "") return { error: "path must name a file inside the research root" };
|
|
3476
|
+
const abs = path.resolve(realRoot, cleaned);
|
|
3477
|
+
let real;
|
|
3478
|
+
try {
|
|
3479
|
+
real = await realpath(abs);
|
|
3480
|
+
} catch {
|
|
3481
|
+
return { error: `no such ${kind} under the research root: '${cleaned === "" ? "." : cleaned}'` };
|
|
3482
|
+
}
|
|
3483
|
+
if (real !== realRoot && !real.startsWith(realRoot + path.sep)) return { error: `path escapes the research root: '${rel}'` };
|
|
3484
|
+
try {
|
|
3485
|
+
const info = await stat(real);
|
|
3486
|
+
if (kind === "file" && !info.isFile()) return { error: `not a regular file: '${cleaned}'` };
|
|
3487
|
+
if (kind === "dir" && !info.isDirectory()) return { error: `not a directory: '${cleaned === "" ? "." : cleaned}'` };
|
|
3488
|
+
} catch {
|
|
3489
|
+
return { error: `no such ${kind} under the research root: '${cleaned === "" ? "." : cleaned}'` };
|
|
3490
|
+
}
|
|
3491
|
+
return {
|
|
3492
|
+
abs: real,
|
|
3493
|
+
rel: cleaned
|
|
3494
|
+
};
|
|
3495
|
+
};
|
|
3496
|
+
/**
|
|
3497
|
+
* Deterministic recursive walk: sorted entries, ignored and hidden
|
|
3498
|
+
* names skipped, symlinks never followed, regular files only. Returns
|
|
3499
|
+
* root-relative POSIX paths in byte order, or an error when the walk
|
|
3500
|
+
* exceeds maxScannedFiles.
|
|
3501
|
+
*/
|
|
3502
|
+
const walkFiles = async (absDir, relDir) => {
|
|
3503
|
+
const files = [];
|
|
3504
|
+
let visited = 0;
|
|
3505
|
+
const recurse = async (dirAbs, dirRel) => {
|
|
3506
|
+
let entries;
|
|
3507
|
+
try {
|
|
3508
|
+
entries = await readdir(dirAbs, { withFileTypes: true });
|
|
3509
|
+
} catch {
|
|
3510
|
+
return `directory disappeared during the walk: '${dirRel === "" ? "." : dirRel}'`;
|
|
3511
|
+
}
|
|
3512
|
+
const sorted = [...entries].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
3513
|
+
for (const entry of sorted) {
|
|
3514
|
+
const name = entry.name;
|
|
3515
|
+
if (ignored.has(name)) continue;
|
|
3516
|
+
if (!includeHidden && name.startsWith(".")) continue;
|
|
3517
|
+
const childRel = dirRel === "" ? name : `${dirRel}/${name}`;
|
|
3518
|
+
if (entry.isDirectory()) {
|
|
3519
|
+
const failure = await recurse(path.join(dirAbs, name), childRel);
|
|
3520
|
+
if (failure !== void 0) return failure;
|
|
3521
|
+
continue;
|
|
3522
|
+
}
|
|
3523
|
+
if (!entry.isFile()) continue;
|
|
3524
|
+
visited += 1;
|
|
3525
|
+
if (visited > maxScannedFiles) return `the walk exceeded maxScannedFiles (${String(maxScannedFiles)}); narrow dir or raise the limit`;
|
|
3526
|
+
files.push(childRel);
|
|
3527
|
+
}
|
|
3528
|
+
};
|
|
3529
|
+
const failure = await recurse(absDir, relDir);
|
|
3530
|
+
if (failure !== void 0) return { error: failure };
|
|
3531
|
+
return { files };
|
|
3532
|
+
};
|
|
3533
|
+
const loadTextFile = async (abs, rel) => {
|
|
3534
|
+
let info;
|
|
3535
|
+
try {
|
|
3536
|
+
info = await stat(abs);
|
|
3537
|
+
} catch {
|
|
3538
|
+
return { error: `no such file under the research root: '${rel}'` };
|
|
3539
|
+
}
|
|
3540
|
+
if (info.size > maxFileBytes) return { error: `file '${rel}' is ${String(info.size)} bytes, over the maxFileBytes limit (${String(maxFileBytes)})` };
|
|
3541
|
+
const buffer = await readFile(abs);
|
|
3542
|
+
if (isBinary(buffer)) return { error: `file '${rel}' is binary` };
|
|
3543
|
+
return { text: buffer.toString("utf8") };
|
|
3544
|
+
};
|
|
3545
|
+
return {
|
|
3546
|
+
tools: [
|
|
3547
|
+
tool({
|
|
3548
|
+
name: "list_files",
|
|
3549
|
+
description: "List files under a directory of the research root, recursively, in deterministic byte order, one page at a time. Returns { files, totalFiles, nextCursor? }; pass cursor to continue where the last page ended (the cursor is stable: unrelated changes never shift the boundary).",
|
|
3550
|
+
parameters: LIST_SCHEMA,
|
|
3551
|
+
risk: "read",
|
|
3552
|
+
execute: async (input) => {
|
|
3553
|
+
const params = input;
|
|
3554
|
+
let dir = params.dir ?? "";
|
|
3555
|
+
let after;
|
|
3556
|
+
if (params.cursor !== void 0) {
|
|
3557
|
+
const payload = decodeCursor(params.cursor);
|
|
3558
|
+
if (payload === void 0 || payload.t !== "list" || typeof payload.dir !== "string" || typeof payload.after !== "string" || params.dir !== void 0 && params.dir !== payload.dir) return { error: "invalid cursor: pass the nextCursor of a previous list_files page" };
|
|
3559
|
+
dir = payload.dir;
|
|
3560
|
+
after = payload.after;
|
|
3561
|
+
}
|
|
3562
|
+
const resolved = await resolveWithin(dir, "dir");
|
|
3563
|
+
if ("error" in resolved) return resolved;
|
|
3564
|
+
const walked = await walkFiles(resolved.abs, resolved.rel);
|
|
3565
|
+
if ("error" in walked) return walked;
|
|
3566
|
+
const remaining = after === void 0 ? walked.files : walked.files.filter((file) => file > after);
|
|
3567
|
+
const page = remaining.slice(0, pageSize);
|
|
3568
|
+
const more = remaining.length > pageSize;
|
|
3569
|
+
return {
|
|
3570
|
+
files: page,
|
|
3571
|
+
totalFiles: walked.files.length,
|
|
3572
|
+
...more ? { nextCursor: encodeCursor({
|
|
3573
|
+
t: "list",
|
|
3574
|
+
dir: resolved.rel,
|
|
3575
|
+
after: page[page.length - 1]
|
|
3576
|
+
}) } : {}
|
|
3577
|
+
};
|
|
3578
|
+
}
|
|
3579
|
+
}),
|
|
3580
|
+
tool({
|
|
3581
|
+
name: "search_files",
|
|
3582
|
+
description: "Search files under the research root for a literal substring (case-sensitive, never a regex), one page of matches at a time in deterministic (path, line) order. Returns { matches: [{ file, line, text }], filesScanned, filesSkipped, nextCursor? }; binary and oversized files are skipped and counted.",
|
|
3583
|
+
parameters: SEARCH_SCHEMA,
|
|
3584
|
+
risk: "read",
|
|
3585
|
+
execute: async (input) => {
|
|
3586
|
+
const params = input;
|
|
3587
|
+
let dir = params.dir ?? "";
|
|
3588
|
+
let query = params.query;
|
|
3589
|
+
let after;
|
|
3590
|
+
if (params.cursor !== void 0) {
|
|
3591
|
+
const payload = decodeCursor(params.cursor);
|
|
3592
|
+
if (payload === void 0 || payload.t !== "search" || typeof payload.query !== "string" || typeof payload.dir !== "string" || typeof payload.file !== "string" || typeof payload.line !== "number" || payload.query !== params.query || params.dir !== void 0 && params.dir !== payload.dir) return { error: "invalid cursor: pass the nextCursor of a previous search_files page with the same query and dir" };
|
|
3593
|
+
dir = payload.dir;
|
|
3594
|
+
query = payload.query;
|
|
3595
|
+
after = {
|
|
3596
|
+
file: payload.file,
|
|
3597
|
+
line: payload.line
|
|
3598
|
+
};
|
|
3599
|
+
}
|
|
3600
|
+
if (query.length === 0) return { error: "query must be a non-empty literal substring" };
|
|
3601
|
+
const resolved = await resolveWithin(dir, "dir");
|
|
3602
|
+
if ("error" in resolved) return resolved;
|
|
3603
|
+
const walked = await walkFiles(resolved.abs, resolved.rel);
|
|
3604
|
+
if ("error" in walked) return walked;
|
|
3605
|
+
const matches = [];
|
|
3606
|
+
let filesScanned = 0;
|
|
3607
|
+
let filesSkipped = 0;
|
|
3608
|
+
for (const file of walked.files) {
|
|
3609
|
+
const loaded = await loadTextFile(path.join(realRoot, file), file);
|
|
3610
|
+
if ("error" in loaded) {
|
|
3611
|
+
filesSkipped += 1;
|
|
3612
|
+
continue;
|
|
3613
|
+
}
|
|
3614
|
+
filesScanned += 1;
|
|
3615
|
+
const lines = splitLines(loaded.text);
|
|
3616
|
+
for (let index = 0; index < lines.length; index += 1) if (lines[index].includes(query)) matches.push({
|
|
3617
|
+
file,
|
|
3618
|
+
line: index + 1,
|
|
3619
|
+
text: lines[index].trim().slice(0, SEARCH_SNIPPET_CHARS)
|
|
3620
|
+
});
|
|
3621
|
+
}
|
|
3622
|
+
const remaining = after === void 0 ? matches : matches.filter((match) => match.file > after.file || match.file === after.file && match.line > after.line);
|
|
3623
|
+
const page = remaining.slice(0, pageSize);
|
|
3624
|
+
const more = remaining.length > pageSize;
|
|
3625
|
+
const last = page[page.length - 1];
|
|
3626
|
+
return {
|
|
3627
|
+
matches: page,
|
|
3628
|
+
filesScanned,
|
|
3629
|
+
filesSkipped,
|
|
3630
|
+
...more && last !== void 0 ? { nextCursor: encodeCursor({
|
|
3631
|
+
t: "search",
|
|
3632
|
+
query,
|
|
3633
|
+
dir: resolved.rel,
|
|
3634
|
+
file: last.file,
|
|
3635
|
+
line: last.line
|
|
3636
|
+
}) } : {}
|
|
3637
|
+
};
|
|
3638
|
+
}
|
|
3639
|
+
}),
|
|
3640
|
+
tool({
|
|
3641
|
+
name: "read_file",
|
|
3642
|
+
description: "Read a file of the research root as numbered lines, one page at a time (whole lines up to the page character budget). Returns { path, totalLines, fromLine, toLine, content, nextCursor? }; the same page reads byte-identically however it is addressed, so duplicate reads are visible to the exploration guards.",
|
|
3643
|
+
parameters: READ_SCHEMA,
|
|
3644
|
+
risk: "read",
|
|
3645
|
+
execute: async (input) => {
|
|
3646
|
+
const params = input;
|
|
3647
|
+
let rel = params.path;
|
|
3648
|
+
let fromLine = 1;
|
|
3649
|
+
if (params.cursor !== void 0) {
|
|
3650
|
+
const payload = decodeCursor(params.cursor);
|
|
3651
|
+
if (payload === void 0 || payload.t !== "read" || typeof payload.path !== "string" || typeof payload.after !== "number" || payload.path !== params.path) return { error: "invalid cursor: pass the nextCursor of a previous read_file page for the same path" };
|
|
3652
|
+
rel = payload.path;
|
|
3653
|
+
fromLine = payload.after + 1;
|
|
3654
|
+
}
|
|
3655
|
+
const resolved = await resolveWithin(rel, "file");
|
|
3656
|
+
if ("error" in resolved) return resolved;
|
|
3657
|
+
const loaded = await loadTextFile(resolved.abs, resolved.rel);
|
|
3658
|
+
if ("error" in loaded) return loaded;
|
|
3659
|
+
const lines = splitLines(loaded.text);
|
|
3660
|
+
const totalLines = lines.length;
|
|
3661
|
+
if (fromLine > totalLines) return { error: `fromLine ${String(fromLine)} is past the end of '${resolved.rel}' (${String(totalLines)} lines)` };
|
|
3662
|
+
const rendered = [];
|
|
3663
|
+
let used = 0;
|
|
3664
|
+
let toLine = fromLine - 1;
|
|
3665
|
+
for (let index = fromLine - 1; index < totalLines; index += 1) {
|
|
3666
|
+
const row = `${String(index + 1)}: ${lines[index]}`;
|
|
3667
|
+
if (rendered.length > 0 && used + 1 + row.length > readPageChars) break;
|
|
3668
|
+
rendered.push(row);
|
|
3669
|
+
used += (rendered.length > 1 ? 1 : 0) + row.length;
|
|
3670
|
+
toLine = index + 1;
|
|
3671
|
+
}
|
|
3672
|
+
const more = toLine < totalLines;
|
|
3673
|
+
return {
|
|
3674
|
+
path: resolved.rel,
|
|
3675
|
+
totalLines,
|
|
3676
|
+
fromLine,
|
|
3677
|
+
toLine,
|
|
3678
|
+
content: rendered.join("\n"),
|
|
3679
|
+
...more ? { nextCursor: encodeCursor({
|
|
3680
|
+
t: "read",
|
|
3681
|
+
path: resolved.rel,
|
|
3682
|
+
after: toLine
|
|
3683
|
+
}) } : {}
|
|
3684
|
+
};
|
|
3685
|
+
}
|
|
3686
|
+
}),
|
|
3687
|
+
tool({
|
|
3688
|
+
name: "record_evidence",
|
|
3689
|
+
description: "Record one evidence entry supporting a claim. The citation is VERIFIED at record time: the file must exist under the research root, lines must be a valid 1-based line or range inside it ('12' or '12-40'), and quote (when given) must appear verbatim in the file. Returns { recorded, duplicate, totalEvidence }.",
|
|
3690
|
+
parameters: RECORD_EVIDENCE_SCHEMA,
|
|
3691
|
+
risk: "read",
|
|
3692
|
+
execute: async (input) => {
|
|
3693
|
+
const params = input;
|
|
3694
|
+
if (params.claim.trim().length === 0) return { error: "claim must be a non-empty string" };
|
|
3695
|
+
const resolved = await resolveWithin(params.file, "file");
|
|
3696
|
+
if ("error" in resolved) return resolved;
|
|
3697
|
+
const loaded = await loadTextFile(resolved.abs, resolved.rel);
|
|
3698
|
+
if ("error" in loaded) return loaded;
|
|
3699
|
+
const lines = splitLines(loaded.text);
|
|
3700
|
+
if (params.lines !== void 0) {
|
|
3701
|
+
const match = /^(\d+)(?:-(\d+))?$/u.exec(params.lines);
|
|
3702
|
+
if (match === null) return { error: "lines must be '12' or '12-40' (1-based)" };
|
|
3703
|
+
const from = Number(match[1]);
|
|
3704
|
+
const to = match[2] === void 0 ? from : Number(match[2]);
|
|
3705
|
+
if (from < 1 || to < from || to > lines.length) return { error: `lines '${params.lines}' is outside '${resolved.rel}' (${String(lines.length)} lines)` };
|
|
3706
|
+
}
|
|
3707
|
+
if (params.quote !== void 0 && !loaded.text.includes(params.quote)) return { error: `quote not found verbatim in '${resolved.rel}'; cite what the file actually says` };
|
|
3708
|
+
const entry = {
|
|
3709
|
+
claim: params.claim,
|
|
3710
|
+
file: resolved.rel,
|
|
3711
|
+
...params.lines === void 0 ? {} : { lines: params.lines },
|
|
3712
|
+
...params.quote === void 0 ? {} : { quote: params.quote }
|
|
3713
|
+
};
|
|
3714
|
+
const duplicate = evidence.some((existing) => existing.claim === entry.claim && existing.file === entry.file && existing.lines === entry.lines && existing.quote === entry.quote);
|
|
3715
|
+
if (!duplicate) evidence.push(entry);
|
|
3716
|
+
return {
|
|
3717
|
+
recorded: !duplicate,
|
|
3718
|
+
duplicate,
|
|
3719
|
+
totalEvidence: evidence.length
|
|
3720
|
+
};
|
|
3721
|
+
}
|
|
3722
|
+
}),
|
|
3723
|
+
tool({
|
|
3724
|
+
name: "list_evidence",
|
|
3725
|
+
description: "List the evidence recorded so far, one page at a time in record order. Returns { evidence, totalEvidence, nextCursor? }.",
|
|
3726
|
+
parameters: LIST_EVIDENCE_SCHEMA,
|
|
3727
|
+
risk: "read",
|
|
3728
|
+
execute: (input) => {
|
|
3729
|
+
const params = input;
|
|
3730
|
+
let from = 0;
|
|
3731
|
+
if (params.cursor !== void 0) {
|
|
3732
|
+
const payload = decodeCursor(params.cursor);
|
|
3733
|
+
if (payload === void 0 || payload.t !== "evidence" || typeof payload.after !== "number") return Promise.resolve({ error: "invalid cursor: pass the nextCursor of a previous list_evidence page" });
|
|
3734
|
+
from = payload.after;
|
|
3735
|
+
}
|
|
3736
|
+
const page = evidence.slice(from, from + pageSize);
|
|
3737
|
+
const more = from + pageSize < evidence.length;
|
|
3738
|
+
return Promise.resolve({
|
|
3739
|
+
evidence: page,
|
|
3740
|
+
totalEvidence: evidence.length,
|
|
3741
|
+
...more ? { nextCursor: encodeCursor({
|
|
3742
|
+
t: "evidence",
|
|
3743
|
+
after: from + pageSize
|
|
3744
|
+
}) } : {}
|
|
3745
|
+
});
|
|
3746
|
+
}
|
|
3747
|
+
})
|
|
3748
|
+
],
|
|
3749
|
+
evidence: () => evidence.map((entry) => ({ ...entry }))
|
|
3750
|
+
};
|
|
3751
|
+
}
|
|
3752
|
+
//#endregion
|
|
3300
3753
|
//#region src/journal/identity.ts
|
|
3301
3754
|
/**
|
|
3302
3755
|
* Content-addressed entry identity (M1-T04): IdentityInput records per
|
|
@@ -13265,6 +13718,52 @@ async function executeWorkflow(internals, wf, args) {
|
|
|
13265
13718
|
}
|
|
13266
13719
|
}
|
|
13267
13720
|
//#endregion
|
|
13721
|
+
//#region src/orchestrator/claims.ts
|
|
13722
|
+
/** The conservative matching key: trim plus inner-whitespace collapse. */
|
|
13723
|
+
function claimKey(line) {
|
|
13724
|
+
return line.trim().replace(/\s+/gu, " ");
|
|
13725
|
+
}
|
|
13726
|
+
/**
|
|
13727
|
+
* Removes later occurrences of repeated claim lines across the rows and
|
|
13728
|
+
* indexes each repeated claim with its reporters. Deterministic: output
|
|
13729
|
+
* depends only on the input order and bytes.
|
|
13730
|
+
*/
|
|
13731
|
+
function dedupeRepeatedClaims(rows) {
|
|
13732
|
+
const seen = /* @__PURE__ */ new Map();
|
|
13733
|
+
const order = [];
|
|
13734
|
+
return {
|
|
13735
|
+
rows: rows.map((row) => {
|
|
13736
|
+
const kept = [];
|
|
13737
|
+
for (const line of row.text.split("\n")) {
|
|
13738
|
+
const key = claimKey(line);
|
|
13739
|
+
if (key === "") {
|
|
13740
|
+
kept.push(line);
|
|
13741
|
+
continue;
|
|
13742
|
+
}
|
|
13743
|
+
const prior = seen.get(key);
|
|
13744
|
+
if (prior === void 0) {
|
|
13745
|
+
const entry = {
|
|
13746
|
+
claim: line,
|
|
13747
|
+
nodeIds: [row.nodeId],
|
|
13748
|
+
count: 1
|
|
13749
|
+
};
|
|
13750
|
+
seen.set(key, entry);
|
|
13751
|
+
order.push(entry);
|
|
13752
|
+
kept.push(line);
|
|
13753
|
+
continue;
|
|
13754
|
+
}
|
|
13755
|
+
prior.count += 1;
|
|
13756
|
+
if (!prior.nodeIds.includes(row.nodeId)) prior.nodeIds.push(row.nodeId);
|
|
13757
|
+
}
|
|
13758
|
+
return {
|
|
13759
|
+
nodeId: row.nodeId,
|
|
13760
|
+
text: kept.join("\n")
|
|
13761
|
+
};
|
|
13762
|
+
}),
|
|
13763
|
+
repeated: order.filter((entry) => entry.count > 1)
|
|
13764
|
+
};
|
|
13765
|
+
}
|
|
13766
|
+
//#endregion
|
|
13268
13767
|
//#region src/orchestrator/orchestrate.ts
|
|
13269
13768
|
/**
|
|
13270
13769
|
* The mode (c) dynamic orchestrator (M6-T07/T08).
|
|
@@ -13291,6 +13790,12 @@ const DEFAULT_FINISH_MAX_REPAIRS = 1;
|
|
|
13291
13790
|
* call plus headroom for one validator repair exchange.
|
|
13292
13791
|
*/
|
|
13293
13792
|
const DEFAULT_SYNTHESIS_MAX_TURNS = 4;
|
|
13793
|
+
/**
|
|
13794
|
+
* Default maxTurns of ONE incremental synthesis note (RV-211 remainder):
|
|
13795
|
+
* a note summarizes a single settled child into a bounded finish call,
|
|
13796
|
+
* so it needs less headroom than the full synthesis invocation.
|
|
13797
|
+
*/
|
|
13798
|
+
const DEFAULT_SYNTHESIS_NOTE_MAX_TURNS = 2;
|
|
13294
13799
|
const ORCHESTRATE_WORKFLOW_NAME = "rulvar-orchestrate";
|
|
13295
13800
|
/**
|
|
13296
13801
|
* One page of a string, for the child result evidence tools: maxChars is
|
|
@@ -13350,6 +13855,10 @@ function validateOrchestrateOptions(opts) {
|
|
|
13350
13855
|
}
|
|
13351
13856
|
if (opts.synthesis !== void 0) {
|
|
13352
13857
|
const synthesis = opts.synthesis;
|
|
13858
|
+
if (synthesis.mode !== void 0 && synthesis.mode !== "single" && synthesis.mode !== "incremental") throw new ConfigError("orchestrate synthesis.mode must be 'single' or 'incremental'; got " + JSON.stringify(synthesis.mode));
|
|
13859
|
+
if (synthesis.mode === "incremental" && opts.finishValidation !== void 0) throw new ConfigError("orchestrate synthesis.mode 'incremental' reconciles deterministically and has no model-composed final finish for finishValidation to bind; configure validators with mode 'single', or drop them");
|
|
13860
|
+
if (synthesis.dedupeClaims !== void 0 && typeof synthesis.dedupeClaims !== "boolean") throw new ConfigError("orchestrate synthesis.dedupeClaims must be a boolean; got " + typeof synthesis.dedupeClaims);
|
|
13861
|
+
if (synthesis.noteLimits !== void 0) validateUsageLimits(synthesis.noteLimits, "orchestrate synthesis.noteLimits");
|
|
13353
13862
|
if (synthesis.effort !== void 0 && ![
|
|
13354
13863
|
"low",
|
|
13355
13864
|
"medium",
|
|
@@ -13551,6 +14060,22 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
13551
14060
|
const recoveryDone = new Promise((resolve) => {
|
|
13552
14061
|
releaseRecovery = resolve;
|
|
13553
14062
|
});
|
|
14063
|
+
/**
|
|
14064
|
+
* Incremental synthesis notes (RV-211 remainder): one bounded
|
|
14065
|
+
* synthesize-role invocation per settled child, keyed by nodeId so a
|
|
14066
|
+
* note can never double-dispatch. The settle hook fires the note the
|
|
14067
|
+
* moment its child settles (overlapping the still-running fan-out);
|
|
14068
|
+
* the deterministic reconciliation is the completeness backstop and
|
|
14069
|
+
* dispatches any note the hook missed. The dispatcher installs right
|
|
14070
|
+
* before the coordination loop because it closes over runtime pieces
|
|
14071
|
+
* built below; these bindings are declared HERE, before
|
|
14072
|
+
* dispatchChild, so a recovered child's settle hook (which can fire
|
|
14073
|
+
* during the recovery scan) never touches a binding in its temporal
|
|
14074
|
+
* dead zone.
|
|
14075
|
+
*/
|
|
14076
|
+
const synthesisNotes = /* @__PURE__ */ new Map();
|
|
14077
|
+
let synthesisNoteDispatcher;
|
|
14078
|
+
let synthesisSettleFrozen = false;
|
|
13554
14079
|
let activityChain = Promise.resolve();
|
|
13555
14080
|
const childScopeOf = () => {
|
|
13556
14081
|
if (orchSeq === void 0) throw new ConfigError("orchestrator dispatch seq unknown before the loop started");
|
|
@@ -13636,6 +14161,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
13636
14161
|
};
|
|
13637
14162
|
settledResult.then(async (settled) => {
|
|
13638
14163
|
record.settled = settled;
|
|
14164
|
+
if (!synthesisSettleFrozen) synthesisNoteDispatcher?.(record);
|
|
13639
14165
|
await runExtensionActivity();
|
|
13640
14166
|
for (const listener of [...settleListeners]) listener();
|
|
13641
14167
|
});
|
|
@@ -14425,33 +14951,198 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
14425
14951
|
};
|
|
14426
14952
|
};
|
|
14427
14953
|
/**
|
|
14954
|
+
* One incremental synthesis note (RV-211 remainder): a FRESH agent
|
|
14955
|
+
* entry with role 'synthesize' on the finish-only toolset whose
|
|
14956
|
+
* prompt derives deterministically from the goal and the ONE settled
|
|
14957
|
+
* child's digest, so a resume replays it by identity with zero paid
|
|
14958
|
+
* calls. The invocation itself never throws out of here: an infra
|
|
14959
|
+
* failure settles as a synthesized error result and the
|
|
14960
|
+
* reconciliation falls back to the raw digest summary.
|
|
14961
|
+
*/
|
|
14962
|
+
const runSynthesisNote = async (record) => {
|
|
14963
|
+
const spec = opts?.synthesis;
|
|
14964
|
+
const finishOnly = buildOrchestratorTools(orchestratorRuntime, fullCardText).filter((tool) => tool.name === FINISH_TOOL_NAME);
|
|
14965
|
+
const digest = digestOf(record, record.settled);
|
|
14966
|
+
const prompt = [
|
|
14967
|
+
"You are an incremental synthesis note of an orchestrated run. Digest the SINGLE settled child below into a self-contained note for the final deterministic reconciliation by calling finish({ result }) EXACTLY once, where result is a STRING. Preserve concrete evidence and citations; do not invent findings. No other tool exists.",
|
|
14968
|
+
...spec.instructions === void 0 ? [] : [spec.instructions],
|
|
14969
|
+
`GOAL: ${goal}`,
|
|
14970
|
+
`CHILD: ${JSON.stringify(digest)}`
|
|
14971
|
+
].join("\n");
|
|
14972
|
+
const noteState = { ...callingState };
|
|
14973
|
+
if (orchestratorAccount !== void 0) noteState.budgetScope = orchestratorAccount;
|
|
14974
|
+
const noteOpts = {
|
|
14975
|
+
role: "synthesize",
|
|
14976
|
+
result: "full",
|
|
14977
|
+
tools: finishOnly,
|
|
14978
|
+
limits: spec.noteLimits ?? { maxTurns: 2 },
|
|
14979
|
+
...spec.model === void 0 ? {} : { model: spec.model },
|
|
14980
|
+
...spec.effort === void 0 ? {} : { effort: spec.effort },
|
|
14981
|
+
...spec.estCost === void 0 ? {} : { estCost: spec.estCost },
|
|
14982
|
+
[kTerminalTool]: { name: FINISH_TOOL_NAME }
|
|
14983
|
+
};
|
|
14984
|
+
return runtime.runInScope(noteState, () => ctx.agent(prompt, noteOpts));
|
|
14985
|
+
};
|
|
14986
|
+
/**
|
|
14987
|
+
* Note dispatch is idempotent per child: the settle hook and the
|
|
14988
|
+
* reconciliation both come through here, and the map guarantees one
|
|
14989
|
+
* dispatch per nodeId (a concurrent identical dispatch would mint a
|
|
14990
|
+
* second occurrence and PAY twice: the v1.32.0 lesson).
|
|
14991
|
+
*/
|
|
14992
|
+
const ensureSynthesisNote = (record) => {
|
|
14993
|
+
const existing = synthesisNotes.get(record.nodeId);
|
|
14994
|
+
if (existing !== void 0) return existing;
|
|
14995
|
+
const note = runSynthesisNote(record).catch((thrown) => ({
|
|
14996
|
+
status: "error",
|
|
14997
|
+
output: null,
|
|
14998
|
+
usage: {
|
|
14999
|
+
inputTokens: 0,
|
|
15000
|
+
outputTokens: 0,
|
|
15001
|
+
cacheReadTokens: 0,
|
|
15002
|
+
cacheWriteTokens: 0
|
|
15003
|
+
},
|
|
15004
|
+
costUsd: 0,
|
|
15005
|
+
turns: 0,
|
|
15006
|
+
servedBy: "unknown:unknown",
|
|
15007
|
+
transcriptRef: "",
|
|
15008
|
+
errorMessage: thrown instanceof Error ? thrown.message : String(thrown)
|
|
15009
|
+
}));
|
|
15010
|
+
synthesisNotes.set(record.nodeId, note);
|
|
15011
|
+
return note;
|
|
15012
|
+
};
|
|
15013
|
+
if (opts?.synthesis?.mode === "incremental" && capDecisionRef === void 0) synthesisNoteDispatcher = ensureSynthesisNote;
|
|
15014
|
+
/**
|
|
15015
|
+
* The deterministic reconciliation of 'incremental' synthesis: the
|
|
15016
|
+
* final result is a PURE fold of the journaled draft and the note
|
|
15017
|
+
* results in spawn order, never another model call. A note that died
|
|
15018
|
+
* falls back to the child's raw digest summary under a journaled
|
|
15019
|
+
* per-child decision and a warn log. With dedupeClaims, repeated
|
|
15020
|
+
* claim lines keep their first occurrence and the envelope carries
|
|
15021
|
+
* the repeatedClaims index.
|
|
15022
|
+
*/
|
|
15023
|
+
const reconcileIncremental = async (draft, spec) => {
|
|
15024
|
+
synthesisSettleFrozen = true;
|
|
15025
|
+
const settledRecords = [...records.values()].filter((record) => record.settled !== void 0).sort((a, b) => a.spawnOrdinal - b.spawnOrdinal);
|
|
15026
|
+
const sections = [];
|
|
15027
|
+
for (const record of settledRecords) {
|
|
15028
|
+
const settled = record.settled;
|
|
15029
|
+
const note = await ensureSynthesisNote(record);
|
|
15030
|
+
let noteText;
|
|
15031
|
+
if (note.status === "ok") noteText = typeof note.output === "string" ? note.output : JSON.stringify(note.output ?? null);
|
|
15032
|
+
else {
|
|
15033
|
+
const fallbackKey = deriverV2.deriveKey({
|
|
15034
|
+
kind: "orchestrator-synthesis-note-fallback",
|
|
15035
|
+
nodeId: record.nodeId
|
|
15036
|
+
});
|
|
15037
|
+
if (!internals.replayer.snapshot().some((entry) => entry.kind === "decision" && entry.key === fallbackKey)) await internals.replayer.appendSinglePhase({
|
|
15038
|
+
scope: callingState.scope,
|
|
15039
|
+
key: fallbackKey,
|
|
15040
|
+
kind: "decision",
|
|
15041
|
+
status: "ok",
|
|
15042
|
+
spanId: internals.spans.mint(callingState.spanId),
|
|
15043
|
+
site: "orchestrator-synthesis",
|
|
15044
|
+
value: {
|
|
15045
|
+
decisionType: "orchestrator_synthesis_note_fallback",
|
|
15046
|
+
nodeId: record.nodeId,
|
|
15047
|
+
status: note.status,
|
|
15048
|
+
turnsUsed: note.turns
|
|
15049
|
+
}
|
|
15050
|
+
});
|
|
15051
|
+
internals.events.emit({
|
|
15052
|
+
type: "log",
|
|
15053
|
+
level: "warn",
|
|
15054
|
+
msg: `the synthesis note for child '${record.nodeId}' terminated with status '${note.status}'; falling back to the raw digest summary (journaled decision 'orchestrator_synthesis_note_fallback')`
|
|
15055
|
+
}, callingState.spanId);
|
|
15056
|
+
noteText = digestOf(record, settled).outputSummary;
|
|
15057
|
+
}
|
|
15058
|
+
sections.push({
|
|
15059
|
+
nodeId: record.nodeId,
|
|
15060
|
+
logicalTaskId: record.logicalTaskId,
|
|
15061
|
+
status: settled.status,
|
|
15062
|
+
noteStatus: note.status,
|
|
15063
|
+
note: noteText
|
|
15064
|
+
});
|
|
15065
|
+
}
|
|
15066
|
+
let repeatedClaims;
|
|
15067
|
+
if (spec.dedupeClaims === true) {
|
|
15068
|
+
const deduped = dedupeRepeatedClaims(sections.map((section) => ({
|
|
15069
|
+
nodeId: section.nodeId,
|
|
15070
|
+
text: section.note
|
|
15071
|
+
})));
|
|
15072
|
+
const textByNode = new Map(deduped.rows.map((row) => [row.nodeId, row.text]));
|
|
15073
|
+
for (const section of sections) section.note = textByNode.get(section.nodeId) ?? section.note;
|
|
15074
|
+
repeatedClaims = deduped.repeated;
|
|
15075
|
+
}
|
|
15076
|
+
const draftJson = JSON.stringify(draft ?? null);
|
|
15077
|
+
internals.events.emit({
|
|
15078
|
+
type: "log",
|
|
15079
|
+
level: "debug",
|
|
15080
|
+
msg: "orchestrator synthesis reconciliation",
|
|
15081
|
+
data: {
|
|
15082
|
+
children: sections.length,
|
|
15083
|
+
draftChars: draftJson.length,
|
|
15084
|
+
notesChars: sections.reduce((sum, section) => sum + section.note.length, 0),
|
|
15085
|
+
perChild: sections.map((section) => ({
|
|
15086
|
+
nodeId: section.nodeId,
|
|
15087
|
+
chars: section.note.length
|
|
15088
|
+
})),
|
|
15089
|
+
...repeatedClaims === void 0 ? {} : { repeatedClaims: repeatedClaims.length }
|
|
15090
|
+
}
|
|
15091
|
+
}, callingState.spanId);
|
|
15092
|
+
return {
|
|
15093
|
+
synthesis: "incremental",
|
|
15094
|
+
draft,
|
|
15095
|
+
sections,
|
|
15096
|
+
...repeatedClaims === void 0 ? {} : { repeatedClaims }
|
|
15097
|
+
};
|
|
15098
|
+
};
|
|
15099
|
+
/**
|
|
14428
15100
|
* The post-fan-in synthesis invocation (RV-211): a FRESH agent entry
|
|
14429
15101
|
* with role 'synthesize' on the finish-only toolset (a distinct
|
|
14430
15102
|
* toolsetHash, the reserved-finalizer precedent), its prompt derived
|
|
14431
15103
|
* deterministically from the goal, the journaled coordination draft,
|
|
14432
15104
|
* and the settled child digest, so a resume replays it by identity
|
|
14433
15105
|
* with zero paid calls. Runs strictly AFTER the acceptance verdict
|
|
14434
|
-
* (a rejected run never pays for synthesis
|
|
14435
|
-
*
|
|
14436
|
-
*
|
|
14437
|
-
*
|
|
14438
|
-
*
|
|
15106
|
+
* (a rejected run never pays for synthesis; in 'incremental' mode
|
|
15107
|
+
* the per-child notes are paid DURING the run, so only the
|
|
15108
|
+
* reconciliation itself is deferred) and owns the finish validators
|
|
15109
|
+
* when they are configured. Failure posture: with validators the run
|
|
15110
|
+
* fails typed (the validated path is mandatory); without them the
|
|
15111
|
+
* run falls back to the draft under a journaled decision and a warn
|
|
15112
|
+
* log, never silently.
|
|
14439
15113
|
*/
|
|
14440
15114
|
const runSynthesis = async (draft) => {
|
|
14441
15115
|
const spec = opts?.synthesis;
|
|
14442
15116
|
if (spec === void 0) return draft;
|
|
14443
15117
|
await recoveryDone;
|
|
15118
|
+
if (spec.mode === "incremental") return await reconcileIncremental(draft, spec);
|
|
14444
15119
|
const finishOnly = buildOrchestratorTools(orchestratorRuntime, fullCardText).filter((tool) => tool.name === FINISH_TOOL_NAME);
|
|
14445
15120
|
const settledDigests = [...records.values()].filter((record) => record.settled !== void 0).sort((a, b) => a.spawnOrdinal - b.spawnOrdinal).map((record) => digestOf(record, record.settled));
|
|
15121
|
+
let digestRows = settledDigests;
|
|
15122
|
+
let repeatedClaims;
|
|
15123
|
+
if (spec.dedupeClaims === true) {
|
|
15124
|
+
const deduped = dedupeRepeatedClaims(settledDigests.map((row) => ({
|
|
15125
|
+
nodeId: row.nodeId,
|
|
15126
|
+
text: row.outputSummary
|
|
15127
|
+
})));
|
|
15128
|
+
const textByNode = new Map(deduped.rows.map((row) => [row.nodeId, row.text]));
|
|
15129
|
+
digestRows = settledDigests.map((row) => ({
|
|
15130
|
+
...row,
|
|
15131
|
+
outputSummary: textByNode.get(row.nodeId) ?? row.outputSummary
|
|
15132
|
+
}));
|
|
15133
|
+
repeatedClaims = deduped.repeated;
|
|
15134
|
+
}
|
|
14446
15135
|
const draftJson = JSON.stringify(draft ?? null);
|
|
14447
|
-
const digestJson = JSON.stringify(
|
|
15136
|
+
const digestJson = JSON.stringify(digestRows);
|
|
14448
15137
|
const prompt = [
|
|
14449
15138
|
"You are the synthesis invocation of an orchestrated run. Compose the FINAL result of the run from the goal, the coordination draft, and the settled child evidence below by calling finish({ result }) EXACTLY once. Preserve the evidence and citations the draft relies on; do not invent findings. No other tool exists.",
|
|
15139
|
+
...repeatedClaims === void 0 ? [] : ["Repeated claims across children were deduplicated before this prompt: only the first occurrence of each repeated line remains in the digest, and the REPEATED CLAIMS index below lists each one with its reporters."],
|
|
14450
15140
|
...spec.instructions === void 0 ? [] : [spec.instructions],
|
|
14451
15141
|
...finishValidationPromptLines(validationSpec),
|
|
14452
15142
|
`GOAL: ${goal}`,
|
|
14453
15143
|
`DRAFT: ${draftJson}`,
|
|
14454
|
-
`DIGEST: ${digestJson}
|
|
15144
|
+
`DIGEST: ${digestJson}`,
|
|
15145
|
+
...repeatedClaims === void 0 ? [] : [`REPEATED CLAIMS: ${JSON.stringify(repeatedClaims)}`]
|
|
14455
15146
|
].join("\n");
|
|
14456
15147
|
internals.events.emit({
|
|
14457
15148
|
type: "log",
|
|
@@ -14462,10 +15153,11 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
14462
15153
|
draftChars: draftJson.length,
|
|
14463
15154
|
digestChars: digestJson.length,
|
|
14464
15155
|
promptChars: prompt.length,
|
|
14465
|
-
perChild:
|
|
15156
|
+
perChild: digestRows.map((entry) => ({
|
|
14466
15157
|
nodeId: entry.nodeId,
|
|
14467
15158
|
chars: JSON.stringify(entry).length
|
|
14468
|
-
}))
|
|
15159
|
+
})),
|
|
15160
|
+
...repeatedClaims === void 0 ? {} : { repeatedClaims: repeatedClaims.length }
|
|
14469
15161
|
}
|
|
14470
15162
|
}, callingState.spanId);
|
|
14471
15163
|
const synthesisState = { ...callingState };
|
|
@@ -14586,6 +15278,7 @@ function makeOrchestratorWorkflow(goal, opts) {
|
|
|
14586
15278
|
const required = decision.childPolicy === "all-ok" ? "every child ok" : `at least ${String(decision.childPolicy.minSuccessful)} children ok`;
|
|
14587
15279
|
throw new FailRunError(`the orchestrator acceptance policy rejected the finish: ${String(decision.childStatusCounts.ok ?? 0)} children settled 'ok' but the policy requires ${required}; degraded: ${decision.degradedReasons.join("; ")}`, { data: {
|
|
14588
15280
|
source: "orchestrator_acceptance",
|
|
15281
|
+
completion: "rejected",
|
|
14589
15282
|
childPolicy: decision.childPolicy,
|
|
14590
15283
|
childStatusCounts: decision.childStatusCounts,
|
|
14591
15284
|
degradedReasons: decision.degradedReasons
|
|
@@ -15243,6 +15936,32 @@ function workflowSourceRef(runId) {
|
|
|
15243
15936
|
return `${runId}/workflow-source`;
|
|
15244
15937
|
}
|
|
15245
15938
|
/**
|
|
15939
|
+
* The completion envelope contract (RV-207 tail): a workflow reports
|
|
15940
|
+
* SEMANTIC completion by returning an object result carrying a
|
|
15941
|
+
* `completion` literal (and optionally `childStatusCounts`), or by
|
|
15942
|
+
* throwing a typed RulvarError whose `data` carries them; the engine
|
|
15943
|
+
* lifts the validated fields onto the `run:end` event so telemetry
|
|
15944
|
+
* consumers read completeness without parsing workflow-specific result
|
|
15945
|
+
* shapes. The orchestrator acceptance path emits this envelope. Pure
|
|
15946
|
+
* shape validation: anything malformed is silently absent (the event is
|
|
15947
|
+
* telemetry, never authority), and an invalid counts record drops the
|
|
15948
|
+
* counts while keeping a valid completion.
|
|
15949
|
+
*/
|
|
15950
|
+
function liftRunCompletion(candidate) {
|
|
15951
|
+
if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) return;
|
|
15952
|
+
const completion = candidate.completion;
|
|
15953
|
+
if (completion !== "complete" && completion !== "partial" && completion !== "rejected") return;
|
|
15954
|
+
const counts = candidate.childStatusCounts;
|
|
15955
|
+
if (typeof counts === "object" && counts !== null && !Array.isArray(counts)) {
|
|
15956
|
+
const entries = Object.entries(counts);
|
|
15957
|
+
if (entries.every(([, value]) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0)) return {
|
|
15958
|
+
completion,
|
|
15959
|
+
childStatusCounts: Object.fromEntries(entries)
|
|
15960
|
+
};
|
|
15961
|
+
}
|
|
15962
|
+
return { completion };
|
|
15963
|
+
}
|
|
15964
|
+
/**
|
|
15246
15965
|
* sha256 hex over the JCS canonical serialization of a run's args: the
|
|
15247
15966
|
* value the engine records as `RunMeta.argsHash` at genesis, exposed so
|
|
15248
15967
|
* hosts can verify re-supplied resume args against the recorded hash
|
|
@@ -15613,11 +16332,13 @@ function createEngine(options) {
|
|
|
15613
16332
|
}
|
|
15614
16333
|
}
|
|
15615
16334
|
await putMeta(status).catch(() => void 0);
|
|
16335
|
+
const lifted = liftRunCompletion(status === "ok" || status === "exhausted" ? outcome.value : status === "error" ? wireError?.data : void 0);
|
|
15616
16336
|
bus.emit({
|
|
15617
16337
|
type: "run:end",
|
|
15618
16338
|
status,
|
|
15619
16339
|
totalUsd: ledger.usd,
|
|
15620
|
-
...outcome.cost.usageApprox === true ? { usageApprox: true } : {}
|
|
16340
|
+
...outcome.cost.usageApprox === true ? { usageApprox: true } : {},
|
|
16341
|
+
...lifted === void 0 ? {} : lifted
|
|
15621
16342
|
}, rootSpanId);
|
|
15622
16343
|
bus.end();
|
|
15623
16344
|
resumeCtx?.previewResolve({
|
|
@@ -16089,4 +16810,4 @@ function createSandboxBridge(ctx, options) {
|
|
|
16089
16810
|
};
|
|
16090
16811
|
}
|
|
16091
16812
|
//#endregion
|
|
16092
|
-
export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, requiredFieldsValidator, requiredSectionsValidator, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
|
16813
|
+
export { AWAIT_SCHEMA, AdmissionController, AdmissionRejectedError, AgentCallError, BUDGET_ABORT_REASON, BudgetExhaustedError, CANCEL_AGENT_SCHEMA, CHECKPOINT_FORMAT_V1, CLAIM_STATEMENT_MAX_CHARS, CLAIM_TTL_DAYS, COMPACTION_SUMMARY_PREFIX, CURRENT_HASH_VERSION, ConfigError, DEFAULT_CHILD_BUDGET_FRACTION, DEFAULT_CHILD_RESULT_PAGE_CHARS, DEFAULT_CITATION_PATTERN, DEFAULT_COMPACTION_THRESHOLD, DEFAULT_ESCALATION_LIMITS, DEFAULT_EVIDENCE_MIN_SHARE, DEFAULT_FINISH_MAX_REPAIRS, DEFAULT_FLAT_RESERVE_USD, DEFAULT_MAX_CHILDREN_PER_NODE, DEFAULT_MAX_DEPTH, DEFAULT_MAX_OSCILLATIONS_PER_KEY, DEFAULT_MAX_PINNED_WORKTREES, DEFAULT_MAX_REVISIONS_PER_RUN, DEFAULT_MAX_TOTAL_SPAWNS, DEFAULT_MAX_TURNS, DEFAULT_MODEL_RETRY_ATTEMPTS, DEFAULT_NO_PROGRESS_TURNS, DEFAULT_PER_RUN_CONCURRENCY, DEFAULT_RETRY_POLICY, DEFAULT_STREAM_IDLE_TIMEOUT_MS, DEFAULT_SYNTHESIS_MAX_TURNS, DEFAULT_SYNTHESIS_NOTE_MAX_TURNS, DedupIndex, DeterminismError, EMIT_RESULT_TOOL, EMPTY_SCHEMA_HASH, EMPTY_TOOLSET_HASH, ESCALATE_TOOL_NAME, ESCALATION_REPORT_SCHEMA, ESCALATION_REQUEST_SCHEMA, EVENT_SEGMENT_STRIDE, EscalationDecisionAbortedError, EventBus, ExternalRegistry, FINALIZE_SYNTHESIS_INSTRUCTION, FINISH_SCHEMA, FINISH_TOOL_NAME, FailRunError, FileModelKnowledgeStore, FileTranscriptStore, GET_CHILD_RESULT_SCHEMA, GET_CHILD_RESULT_TOOL_NAME, GitWorktreeProvider, INBOX_PROPOSAL_TTL_DAYS, InMemoryStore, InMemoryTranscriptStore, InProcessRunner, InvalidResolutionError, JournalCompatibilityError, JournalMatcher, JournalMissError, JournalOrderViolation, JsonlFileStore, KB_ACTIVE_CLAIMS_CAP, KB_CARD_RENDER_BUDGET_CHARS, KeyedLimiter, KnowledgeCasError, LARGE_VALUE_WARN_BYTES, LEGACY_LTID_PREFIX, LEGACY_SIGNATURE_INPUTS, LINEAGE_SIG_VERSION, LeaseHeldError, LineageIndex, MASKED_SECRET, MAX_CHILD_RESULT_PAGE_CHARS, MAX_DEPTH_CEILING, ModelRetry, NoProgressDetector, NonSerializableValueError, ORCHESTRATE_WORKFLOW_NAME, OrchestratorCapConfigError, PARALLEL_AGENTS_SCHEMA, ParallelSiteCounter, PlanInvariantError, READ_CHILD_ARTIFACT_SCHEMA, READ_CHILD_ARTIFACT_TOOL_NAME, ROLE_EFFORT_DEFAULTS, ROOT_ACCOUNT, ROOT_SCOPE, RUN_PROFILES, RUN_SETTLE_DECISION_TYPE, ReplayPlanHashMismatch, Replayer, ResolutionArbiter, ResolutionFold, RulvarError, RunBudget, SANDBOX_AGENT_OPT_KEYS, SPAWN_AGENT_SCHEMA, SandboxError, ScriptRejected, Semaphore, SpanRegistry, TOOL_NAME_PATTERN, TerminationAccount, WAIT_FOR_EVENTS_SCHEMA, WAIT_FOR_EVENTS_TOOL_NAME, WAKE_SUMMARY_RENDER_BUDGET_CHARS, admissionReserveUsd, affordableOutputTokens, agentErrorFromWire, agentErrorToWire, agentResultWire, agentScope, applyClaimOps, applyStructuredOutputTier, approachSigCoarse, approachSigOf, archiveDeprecatedModelOps, assertFencedWrites, atCompactionThreshold, auditRun, auditRuns, buildAbandonFold, buildAdapterRegistry, buildCostReport, buildDeriverRegistry, buildOrchestratorTools, buildTerminationInitValue, buildToolContext, canRideLoopTurn, canonicalIsolationTag, canonicalizeLadder, canonicalizeSchema, capIssues, capsHashOf, checkFloors, checkpointRefFor, childCoveragePrefix, claimExpired, claimExpiry, claimIssues, claimOpIssues, classifyAgentError, classifyAttemptOutcome, collectDeclaredLadders, compactMessages, compilePermissionChain, compilePermissionPreset, compileVerifiedLayer, costReportFromJournal, countsAgainstLimit, createCanonicalIdMinter, createCtx, createEngine, createSandboxBridge, currentOnlyKeyRing, decodeCheckpoint, dedupeRepeatedClaims, defineWorkflow, deriveContentKey, deriverV1, deriverV2, digestOf, dispositionHook, emptyDigestBlocks, emptyToolset, encodeCheckpoint, entryUsageSlices, escalateTool, evaluatePermission, evaluateReuse, evidencePreservedValidator, executeWorkflow, exhaustionCodeOf, extractCandidate, failoverTriggerOf, fallbackTriggerOf, filterClaimsForRun, finalizeFires, foldTermination, formatRePrompt, formatScopePath, hasFencedWrites, hasMetaLookup, hashRunArgs, hashRunOutput, hashWorkflowBody, hashWorkflowSource, identityJcs, isEscalated, isSchemaPairSpec, isStandardSchemaSpec, isStrictCompatibleSchema, kMaxOf, knowledgeHash, ladderLengthOf, ladderRungChoice, lastRunSettle, lexShellCommand, liftRetainedParts, lineageWeightOf, makeOrchestratorWorkflow, maskSecrets, maskSecretsDeep, maskSecretsJson, matchArgvPattern, matchShellCommand, mcp, mergeUsageLimits, metaMatchesFilter, minMatchesValidator, modelEpochOf, modelKnowledgeCard, modelSpecIdentity, needsSeparateExtract, nextFailover, nodeLinkKey, normalizeApproachTag, normalizeEntry, normalizeFallbacks, orchestrate, parallelScope, parseModelRef, parseScopePath, phiInitialOf, pipelineScope, planNodeScope, priceEntryUsage, priceUsdOf, profileCard, profileRegistrySnapshotHash, projectHistory, projectIdentity, projectToJsonSchema, proposalStatement, providerOf, readRunMeta, readTerminationInit, reconcileRunMeta, reduceCriticalPath, reduceInvocationTable, registryKeyRing, remeasureQueue, replayDisposition, repositoryResearchToolset, requiredFieldsValidator, requiredSectionsValidator, resolveModelInvocation, resolvePricing, resolveToolset, retryClassOf, retryDelayMs, roleConfiguredInRouting, roundOneDisposition, runAgent, runProfile, sanitizeTerminalText, sanitizeTokenCount, sanitizeUsage, sanitizeUsageDelta, scanJournalCompatibility, schemaHash, schemaHashOfSpec, selectStructuredOutputTier, shouldCompact, snapshotUsage, spawnDepthOf, summarizeInstruction, summarizeOutput, terminationConfigDrift, tierWithinCaps, toApprovalDecision, toJournalValue, tool, toolContract, toolsetHash, ttlState, usageViolations, validateEditorialCommit, validateEntryShape, validateEscalationLimits, validateEscalationReport, validateRetryPolicy, validateSchemaSpec, validateTerminationLimits, validateUsageLimits, workflowScope, workflowSourceRef, wrapJournalStore, wrapTranscriptStore };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulvar/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.54.0",
|
|
4
4
|
"description": "Rulvar core: L0 contracts, journal kernel, ctx primitives, agent runtime, model router, tool system, dynamic orchestrator, InMemory and JSONL stores, event stream.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|