specrails-core 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-runtime/capabilities.js +3 -1
- package/dist/agent-runtime/change-scope.d.ts +63 -0
- package/dist/agent-runtime/change-scope.js +297 -0
- package/dist/agent-runtime/cli-executor.d.ts +3 -0
- package/dist/agent-runtime/cli-executor.js +50 -13
- package/dist/agent-runtime/cli-process.js +6 -2
- package/dist/agent-runtime/cli.d.ts +15 -0
- package/dist/agent-runtime/cli.js +43 -9
- package/dist/agent-runtime/compact/chat-client.js +2 -1
- package/dist/agent-runtime/compact/environment.d.ts +12 -0
- package/dist/agent-runtime/compact/environment.js +31 -1
- package/dist/agent-runtime/compact/test-reachability.js +6 -2
- package/dist/agent-runtime/config.d.ts +4 -1
- package/dist/agent-runtime/config.js +41 -3
- package/dist/agent-runtime/core-host.d.ts +10 -4
- package/dist/agent-runtime/core-host.js +22 -19
- package/dist/agent-runtime/efficiency-summary.d.ts +4 -1
- package/dist/agent-runtime/efficiency-summary.js +30 -27
- package/dist/agent-runtime/efficiency-types.d.ts +4 -4
- package/dist/agent-runtime/efficiency.d.ts +1 -1
- package/dist/agent-runtime/efficiency.js +7 -6
- package/dist/agent-runtime/engine/__fixtures__/implementation-component.json +90 -0
- package/dist/agent-runtime/engine/__fixtures__/implementation-fixture.d.ts +11 -0
- package/dist/agent-runtime/engine/__fixtures__/implementation-fixture.js +60 -0
- package/dist/agent-runtime/engine/__fixtures__/implementation.json +43 -0
- package/dist/agent-runtime/engine/budget.d.ts +9 -0
- package/dist/agent-runtime/engine/budget.js +33 -0
- package/dist/agent-runtime/engine/canonical-json.d.ts +9 -0
- package/dist/agent-runtime/engine/canonical-json.js +162 -0
- package/dist/agent-runtime/engine/checkpoint/database.d.ts +67 -0
- package/dist/agent-runtime/engine/checkpoint/database.js +304 -0
- package/dist/agent-runtime/engine/checkpoint/lease.d.ts +17 -0
- package/dist/agent-runtime/engine/checkpoint/lease.js +82 -0
- package/dist/agent-runtime/engine/checkpoint/ledger.d.ts +133 -0
- package/dist/agent-runtime/engine/checkpoint/ledger.js +510 -0
- package/dist/agent-runtime/engine/checkpoint/saver.d.ts +25 -0
- package/dist/agent-runtime/engine/checkpoint/saver.js +146 -0
- package/dist/agent-runtime/engine/cli.d.ts +10 -0
- package/dist/agent-runtime/engine/cli.js +172 -0
- package/dist/agent-runtime/engine/compiler.d.ts +23 -0
- package/dist/agent-runtime/engine/compiler.js +261 -0
- package/dist/agent-runtime/engine/composition.d.ts +16 -0
- package/dist/agent-runtime/engine/composition.js +28 -0
- package/dist/agent-runtime/engine/concurrency.d.ts +14 -0
- package/dist/agent-runtime/engine/concurrency.js +55 -0
- package/dist/agent-runtime/engine/contracts.d.ts +273 -0
- package/dist/agent-runtime/engine/contracts.js +11 -0
- package/dist/agent-runtime/engine/definition-schema.d.ts +250 -0
- package/dist/agent-runtime/engine/definition-schema.js +313 -0
- package/dist/agent-runtime/engine/definition-types.d.ts +84 -0
- package/dist/agent-runtime/engine/definition-types.js +3 -0
- package/dist/agent-runtime/engine/definition-validator.d.ts +7 -0
- package/dist/agent-runtime/engine/definition-validator.js +187 -0
- package/dist/agent-runtime/engine/efficiency-summary.d.ts +62 -0
- package/dist/agent-runtime/engine/efficiency-summary.js +31 -0
- package/dist/agent-runtime/engine/events.d.ts +19 -0
- package/dist/agent-runtime/engine/events.js +88 -0
- package/dist/agent-runtime/engine/execution.d.ts +29 -0
- package/dist/agent-runtime/engine/execution.js +121 -0
- package/dist/agent-runtime/engine/expressions.d.ts +11 -0
- package/dist/agent-runtime/engine/expressions.js +172 -0
- package/dist/agent-runtime/engine/fork.d.ts +28 -0
- package/dist/agent-runtime/engine/fork.js +211 -0
- package/dist/agent-runtime/engine/graph-description.d.ts +48 -0
- package/dist/agent-runtime/engine/graph-description.js +16 -0
- package/dist/agent-runtime/engine/implementation-compiler.d.ts +214 -0
- package/dist/agent-runtime/engine/implementation-compiler.js +91 -0
- package/dist/agent-runtime/engine/index.d.ts +14 -0
- package/dist/agent-runtime/engine/index.js +14 -0
- package/dist/agent-runtime/engine/invocation-context.d.ts +11 -0
- package/dist/agent-runtime/engine/invocation-context.js +128 -0
- package/dist/agent-runtime/engine/otel.d.ts +15 -0
- package/dist/agent-runtime/engine/otel.js +132 -0
- package/dist/agent-runtime/engine/output.d.ts +4 -0
- package/dist/agent-runtime/engine/output.js +73 -0
- package/dist/agent-runtime/engine/piece-dependencies.d.ts +50 -0
- package/dist/agent-runtime/engine/piece-dependencies.js +193 -0
- package/dist/agent-runtime/engine/piece-registry.d.ts +19 -0
- package/dist/agent-runtime/engine/piece-registry.js +62 -0
- package/dist/agent-runtime/engine/pieces/assign.d.ts +4 -0
- package/dist/agent-runtime/engine/pieces/assign.js +35 -0
- package/dist/agent-runtime/engine/pieces/control.d.ts +5 -0
- package/dist/agent-runtime/engine/pieces/control.js +49 -0
- package/dist/agent-runtime/engine/pieces/decider.d.ts +5 -0
- package/dist/agent-runtime/engine/pieces/decider.js +70 -0
- package/dist/agent-runtime/engine/pieces/implementation-binding.d.ts +12 -0
- package/dist/agent-runtime/engine/pieces/implementation-binding.js +40 -0
- package/dist/agent-runtime/engine/pieces/implementation-journal.d.ts +25 -0
- package/dist/agent-runtime/engine/pieces/implementation-journal.js +192 -0
- package/dist/agent-runtime/engine/pieces/implementation.d.ts +23 -0
- package/dist/agent-runtime/engine/pieces/implementation.js +176 -0
- package/dist/agent-runtime/engine/pieces/index.d.ts +7 -0
- package/dist/agent-runtime/engine/pieces/index.js +22 -0
- package/dist/agent-runtime/engine/pieces/openspec.d.ts +3 -0
- package/dist/agent-runtime/engine/pieces/openspec.js +69 -0
- package/dist/agent-runtime/engine/pieces/ports.d.ts +48 -0
- package/dist/agent-runtime/engine/pieces/ports.js +1 -0
- package/dist/agent-runtime/engine/pieces/project-memory.d.ts +3 -0
- package/dist/agent-runtime/engine/pieces/project-memory.js +13 -0
- package/dist/agent-runtime/engine/pieces/prompt.d.ts +5 -0
- package/dist/agent-runtime/engine/pieces/prompt.js +130 -0
- package/dist/agent-runtime/engine/pieces/role-turn.d.ts +7 -0
- package/dist/agent-runtime/engine/pieces/role-turn.js +73 -0
- package/dist/agent-runtime/engine/pieces/shared.d.ts +67 -0
- package/dist/agent-runtime/engine/pieces/shared.js +40 -0
- package/dist/agent-runtime/engine/pieces/shell.d.ts +6 -0
- package/dist/agent-runtime/engine/pieces/shell.js +47 -0
- package/dist/agent-runtime/engine/pieces/verify.d.ts +7 -0
- package/dist/agent-runtime/engine/pieces/verify.js +52 -0
- package/dist/agent-runtime/engine/preflight.d.ts +27 -0
- package/dist/agent-runtime/engine/preflight.js +54 -0
- package/dist/agent-runtime/engine/regex.d.ts +3 -0
- package/dist/agent-runtime/engine/regex.js +19 -0
- package/dist/agent-runtime/engine/run-status.d.ts +563 -0
- package/dist/agent-runtime/engine/run-status.js +61 -0
- package/dist/agent-runtime/engine/runs.d.ts +605 -0
- package/dist/agent-runtime/engine/runs.js +247 -0
- package/dist/agent-runtime/engine/state.d.ts +64 -0
- package/dist/agent-runtime/engine/state.js +98 -0
- package/dist/agent-runtime/engine/steering/inbox.d.ts +54 -0
- package/dist/agent-runtime/engine/steering/inbox.js +113 -0
- package/dist/agent-runtime/engine/storage/fork-allocation.d.ts +21 -0
- package/dist/agent-runtime/engine/storage/fork-allocation.js +143 -0
- package/dist/agent-runtime/engine/storage/private-path.d.ts +11 -0
- package/dist/agent-runtime/engine/storage/private-path.js +74 -0
- package/dist/agent-runtime/engine/store/sqlite-store.d.ts +26 -0
- package/dist/agent-runtime/engine/store/sqlite-store.js +227 -0
- package/dist/agent-runtime/evaluation-corpus.d.ts +125 -0
- package/dist/agent-runtime/evaluation-corpus.js +4 -0
- package/dist/agent-runtime/evaluation.d.ts +9 -3
- package/dist/agent-runtime/evaluation.js +50 -8
- package/dist/agent-runtime/executor-types.d.ts +53 -3
- package/dist/agent-runtime/executor-types.js +35 -2
- package/dist/agent-runtime/executors.js +2 -2
- package/dist/agent-runtime/graph/artifacts.d.ts +7 -0
- package/dist/agent-runtime/graph/artifacts.js +86 -10
- package/dist/agent-runtime/graph/convergence.d.ts +26 -0
- package/dist/agent-runtime/graph/convergence.js +62 -0
- package/dist/agent-runtime/graph/nodes.d.ts +2 -0
- package/dist/agent-runtime/graph/nodes.js +171 -24
- package/dist/agent-runtime/graph/roles.d.ts +6 -0
- package/dist/agent-runtime/graph/roles.js +23 -17
- package/dist/agent-runtime/graph/state.d.ts +5 -0
- package/dist/agent-runtime/graph/state.js +2 -0
- package/dist/agent-runtime/kimi-acp.js +6 -6
- package/dist/agent-runtime/openai-executor.js +17 -12
- package/dist/agent-runtime/openspec.d.ts +17 -2
- package/dist/agent-runtime/openspec.js +54 -20
- package/dist/agent-runtime/prompts.d.ts +11 -5
- package/dist/agent-runtime/prompts.js +71 -20
- package/dist/agent-runtime/recovery.d.ts +1 -1
- package/dist/agent-runtime/repository-context.js +20 -1
- package/dist/agent-runtime/role-routing.js +4 -2
- package/dist/agent-runtime/role-state.d.ts +5 -0
- package/dist/agent-runtime/verification-plan.d.ts +2 -0
- package/dist/agent-runtime/verification-plan.js +18 -3
- package/dist/agent-runtime/workflow-types.d.ts +2 -0
- package/dist/agent-runtime/workflow.d.ts +3 -1
- package/dist/agent-runtime/workflow.js +7 -3
- package/dist/agent-runtime/workspace-tools.d.ts +2 -2
- package/dist/agent-runtime/workspace-tools.js +6 -6
- package/dist/installer/cli.js +5 -0
- package/dist/installer/phases/scaffold.d.ts +2 -2
- package/dist/installer/phases/scaffold.js +3 -7
- package/dist/pipeline/pipeline-state.d.ts +49 -4
- package/dist/pipeline/pipeline-state.js +150 -23
- package/integration-contract.json +84 -12
- package/package.json +12 -5
- package/schemas/agent-runtime.schema.json +93 -1
- package/schemas/workflow-definition.schema.json +312 -0
- package/templates/kimi/specrails/run-skill.mjs +15 -1
- package/templates/commands/specrails/batch-implement.md +0 -32
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { SqliteRunSaver } from './checkpoint/saver.js';
|
|
3
|
+
import { compileWorkflowDefinition } from './compiler.js';
|
|
4
|
+
import { DefinitionExecution } from './execution.js';
|
|
5
|
+
import { RunPieceDependencies } from './piece-dependencies.js';
|
|
6
|
+
import { createPieceRegistry } from './pieces/index.js';
|
|
7
|
+
import { createImplementationAdapter } from './pieces/implementation.js';
|
|
8
|
+
import { SqliteProjectStore } from './store/sqlite-store.js';
|
|
9
|
+
/** Infrastructure is bound once to the frozen project and the current execution lease. */
|
|
10
|
+
export async function composeDefinitionRuntime(database, ledger, admitted, stream, signal) {
|
|
11
|
+
const memory = await SqliteProjectStore.open(admitted.request.context.backlogRoot);
|
|
12
|
+
const deps = new RunPieceDependencies(admitted.request.context, admitted.request.config, admitted.registry, admitted.definition, ledger, path.dirname(database.filename), admitted.request.change, memory);
|
|
13
|
+
const execution = new DefinitionExecution(ledger, stream, signal, admitted.definition.policies?.concurrency ?? 1, (frame, result, effect) => deps.finalize(frame, result, effect));
|
|
14
|
+
try {
|
|
15
|
+
const saver = new SqliteRunSaver(database, ledger, { onEvents: events => execution.committed(events) });
|
|
16
|
+
const graph = compileWorkflowDefinition(admitted.definition, createPieceRegistry(deps), execution, {
|
|
17
|
+
roles: admitted.roles, checkpointer: saver,
|
|
18
|
+
collections: { tickets: JSON.parse(JSON.stringify(admitted.request.context.specs)), repositories: JSON.parse(JSON.stringify(admitted.request.context.repositories)) },
|
|
19
|
+
implementation: params => createImplementationAdapter(deps, { change: admitted.request.change, params }),
|
|
20
|
+
});
|
|
21
|
+
return { deps, execution, saver, graph, close: () => { execution.close(); memory.close(); } };
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
execution.close();
|
|
25
|
+
memory.close();
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** FIFO weighted permits prevent writers starving behind new read branches. */
|
|
2
|
+
export declare class ConcurrencyGate {
|
|
3
|
+
readonly capacity: number;
|
|
4
|
+
private available;
|
|
5
|
+
private readonly queue;
|
|
6
|
+
constructor(capacity: number);
|
|
7
|
+
acquire(signal?: AbortSignal, weight?: number): Promise<() => void>;
|
|
8
|
+
private drain;
|
|
9
|
+
}
|
|
10
|
+
/** All branches share this gate; a write owns the complete repository effect window. */
|
|
11
|
+
export declare class RepositoryEffectGate {
|
|
12
|
+
private readonly permits;
|
|
13
|
+
acquire(effect: 'read' | 'write', signal?: AbortSignal): Promise<() => void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { EngineError } from './contracts.js';
|
|
2
|
+
/** FIFO weighted permits prevent writers starving behind new read branches. */
|
|
3
|
+
export class ConcurrencyGate {
|
|
4
|
+
capacity;
|
|
5
|
+
available;
|
|
6
|
+
queue = [];
|
|
7
|
+
constructor(capacity) {
|
|
8
|
+
this.capacity = capacity;
|
|
9
|
+
if (!Number.isSafeInteger(capacity) || capacity < 1)
|
|
10
|
+
throw new EngineError('invalid_arguments', 'Concurrency must be a positive integer');
|
|
11
|
+
this.available = capacity;
|
|
12
|
+
}
|
|
13
|
+
acquire(signal, weight = 1) {
|
|
14
|
+
if (!Number.isSafeInteger(weight) || weight < 1 || weight > this.capacity)
|
|
15
|
+
return Promise.reject(new EngineError('invalid_arguments', 'Invalid permit weight'));
|
|
16
|
+
if (signal?.aborted)
|
|
17
|
+
return Promise.reject(new EngineError('aborted', 'Execution cancelled while waiting for admission'));
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
const waiter = { weight, resolve, reject, signal, abort: () => {
|
|
20
|
+
const index = this.queue.indexOf(waiter);
|
|
21
|
+
if (index < 0)
|
|
22
|
+
return;
|
|
23
|
+
this.queue.splice(index, 1);
|
|
24
|
+
signal?.removeEventListener('abort', waiter.abort);
|
|
25
|
+
reject(new EngineError('aborted', 'Execution cancelled while waiting for admission'));
|
|
26
|
+
this.drain();
|
|
27
|
+
} };
|
|
28
|
+
signal?.addEventListener('abort', waiter.abort, { once: true });
|
|
29
|
+
this.queue.push(waiter);
|
|
30
|
+
this.drain();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
drain() {
|
|
34
|
+
while (this.queue.length && this.queue[0].weight <= this.available) {
|
|
35
|
+
const waiter = this.queue.shift();
|
|
36
|
+
waiter.signal?.removeEventListener('abort', waiter.abort);
|
|
37
|
+
this.available -= waiter.weight;
|
|
38
|
+
let released = false;
|
|
39
|
+
waiter.resolve(() => {
|
|
40
|
+
if (released)
|
|
41
|
+
return;
|
|
42
|
+
released = true;
|
|
43
|
+
this.available += waiter.weight;
|
|
44
|
+
this.drain();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** All branches share this gate; a write owns the complete repository effect window. */
|
|
50
|
+
export class RepositoryEffectGate {
|
|
51
|
+
permits = new ConcurrencyGate(Number.MAX_SAFE_INTEGER);
|
|
52
|
+
acquire(effect, signal) {
|
|
53
|
+
return this.permits.acquire(signal, effect === 'write' ? this.permits.capacity : 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import type { JsonValue, WorkflowBudget } from '../workflow-types.js';
|
|
2
|
+
export type { JsonValue, WorkflowBudget };
|
|
3
|
+
export type JsonObject = {
|
|
4
|
+
[key: string]: JsonValue;
|
|
5
|
+
};
|
|
6
|
+
export type EngineEffect = 'read' | 'write';
|
|
7
|
+
export type EngineStepStatus = 'running' | 'succeeded' | 'failed' | 'blocked' | 'paused' | 'interrupted';
|
|
8
|
+
export type EngineRunStatus = EngineStepStatus | 'cancelled';
|
|
9
|
+
/** Stable public LangGraph execution metadata; never parse private namespace keys. */
|
|
10
|
+
export interface TaskIdentity {
|
|
11
|
+
checkpointThreadId: string;
|
|
12
|
+
checkpointId: string;
|
|
13
|
+
taskCheckpointNs: string;
|
|
14
|
+
taskId: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ExecutionScope {
|
|
17
|
+
id: string;
|
|
18
|
+
nodePathPrefix: string;
|
|
19
|
+
branchId?: string;
|
|
20
|
+
/** Nested map limits; the run coordinator acquires them only around physical AI work. */
|
|
21
|
+
limits?: Array<{
|
|
22
|
+
id: string;
|
|
23
|
+
concurrency: number;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export interface ExecutionLease {
|
|
27
|
+
runId: string;
|
|
28
|
+
owner: string;
|
|
29
|
+
epoch: number;
|
|
30
|
+
expiresAt: number;
|
|
31
|
+
}
|
|
32
|
+
export interface AttemptFrame {
|
|
33
|
+
runId: string;
|
|
34
|
+
nodePath: string;
|
|
35
|
+
scope: ExecutionScope;
|
|
36
|
+
task: TaskIdentity;
|
|
37
|
+
visitId: string;
|
|
38
|
+
visit: number;
|
|
39
|
+
transition: number;
|
|
40
|
+
attemptId: string;
|
|
41
|
+
attempt: number;
|
|
42
|
+
leaseEpoch: number;
|
|
43
|
+
}
|
|
44
|
+
export interface NodeRetryPolicy {
|
|
45
|
+
maxAttempts: number;
|
|
46
|
+
retrySafe?: boolean;
|
|
47
|
+
initialIntervalMs?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface NodeAdmission {
|
|
50
|
+
nodePath: string;
|
|
51
|
+
kind: string;
|
|
52
|
+
effect: EngineEffect;
|
|
53
|
+
requiresAI: boolean;
|
|
54
|
+
acceptsSteering?: boolean;
|
|
55
|
+
scope: ExecutionScope;
|
|
56
|
+
task: TaskIdentity;
|
|
57
|
+
retry: NodeRetryPolicy;
|
|
58
|
+
}
|
|
59
|
+
export interface HistoryEntry {
|
|
60
|
+
id: string;
|
|
61
|
+
transition: number;
|
|
62
|
+
attempt: number;
|
|
63
|
+
ordinal: number;
|
|
64
|
+
nodePath: string;
|
|
65
|
+
text: string;
|
|
66
|
+
truncated?: boolean;
|
|
67
|
+
}
|
|
68
|
+
/** Aggregate revision comes from the ledger; checkpoints cannot double-count it. */
|
|
69
|
+
export interface EngineUsage {
|
|
70
|
+
revision: number;
|
|
71
|
+
invocations: number;
|
|
72
|
+
costUsd: number | null;
|
|
73
|
+
inputTokens: number | null;
|
|
74
|
+
outputTokens: number | null;
|
|
75
|
+
knownCostUsd: number;
|
|
76
|
+
knownInputTokens: number;
|
|
77
|
+
knownOutputTokens: number;
|
|
78
|
+
}
|
|
79
|
+
export interface CandidateState {
|
|
80
|
+
hash: string;
|
|
81
|
+
atTransition: number;
|
|
82
|
+
revision: number;
|
|
83
|
+
/** Logical scope and exact metadata exclusions travel with a historical fork. */
|
|
84
|
+
scope?: JsonObject;
|
|
85
|
+
}
|
|
86
|
+
export interface VerifiedState {
|
|
87
|
+
receiptId: string;
|
|
88
|
+
candidateHash: string;
|
|
89
|
+
atTransition: number;
|
|
90
|
+
revision: number;
|
|
91
|
+
}
|
|
92
|
+
/** Evidence stays JSON; the verification adapter owns the legacy receipt format. */
|
|
93
|
+
export interface ReceiptEvidence {
|
|
94
|
+
id: string;
|
|
95
|
+
candidateHash: string;
|
|
96
|
+
valid: boolean;
|
|
97
|
+
scope: 'full' | 'scoped';
|
|
98
|
+
evidence: JsonValue;
|
|
99
|
+
}
|
|
100
|
+
export interface EngineCompletion {
|
|
101
|
+
ok: boolean;
|
|
102
|
+
reasons: string[];
|
|
103
|
+
verified: boolean;
|
|
104
|
+
}
|
|
105
|
+
export interface EngineAnswer {
|
|
106
|
+
id: string;
|
|
107
|
+
transition: number;
|
|
108
|
+
attempt: number;
|
|
109
|
+
ordinal: number;
|
|
110
|
+
nodePath: string;
|
|
111
|
+
value: JsonValue;
|
|
112
|
+
}
|
|
113
|
+
export interface BranchResult {
|
|
114
|
+
id: string;
|
|
115
|
+
transition: number;
|
|
116
|
+
attempt: number;
|
|
117
|
+
ordinal: number;
|
|
118
|
+
index: number;
|
|
119
|
+
outcome: string;
|
|
120
|
+
output: JsonValue;
|
|
121
|
+
}
|
|
122
|
+
export interface BranchState {
|
|
123
|
+
total: number;
|
|
124
|
+
results: BranchResult[];
|
|
125
|
+
visitId?: string;
|
|
126
|
+
transition?: number;
|
|
127
|
+
done?: number;
|
|
128
|
+
}
|
|
129
|
+
export interface MapPlan {
|
|
130
|
+
frame: AttemptFrame;
|
|
131
|
+
items: JsonValue[];
|
|
132
|
+
}
|
|
133
|
+
export interface ComponentExit {
|
|
134
|
+
outcome: string;
|
|
135
|
+
transition: number;
|
|
136
|
+
completion: EngineCompletion;
|
|
137
|
+
status: 'succeeded' | 'failed' | 'blocked' | 'interrupted';
|
|
138
|
+
error?: {
|
|
139
|
+
code: string;
|
|
140
|
+
message: string;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export interface CoreDefinitionState {
|
|
144
|
+
$outputs: Record<string, JsonValue>;
|
|
145
|
+
$vars: Record<string, JsonValue>;
|
|
146
|
+
$history: HistoryEntry[];
|
|
147
|
+
$sessions: Record<string, {
|
|
148
|
+
sessionId: string;
|
|
149
|
+
identity: string;
|
|
150
|
+
}>;
|
|
151
|
+
$usage: EngineUsage;
|
|
152
|
+
$attempts: Record<string, number>;
|
|
153
|
+
$consecutiveFailures: {
|
|
154
|
+
revision: number;
|
|
155
|
+
count: number;
|
|
156
|
+
};
|
|
157
|
+
$candidate: CandidateState | null;
|
|
158
|
+
$verified: VerifiedState | null;
|
|
159
|
+
$answers: EngineAnswer[];
|
|
160
|
+
$branches: Record<string, BranchState>;
|
|
161
|
+
$maps: Record<string, MapPlan>;
|
|
162
|
+
$transitions: number;
|
|
163
|
+
$lastOutcome: Record<string, string>;
|
|
164
|
+
$item: {
|
|
165
|
+
index: number;
|
|
166
|
+
value: JsonValue;
|
|
167
|
+
} | null;
|
|
168
|
+
$scope: ExecutionScope;
|
|
169
|
+
$exit: ComponentExit | null;
|
|
170
|
+
$commit?: TerminalCommit;
|
|
171
|
+
}
|
|
172
|
+
/** Domain pieces propose results; only the execution adapter can settle them. */
|
|
173
|
+
export interface PieceResult {
|
|
174
|
+
/** Native child-graph update, committed with its terminal marker; never a public output field. */
|
|
175
|
+
childUpdate?: JsonObject;
|
|
176
|
+
outcome: string;
|
|
177
|
+
status?: 'succeeded' | 'failed' | 'blocked' | 'interrupted';
|
|
178
|
+
output?: JsonValue;
|
|
179
|
+
history?: HistoryEntry[];
|
|
180
|
+
vars?: Record<string, JsonValue>;
|
|
181
|
+
session?: {
|
|
182
|
+
sessionId: string;
|
|
183
|
+
identity: string;
|
|
184
|
+
};
|
|
185
|
+
answers?: EngineAnswer[];
|
|
186
|
+
branches?: Record<string, BranchState>;
|
|
187
|
+
usage?: EngineUsage;
|
|
188
|
+
candidate?: CandidateState;
|
|
189
|
+
verified?: VerifiedState | null;
|
|
190
|
+
receipt?: ReceiptEvidence;
|
|
191
|
+
completion?: EngineCompletion;
|
|
192
|
+
/** Compiler-owned: a local component completion must never settle the parent run. */
|
|
193
|
+
completesRun?: boolean;
|
|
194
|
+
error?: {
|
|
195
|
+
code: string;
|
|
196
|
+
message: string;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** This engine-owned channel is persisted with the matching task's pending writes. */
|
|
200
|
+
export interface TerminalCommit {
|
|
201
|
+
schemaVersion: 1;
|
|
202
|
+
frame: AttemptFrame;
|
|
203
|
+
result: PieceResult;
|
|
204
|
+
digest: string;
|
|
205
|
+
}
|
|
206
|
+
export interface TransientEngineEvent {
|
|
207
|
+
type: 'agent-event' | 'verification-output' | 'span' | 'runtime-efficiency-event';
|
|
208
|
+
payload: JsonValue;
|
|
209
|
+
}
|
|
210
|
+
export interface HumanInterrupt {
|
|
211
|
+
kind: 'approval' | 'question' | 'gate';
|
|
212
|
+
prompt: string;
|
|
213
|
+
nodePath: string;
|
|
214
|
+
scopeId: string;
|
|
215
|
+
attemptId: string;
|
|
216
|
+
}
|
|
217
|
+
export interface PieceExecutionContext {
|
|
218
|
+
state: CoreDefinitionState;
|
|
219
|
+
frame: AttemptFrame;
|
|
220
|
+
signal: AbortSignal;
|
|
221
|
+
progress(event: TransientEngineEvent): void;
|
|
222
|
+
interrupt(request: HumanInterrupt): JsonValue;
|
|
223
|
+
}
|
|
224
|
+
export interface PieceDescriptor {
|
|
225
|
+
kind: string;
|
|
226
|
+
paramsSchema: JsonObject;
|
|
227
|
+
outcomes: readonly string[];
|
|
228
|
+
effect: EngineEffect | 'derived';
|
|
229
|
+
requiresAI: boolean;
|
|
230
|
+
storeAccess?: 'none' | 'read' | 'write';
|
|
231
|
+
}
|
|
232
|
+
export interface Piece {
|
|
233
|
+
descriptor: PieceDescriptor;
|
|
234
|
+
/** Exact labels can depend on sentinel mode, structured role output or component parameters. */
|
|
235
|
+
getOutcomes?(params: JsonObject): readonly string[];
|
|
236
|
+
getEffect?(params: JsonObject, roles: Readonly<Record<string, {
|
|
237
|
+
access: EngineEffect;
|
|
238
|
+
}>>): EngineEffect;
|
|
239
|
+
execute(params: JsonObject, context: PieceExecutionContext): Promise<PieceResult>;
|
|
240
|
+
}
|
|
241
|
+
/** Runtime coordination port; SQL, provider processes and locks stay out of compilation. */
|
|
242
|
+
export interface NodeExecutionPort {
|
|
243
|
+
enter(input: NodeAdmission): Promise<AttemptFrame>;
|
|
244
|
+
execute(frame: AttemptFrame, effect: EngineEffect, operation: (signal: AbortSignal) => Promise<PieceResult>): Promise<PieceResult>;
|
|
245
|
+
terminal(frame: AttemptFrame, result: PieceResult): TerminalCommit;
|
|
246
|
+
interrupted(frame: AttemptFrame, error: unknown): Promise<void>;
|
|
247
|
+
/** Only an approved retry settles here; final failure stays running until its marker commits. */
|
|
248
|
+
failed(frame: AttemptFrame, error: unknown, options: {
|
|
249
|
+
retry: boolean;
|
|
250
|
+
}): Promise<{
|
|
251
|
+
retryable: boolean;
|
|
252
|
+
}>;
|
|
253
|
+
progress(event: TransientEngineEvent): void;
|
|
254
|
+
}
|
|
255
|
+
export interface DurableEngineEvent {
|
|
256
|
+
sequence: number;
|
|
257
|
+
runId: string;
|
|
258
|
+
type: string;
|
|
259
|
+
timestamp: string;
|
|
260
|
+
nodePath?: string;
|
|
261
|
+
scopeId?: string;
|
|
262
|
+
branchId?: string;
|
|
263
|
+
visit?: number;
|
|
264
|
+
attempt?: number;
|
|
265
|
+
attemptId?: string;
|
|
266
|
+
payload: JsonValue;
|
|
267
|
+
}
|
|
268
|
+
/** Shared typed failure without leaking SQLite or LangGraph error objects into JSONL. */
|
|
269
|
+
export declare class EngineError extends Error {
|
|
270
|
+
readonly code: string;
|
|
271
|
+
readonly details?: JsonValue | undefined;
|
|
272
|
+
constructor(code: string, message: string, details?: JsonValue | undefined);
|
|
273
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Shared typed failure without leaking SQLite or LangGraph error objects into JSONL. */
|
|
2
|
+
export class EngineError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
details;
|
|
5
|
+
constructor(code, message, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.details = details;
|
|
9
|
+
this.name = 'EngineError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/** Public JSON schema; parity is checked against the packaged schema artifact. */
|
|
2
|
+
export declare const workflowDefinitionSchema: {
|
|
3
|
+
readonly $schema: "https://json-schema.org/draft/2020-12/schema";
|
|
4
|
+
readonly $id: "https://specrails.dev/schemas/workflow-definition/1";
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly additionalProperties: false;
|
|
7
|
+
readonly required: readonly ["schemaVersion", "id", "version", "title", "journal", "change", "entry", "maxTransitions", "roles", "nodes"];
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly schemaVersion: {
|
|
10
|
+
readonly const: 1;
|
|
11
|
+
};
|
|
12
|
+
readonly id: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly pattern: "^[a-z0-9][a-z0-9-]{0,63}$";
|
|
15
|
+
};
|
|
16
|
+
readonly version: {
|
|
17
|
+
readonly type: "string";
|
|
18
|
+
readonly pattern: "^[0-9a-f]{64}$";
|
|
19
|
+
};
|
|
20
|
+
readonly title: {
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
readonly minLength: 1;
|
|
23
|
+
readonly maxLength: 120;
|
|
24
|
+
};
|
|
25
|
+
readonly journal: {
|
|
26
|
+
readonly enum: readonly ["ledger-only", "implementation"];
|
|
27
|
+
};
|
|
28
|
+
readonly change: {
|
|
29
|
+
readonly enum: readonly ["new", "existing", "none"];
|
|
30
|
+
};
|
|
31
|
+
readonly entry: {
|
|
32
|
+
readonly $ref: "#/$defs/nodeId";
|
|
33
|
+
};
|
|
34
|
+
readonly maxTransitions: {
|
|
35
|
+
readonly type: "integer";
|
|
36
|
+
readonly minimum: 1;
|
|
37
|
+
readonly maximum: 10000;
|
|
38
|
+
};
|
|
39
|
+
readonly budget: {
|
|
40
|
+
readonly type: "object";
|
|
41
|
+
readonly additionalProperties: false;
|
|
42
|
+
readonly properties: {
|
|
43
|
+
readonly maxCostUsd: {
|
|
44
|
+
readonly type: "number";
|
|
45
|
+
readonly exclusiveMinimum: 0;
|
|
46
|
+
};
|
|
47
|
+
readonly maxTokens: {
|
|
48
|
+
readonly type: "integer";
|
|
49
|
+
readonly minimum: 1;
|
|
50
|
+
};
|
|
51
|
+
readonly maxDurationMs: {
|
|
52
|
+
readonly type: "integer";
|
|
53
|
+
readonly minimum: 1000;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
readonly policies: {
|
|
58
|
+
readonly type: "object";
|
|
59
|
+
readonly additionalProperties: false;
|
|
60
|
+
readonly properties: {
|
|
61
|
+
readonly failFast: {
|
|
62
|
+
readonly type: "integer";
|
|
63
|
+
readonly minimum: 1;
|
|
64
|
+
readonly maximum: 10;
|
|
65
|
+
readonly default: 2;
|
|
66
|
+
};
|
|
67
|
+
readonly noProgress: {
|
|
68
|
+
readonly type: "integer";
|
|
69
|
+
readonly minimum: 1;
|
|
70
|
+
readonly maximum: 10;
|
|
71
|
+
readonly default: 2;
|
|
72
|
+
};
|
|
73
|
+
readonly historyMaxChars: {
|
|
74
|
+
readonly type: "integer";
|
|
75
|
+
readonly minimum: 200;
|
|
76
|
+
readonly maximum: 20000;
|
|
77
|
+
readonly default: 1500;
|
|
78
|
+
};
|
|
79
|
+
readonly concurrency: {
|
|
80
|
+
readonly type: "integer";
|
|
81
|
+
readonly minimum: 1;
|
|
82
|
+
readonly maximum: 8;
|
|
83
|
+
readonly default: 1;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
readonly roles: {
|
|
88
|
+
readonly type: "array";
|
|
89
|
+
readonly items: {
|
|
90
|
+
readonly $ref: "#/$defs/roleId";
|
|
91
|
+
};
|
|
92
|
+
readonly uniqueItems: true;
|
|
93
|
+
};
|
|
94
|
+
readonly nodes: {
|
|
95
|
+
readonly type: "object";
|
|
96
|
+
readonly minProperties: 1;
|
|
97
|
+
readonly propertyNames: {
|
|
98
|
+
readonly $ref: "#/$defs/nodeId";
|
|
99
|
+
};
|
|
100
|
+
readonly additionalProperties: {
|
|
101
|
+
readonly $ref: "#/$defs/node";
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
readonly components: {
|
|
105
|
+
readonly type: "object";
|
|
106
|
+
readonly propertyNames: {
|
|
107
|
+
readonly pattern: "^[a-z0-9][a-z0-9-]{0,63}$";
|
|
108
|
+
};
|
|
109
|
+
readonly additionalProperties: {
|
|
110
|
+
readonly $ref: "#/$defs/componentBody";
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
readonly delivery: {
|
|
114
|
+
readonly type: "object";
|
|
115
|
+
readonly additionalProperties: false;
|
|
116
|
+
readonly properties: {
|
|
117
|
+
readonly requiresVerified: {
|
|
118
|
+
readonly type: "boolean";
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
readonly $defs: {
|
|
124
|
+
readonly nodeId: {
|
|
125
|
+
readonly type: "string";
|
|
126
|
+
readonly pattern: "^[A-Za-z0-9][A-Za-z0-9_-]{0,119}$";
|
|
127
|
+
readonly not: {
|
|
128
|
+
readonly enum: readonly ["START", "END", "__start__", "__end__", "next"];
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
readonly roleId: {
|
|
132
|
+
readonly type: "string";
|
|
133
|
+
readonly pattern: "^[a-z][a-z0-9-]{0,63}$";
|
|
134
|
+
};
|
|
135
|
+
readonly engine: {
|
|
136
|
+
readonly type: "object";
|
|
137
|
+
readonly additionalProperties: false;
|
|
138
|
+
readonly required: readonly ["provider"];
|
|
139
|
+
readonly properties: {
|
|
140
|
+
readonly provider: {
|
|
141
|
+
readonly type: "string";
|
|
142
|
+
};
|
|
143
|
+
readonly model: {
|
|
144
|
+
readonly type: "string";
|
|
145
|
+
};
|
|
146
|
+
readonly effort: {
|
|
147
|
+
readonly type: "string";
|
|
148
|
+
};
|
|
149
|
+
readonly thinking: {
|
|
150
|
+
readonly enum: readonly ["on", "off"];
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
readonly retry: {
|
|
155
|
+
readonly type: "object";
|
|
156
|
+
readonly additionalProperties: false;
|
|
157
|
+
readonly properties: {
|
|
158
|
+
readonly maxAttempts: {
|
|
159
|
+
readonly type: "integer";
|
|
160
|
+
readonly minimum: 1;
|
|
161
|
+
readonly maximum: 10;
|
|
162
|
+
};
|
|
163
|
+
readonly backoffMs: {
|
|
164
|
+
readonly type: "integer";
|
|
165
|
+
readonly minimum: 0;
|
|
166
|
+
readonly maximum: 600000;
|
|
167
|
+
};
|
|
168
|
+
readonly retryOn: {
|
|
169
|
+
readonly type: "array";
|
|
170
|
+
readonly items: {
|
|
171
|
+
readonly enum: readonly ["idle_timeout", "timeout", "provider_request_error", "session_not_found", "invalid_structured_output"];
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
readonly ends: {
|
|
177
|
+
readonly type: "object";
|
|
178
|
+
readonly propertyNames: {
|
|
179
|
+
readonly pattern: "^[a-z][a-z0-9-]{0,31}$";
|
|
180
|
+
};
|
|
181
|
+
readonly additionalProperties: {
|
|
182
|
+
readonly oneOf: readonly [{
|
|
183
|
+
readonly $ref: "#/$defs/nodeId";
|
|
184
|
+
}, {
|
|
185
|
+
readonly type: "null";
|
|
186
|
+
}];
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
readonly node: {
|
|
190
|
+
readonly type: "object";
|
|
191
|
+
readonly additionalProperties: false;
|
|
192
|
+
readonly required: readonly ["kind", "params", "ends"];
|
|
193
|
+
readonly properties: {
|
|
194
|
+
readonly kind: {
|
|
195
|
+
readonly enum: readonly ["prompt", "role-turn", "decider", "condition", "assign", "verify", "shell", "openspec-validate", "openspec-archive", "approval", "question", "gate", "map", "join", "component", "implementation", "end"];
|
|
196
|
+
};
|
|
197
|
+
readonly params: {
|
|
198
|
+
readonly type: "object";
|
|
199
|
+
};
|
|
200
|
+
readonly ends: {
|
|
201
|
+
readonly $ref: "#/$defs/ends";
|
|
202
|
+
};
|
|
203
|
+
readonly retry: {
|
|
204
|
+
readonly $ref: "#/$defs/retry";
|
|
205
|
+
};
|
|
206
|
+
readonly label: {
|
|
207
|
+
readonly type: "string";
|
|
208
|
+
readonly maxLength: 80;
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
readonly componentBody: {
|
|
213
|
+
readonly type: "object";
|
|
214
|
+
readonly additionalProperties: false;
|
|
215
|
+
readonly required: readonly ["entry", "nodes"];
|
|
216
|
+
readonly properties: {
|
|
217
|
+
readonly entry: {
|
|
218
|
+
readonly $ref: "#/$defs/nodeId";
|
|
219
|
+
};
|
|
220
|
+
readonly maxTransitions: {
|
|
221
|
+
readonly type: "integer";
|
|
222
|
+
readonly minimum: 1;
|
|
223
|
+
readonly maximum: 10000;
|
|
224
|
+
};
|
|
225
|
+
readonly inputs: {
|
|
226
|
+
readonly type: "array";
|
|
227
|
+
readonly items: {
|
|
228
|
+
readonly type: "string";
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
readonly outputs: {
|
|
232
|
+
readonly type: "array";
|
|
233
|
+
readonly items: {
|
|
234
|
+
readonly type: "string";
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
readonly nodes: {
|
|
238
|
+
readonly type: "object";
|
|
239
|
+
readonly minProperties: 1;
|
|
240
|
+
readonly propertyNames: {
|
|
241
|
+
readonly $ref: "#/$defs/nodeId";
|
|
242
|
+
};
|
|
243
|
+
readonly additionalProperties: {
|
|
244
|
+
readonly $ref: "#/$defs/node";
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
};
|
|
250
|
+
};
|