@devflow-tools/database 0.17.2 → 0.17.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/__tests__/database.retrieval-ledger.test.ts +15 -0
- package/__tests__/database.semantic-resolution.test.ts +87 -0
- package/__tests__/database.task-runtime.test.ts +73 -0
- package/__tests__/database.work-queue.test.ts +34 -0
- package/dist/database.d.ts +39 -0
- package/dist/database.js +395 -12
- package/dist/index.d.ts +5 -1
- package/dist/index.js +10 -1
- package/dist/retrieval-ledger.d.ts +8 -1
- package/dist/semantic-resolution.d.ts +30 -0
- package/dist/semantic-resolution.js +156 -0
- package/dist/task-runtime.d.ts +64 -0
- package/dist/task-runtime.js +106 -0
- package/dist/work-queue.d.ts +18 -2
- package/package.json +2 -2
- package/src/database.ts +423 -9
- package/src/index.ts +27 -0
- package/src/retrieval-ledger.ts +9 -2
- package/src/semantic-resolution.ts +181 -0
- package/src/task-runtime.ts +169 -0
- package/src/work-queue.ts +20 -1
- package/tsconfig.tsbuildinfo +1 -0
package/src/database.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
WorkItemRecord,
|
|
13
13
|
WorkQueueHealth,
|
|
14
14
|
WorkState,
|
|
15
|
+
ProjectMutationLeaseRecord,
|
|
15
16
|
} from './work-queue';
|
|
16
17
|
import {
|
|
17
18
|
mapSessionObligationRow,
|
|
@@ -84,6 +85,19 @@ import {
|
|
|
84
85
|
type ToolNameResolutionRecord,
|
|
85
86
|
type TranscriptCheckpointRecord,
|
|
86
87
|
} from './task-semantic-control';
|
|
88
|
+
import {
|
|
89
|
+
mapTaskRuntimeEventRow,
|
|
90
|
+
mapTaskRuntimeSnapshotRow,
|
|
91
|
+
stableTaskRuntimeJson,
|
|
92
|
+
type TaskRuntimeEventRecord,
|
|
93
|
+
type TaskRuntimeSnapshotRecord,
|
|
94
|
+
} from './task-runtime';
|
|
95
|
+
import {
|
|
96
|
+
assertSemanticResolutionRecord,
|
|
97
|
+
mapSemanticResolutionRow,
|
|
98
|
+
stableSemanticResolutionJson,
|
|
99
|
+
type SemanticResolutionRecord,
|
|
100
|
+
} from './semantic-resolution';
|
|
87
101
|
|
|
88
102
|
export interface BenchmarkReportRecord {
|
|
89
103
|
runId: string;
|
|
@@ -612,6 +626,9 @@ export class DevFlowDatabase {
|
|
|
612
626
|
source_id TEXT NOT NULL, stage TEXT NOT NULL, rank INTEGER, raw_score REAL,
|
|
613
627
|
normalized_score REAL, final_score REAL, applicability TEXT NOT NULL DEFAULT '[]',
|
|
614
628
|
reason TEXT, tool_evidence TEXT NOT NULL DEFAULT '[]', verification_receipt TEXT,
|
|
629
|
+
schema_version TEXT NOT NULL DEFAULT 'retrieval-ledger-event.v1', task_spec_hash TEXT,
|
|
630
|
+
actor TEXT, source_version TEXT, source_content_hash TEXT,
|
|
631
|
+
evidence_ids TEXT NOT NULL DEFAULT '[]', reason_code TEXT,
|
|
615
632
|
payload TEXT NOT NULL DEFAULT '{}', created_at INTEGER NOT NULL
|
|
616
633
|
);
|
|
617
634
|
CREATE INDEX IF NOT EXISTS idx_retrieval_ledger_identity ON devflow_retrieval_ledger(
|
|
@@ -651,6 +668,35 @@ export class DevFlowDatabase {
|
|
|
651
668
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_intent_source
|
|
652
669
|
ON devflow_task_intent_artifacts(project_root, session_id, source_hash, version);
|
|
653
670
|
|
|
671
|
+
CREATE TABLE IF NOT EXISTS devflow_semantic_resolutions (
|
|
672
|
+
frame_hash TEXT PRIMARY KEY,
|
|
673
|
+
project_root TEXT NOT NULL,
|
|
674
|
+
project_id TEXT NOT NULL,
|
|
675
|
+
host_id TEXT NOT NULL,
|
|
676
|
+
session_id TEXT NOT NULL,
|
|
677
|
+
turn_id TEXT NOT NULL,
|
|
678
|
+
request_id TEXT NOT NULL,
|
|
679
|
+
source_hash TEXT NOT NULL,
|
|
680
|
+
artifact_hash TEXT NOT NULL,
|
|
681
|
+
artifact_revision INTEGER NOT NULL CHECK(artifact_revision > 0),
|
|
682
|
+
supersedes_frame_hash TEXT,
|
|
683
|
+
state TEXT NOT NULL CHECK(state IN ('provisional', 'resolved', 'abstained', 'unavailable')),
|
|
684
|
+
generated_by TEXT NOT NULL CHECK(generated_by IN ('deterministic', 'embedding_router', 'host_semantic', 'hybrid')),
|
|
685
|
+
model_id TEXT,
|
|
686
|
+
model_revision TEXT,
|
|
687
|
+
route_catalog_version TEXT NOT NULL,
|
|
688
|
+
threshold_version TEXT NOT NULL,
|
|
689
|
+
route_json TEXT NOT NULL,
|
|
690
|
+
sampling_json TEXT NOT NULL,
|
|
691
|
+
conflicts_json TEXT NOT NULL,
|
|
692
|
+
frame_json TEXT NOT NULL,
|
|
693
|
+
duration_ms INTEGER NOT NULL CHECK(duration_ms >= 0),
|
|
694
|
+
created_at INTEGER NOT NULL,
|
|
695
|
+
UNIQUE(project_root, session_id, turn_id, artifact_revision)
|
|
696
|
+
);
|
|
697
|
+
CREATE INDEX IF NOT EXISTS idx_semantic_resolution_latest
|
|
698
|
+
ON devflow_semantic_resolutions(project_root, session_id, turn_id, artifact_revision DESC);
|
|
699
|
+
|
|
654
700
|
CREATE TABLE IF NOT EXISTS devflow_channel_query_plans (
|
|
655
701
|
plan_hash TEXT PRIMARY KEY,
|
|
656
702
|
source_intent_hash TEXT NOT NULL,
|
|
@@ -716,6 +762,40 @@ export class DevFlowDatabase {
|
|
|
716
762
|
CREATE INDEX IF NOT EXISTS idx_terminal_transition_turn
|
|
717
763
|
ON devflow_terminal_transitions(project_root, session_id, turn_id, sequence);
|
|
718
764
|
|
|
765
|
+
CREATE TABLE IF NOT EXISTS devflow_task_runtime_events (
|
|
766
|
+
event_id TEXT PRIMARY KEY,
|
|
767
|
+
schema_version TEXT NOT NULL,
|
|
768
|
+
producer TEXT NOT NULL,
|
|
769
|
+
producer_version TEXT NOT NULL,
|
|
770
|
+
project_root TEXT NOT NULL,
|
|
771
|
+
project_id TEXT NOT NULL,
|
|
772
|
+
host_id TEXT NOT NULL,
|
|
773
|
+
session_id TEXT NOT NULL,
|
|
774
|
+
turn_id TEXT NOT NULL,
|
|
775
|
+
request_id TEXT NOT NULL,
|
|
776
|
+
execution_id TEXT,
|
|
777
|
+
task_spec_hash TEXT NOT NULL,
|
|
778
|
+
sequence INTEGER NOT NULL CHECK(sequence > 0),
|
|
779
|
+
kind TEXT NOT NULL,
|
|
780
|
+
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
781
|
+
created_at INTEGER NOT NULL,
|
|
782
|
+
UNIQUE(project_root, session_id, turn_id, sequence)
|
|
783
|
+
);
|
|
784
|
+
CREATE INDEX IF NOT EXISTS idx_task_runtime_event_identity
|
|
785
|
+
ON devflow_task_runtime_events(project_root, session_id, turn_id, sequence);
|
|
786
|
+
|
|
787
|
+
CREATE TABLE IF NOT EXISTS devflow_task_runtime_snapshots (
|
|
788
|
+
project_root TEXT NOT NULL,
|
|
789
|
+
session_id TEXT NOT NULL,
|
|
790
|
+
turn_id TEXT NOT NULL,
|
|
791
|
+
last_event_sequence INTEGER NOT NULL,
|
|
792
|
+
schema_version TEXT NOT NULL,
|
|
793
|
+
snapshot_json TEXT NOT NULL,
|
|
794
|
+
snapshot_hash TEXT NOT NULL,
|
|
795
|
+
updated_at INTEGER NOT NULL,
|
|
796
|
+
PRIMARY KEY(project_root, session_id, turn_id)
|
|
797
|
+
);
|
|
798
|
+
|
|
719
799
|
CREATE TABLE IF NOT EXISTS devflow_transcript_checkpoints (
|
|
720
800
|
id TEXT PRIMARY KEY,
|
|
721
801
|
project_root TEXT NOT NULL,
|
|
@@ -869,9 +949,11 @@ export class DevFlowDatabase {
|
|
|
869
949
|
project_root TEXT NOT NULL,
|
|
870
950
|
session_id TEXT,
|
|
871
951
|
turn_id TEXT,
|
|
952
|
+
source_hash TEXT,
|
|
953
|
+
task_spec_hash TEXT,
|
|
872
954
|
payload TEXT NOT NULL,
|
|
873
955
|
state TEXT NOT NULL DEFAULT 'pending'
|
|
874
|
-
CHECK(state IN ('pending', 'leased', 'completed', 'failed', 'dead_letter')),
|
|
956
|
+
CHECK(state IN ('pending', 'leased', 'completed', 'failed', 'dead_letter', 'cancelled')),
|
|
875
957
|
attempts INTEGER NOT NULL DEFAULT 0 CHECK(attempts >= 0),
|
|
876
958
|
max_attempts INTEGER NOT NULL DEFAULT 5 CHECK(max_attempts > 0),
|
|
877
959
|
lease_owner TEXT,
|
|
@@ -881,7 +963,11 @@ export class DevFlowDatabase {
|
|
|
881
963
|
error_message TEXT,
|
|
882
964
|
created_at INTEGER NOT NULL,
|
|
883
965
|
updated_at INTEGER NOT NULL,
|
|
884
|
-
completed_at INTEGER
|
|
966
|
+
completed_at INTEGER,
|
|
967
|
+
cancelled_at INTEGER,
|
|
968
|
+
cancellation_reason TEXT,
|
|
969
|
+
replay_of_id TEXT,
|
|
970
|
+
replay_count INTEGER NOT NULL DEFAULT 0
|
|
885
971
|
);
|
|
886
972
|
|
|
887
973
|
CREATE INDEX IF NOT EXISTS idx_work_items_ready
|
|
@@ -891,6 +977,16 @@ export class DevFlowDatabase {
|
|
|
891
977
|
CREATE INDEX IF NOT EXISTS idx_work_items_completed
|
|
892
978
|
ON devflow_work_items(project_root, completed_at DESC);
|
|
893
979
|
|
|
980
|
+
CREATE TABLE IF NOT EXISTS devflow_project_mutation_leases (
|
|
981
|
+
project_root TEXT NOT NULL,
|
|
982
|
+
mutation_kind TEXT NOT NULL,
|
|
983
|
+
owner TEXT NOT NULL,
|
|
984
|
+
lease_expires_at INTEGER NOT NULL,
|
|
985
|
+
source_hash TEXT,
|
|
986
|
+
updated_at INTEGER NOT NULL,
|
|
987
|
+
PRIMARY KEY(project_root, mutation_kind)
|
|
988
|
+
);
|
|
989
|
+
|
|
894
990
|
CREATE TABLE IF NOT EXISTS devflow_session_closures (
|
|
895
991
|
session_id TEXT NOT NULL,
|
|
896
992
|
project_root TEXT NOT NULL,
|
|
@@ -1162,6 +1258,19 @@ export class DevFlowDatabase {
|
|
|
1162
1258
|
try { this.db.exec('ALTER TABLE devflow_context_receipts ADD COLUMN action_satisfied_at INTEGER'); } catch {}
|
|
1163
1259
|
try { this.db.exec('ALTER TABLE devflow_context_receipts ADD COLUMN action_degradation_json TEXT'); } catch {}
|
|
1164
1260
|
try { this.db.exec('ALTER TABLE devflow_context_receipts ADD COLUMN request_id TEXT'); } catch {}
|
|
1261
|
+
try { this.db.exec("ALTER TABLE devflow_retrieval_ledger ADD COLUMN schema_version TEXT NOT NULL DEFAULT 'retrieval-ledger-event.v1'"); } catch {}
|
|
1262
|
+
try { this.db.exec('ALTER TABLE devflow_retrieval_ledger ADD COLUMN task_spec_hash TEXT'); } catch {}
|
|
1263
|
+
try { this.db.exec('ALTER TABLE devflow_retrieval_ledger ADD COLUMN actor TEXT'); } catch {}
|
|
1264
|
+
try { this.db.exec('ALTER TABLE devflow_retrieval_ledger ADD COLUMN source_version TEXT'); } catch {}
|
|
1265
|
+
try { this.db.exec('ALTER TABLE devflow_retrieval_ledger ADD COLUMN source_content_hash TEXT'); } catch {}
|
|
1266
|
+
try { this.db.exec("ALTER TABLE devflow_retrieval_ledger ADD COLUMN evidence_ids TEXT NOT NULL DEFAULT '[]'"); } catch {}
|
|
1267
|
+
try { this.db.exec('ALTER TABLE devflow_retrieval_ledger ADD COLUMN reason_code TEXT'); } catch {}
|
|
1268
|
+
try { this.db.exec('ALTER TABLE devflow_work_items ADD COLUMN source_hash TEXT'); } catch {}
|
|
1269
|
+
try { this.db.exec('ALTER TABLE devflow_work_items ADD COLUMN task_spec_hash TEXT'); } catch {}
|
|
1270
|
+
try { this.db.exec('ALTER TABLE devflow_work_items ADD COLUMN cancelled_at INTEGER'); } catch {}
|
|
1271
|
+
try { this.db.exec('ALTER TABLE devflow_work_items ADD COLUMN cancellation_reason TEXT'); } catch {}
|
|
1272
|
+
try { this.db.exec('ALTER TABLE devflow_work_items ADD COLUMN replay_of_id TEXT'); } catch {}
|
|
1273
|
+
try { this.db.exec('ALTER TABLE devflow_work_items ADD COLUMN replay_count INTEGER NOT NULL DEFAULT 0'); } catch {}
|
|
1165
1274
|
this.db.exec('UPDATE devflow_rules SET updated_at = created_at WHERE updated_at IS NULL');
|
|
1166
1275
|
this.db.exec('CREATE INDEX IF NOT EXISTS idx_devflow_rules_gate ON devflow_rules(gate, enabled)');
|
|
1167
1276
|
|
|
@@ -3010,7 +3119,8 @@ export class DevFlowDatabase {
|
|
|
3010
3119
|
enqueueWork(input: EnqueueWorkInput): WorkItemRecord {
|
|
3011
3120
|
if (!input.idempotencyKey.trim()) throw new Error('Work idempotency key is required');
|
|
3012
3121
|
if (!input.projectRoot.trim()) throw new Error('Work project root is required');
|
|
3013
|
-
const maxAttempts = input.maxAttempts
|
|
3122
|
+
const maxAttempts = input.maxAttempts
|
|
3123
|
+
?? (input.kind === 'knowledge.ingest' || input.kind === 'knowledge.index_refresh' ? 3 : 5);
|
|
3014
3124
|
if (!Number.isSafeInteger(maxAttempts) || maxAttempts <= 0) {
|
|
3015
3125
|
throw new Error('Work maxAttempts must be a positive safe integer');
|
|
3016
3126
|
}
|
|
@@ -3023,10 +3133,10 @@ export class DevFlowDatabase {
|
|
|
3023
3133
|
|
|
3024
3134
|
const row = this.db.prepare(`
|
|
3025
3135
|
INSERT INTO devflow_work_items (
|
|
3026
|
-
id, idempotency_key, kind, project_root, session_id, turn_id, payload,
|
|
3136
|
+
id, idempotency_key, kind, project_root, session_id, turn_id, source_hash, task_spec_hash, payload,
|
|
3027
3137
|
state, attempts, max_attempts, lease_owner, lease_expires_at,
|
|
3028
3138
|
next_attempt_at, error_category, error_message, created_at, updated_at, completed_at
|
|
3029
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', 0, ?, NULL, NULL, ?, NULL, NULL, ?, ?, NULL)
|
|
3139
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', 0, ?, NULL, NULL, ?, NULL, NULL, ?, ?, NULL)
|
|
3030
3140
|
ON CONFLICT(idempotency_key) DO UPDATE SET
|
|
3031
3141
|
state = CASE
|
|
3032
3142
|
WHEN devflow_work_items.state = 'dead_letter'
|
|
@@ -3067,6 +3177,8 @@ export class DevFlowDatabase {
|
|
|
3067
3177
|
input.projectRoot,
|
|
3068
3178
|
input.sessionId ?? null,
|
|
3069
3179
|
input.turnId ?? null,
|
|
3180
|
+
input.sourceHash ?? null,
|
|
3181
|
+
input.taskSpecHash ?? null,
|
|
3070
3182
|
JSON.stringify(input.payload ?? null),
|
|
3071
3183
|
maxAttempts,
|
|
3072
3184
|
nextAttemptAt,
|
|
@@ -3084,6 +3196,53 @@ export class DevFlowDatabase {
|
|
|
3084
3196
|
return row ? this.mapWorkItem(row) : null;
|
|
3085
3197
|
}
|
|
3086
3198
|
|
|
3199
|
+
getWorkById(id: string): WorkItemRecord | null {
|
|
3200
|
+
const row = this.db.prepare('SELECT * FROM devflow_work_items WHERE id = ?').get(id) as any;
|
|
3201
|
+
return row ? this.mapWorkItem(row) : null;
|
|
3202
|
+
}
|
|
3203
|
+
|
|
3204
|
+
acquireProjectMutationLease(input: { projectRoot: string; mutationKind: string; owner: string; leaseMs: number; sourceHash?: string; now?: number }): boolean {
|
|
3205
|
+
const now = input.now ?? Date.now();
|
|
3206
|
+
return this.db.prepare(`
|
|
3207
|
+
INSERT INTO devflow_project_mutation_leases
|
|
3208
|
+
(project_root, mutation_kind, owner, lease_expires_at, source_hash, updated_at)
|
|
3209
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
3210
|
+
ON CONFLICT(project_root, mutation_kind) DO UPDATE SET
|
|
3211
|
+
owner = excluded.owner, lease_expires_at = excluded.lease_expires_at,
|
|
3212
|
+
source_hash = excluded.source_hash, updated_at = excluded.updated_at
|
|
3213
|
+
WHERE devflow_project_mutation_leases.lease_expires_at <= ? OR devflow_project_mutation_leases.owner = excluded.owner
|
|
3214
|
+
`).run(input.projectRoot, input.mutationKind, input.owner, now + input.leaseMs, input.sourceHash ?? null, now, now).changes > 0;
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
releaseProjectMutationLease(projectRoot: string, mutationKind: string, owner: string): boolean {
|
|
3218
|
+
return this.db.prepare('DELETE FROM devflow_project_mutation_leases WHERE project_root = ? AND mutation_kind = ? AND owner = ?')
|
|
3219
|
+
.run(projectRoot, mutationKind, owner).changes > 0;
|
|
3220
|
+
}
|
|
3221
|
+
|
|
3222
|
+
cancelStaleWork(input: { id: string; owner: string; sourceHash?: string; taskSpecHash?: string; reason?: string; now?: number }): boolean {
|
|
3223
|
+
const current = this.getWorkById(input.id);
|
|
3224
|
+
const stale = current && current.state === 'leased' && current.leaseOwner === input.owner
|
|
3225
|
+
&& ((input.sourceHash !== undefined && current.sourceHash !== input.sourceHash)
|
|
3226
|
+
|| (input.taskSpecHash !== undefined && current.taskSpecHash !== input.taskSpecHash));
|
|
3227
|
+
if (!stale) return false;
|
|
3228
|
+
const now = input.now ?? Date.now();
|
|
3229
|
+
try {
|
|
3230
|
+
return this.db.prepare(`UPDATE devflow_work_items SET state = 'cancelled', lease_owner = NULL, lease_expires_at = NULL, cancelled_at = ?, cancellation_reason = ?, updated_at = ? WHERE id = ? AND state = 'leased' AND lease_owner = ?`)
|
|
3231
|
+
.run(now, input.reason ?? 'stale_source_or_task_spec', now, input.id, input.owner).changes === 1;
|
|
3232
|
+
} catch {
|
|
3233
|
+
return this.db.prepare(`UPDATE devflow_work_items SET state = 'completed', lease_owner = NULL, lease_expires_at = NULL, cancelled_at = ?, cancellation_reason = ?, updated_at = ? WHERE id = ? AND state = 'leased' AND lease_owner = ?`)
|
|
3234
|
+
.run(now, input.reason ?? 'stale_source_or_task_spec', now, input.id, input.owner).changes === 1;
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
|
|
3238
|
+
replayDeadLetterWork(id: string, input: { idempotencyKey: string; sourceHash?: string; taskSpecHash?: string; now?: number }): WorkItemRecord | null {
|
|
3239
|
+
const original = this.getWorkById(id);
|
|
3240
|
+
if (!original || original.state !== 'dead_letter') return null;
|
|
3241
|
+
const replay = this.enqueueWork({ idempotencyKey: input.idempotencyKey, kind: original.kind, projectRoot: original.projectRoot, sessionId: original.sessionId, turnId: original.turnId, payload: original.payload, sourceHash: input.sourceHash ?? original.sourceHash, taskSpecHash: input.taskSpecHash ?? original.taskSpecHash, maxAttempts: original.maxAttempts, nextAttemptAt: input.now ?? Date.now() });
|
|
3242
|
+
this.db.prepare('UPDATE devflow_work_items SET replay_of_id = ?, replay_count = replay_count + 1 WHERE id = ?').run(original.id, replay.id);
|
|
3243
|
+
return this.getWorkById(replay.id);
|
|
3244
|
+
}
|
|
3245
|
+
|
|
3087
3246
|
requestSessionClosure(input: RequestSessionClosureInput): SessionClosureRecord {
|
|
3088
3247
|
if (!input.sessionId.trim()) throw new Error('Session closure requires a session ID');
|
|
3089
3248
|
if (!input.projectRoot.trim()) throw new Error('Session closure requires a project root');
|
|
@@ -3387,8 +3546,10 @@ export class DevFlowDatabase {
|
|
|
3387
3546
|
projectRoot: row.project_root,
|
|
3388
3547
|
sessionId: row.session_id ?? undefined,
|
|
3389
3548
|
turnId: row.turn_id ?? undefined,
|
|
3549
|
+
sourceHash: row.source_hash ?? undefined,
|
|
3550
|
+
taskSpecHash: row.task_spec_hash ?? undefined,
|
|
3390
3551
|
payload: parseJson(row.payload),
|
|
3391
|
-
state: row.state,
|
|
3552
|
+
state: row.cancelled_at != null ? 'cancelled' : row.state,
|
|
3392
3553
|
attempts: Number(row.attempts),
|
|
3393
3554
|
maxAttempts: Number(row.max_attempts),
|
|
3394
3555
|
leaseOwner: row.lease_owner ?? undefined,
|
|
@@ -3399,6 +3560,10 @@ export class DevFlowDatabase {
|
|
|
3399
3560
|
createdAt: Number(row.created_at),
|
|
3400
3561
|
updatedAt: Number(row.updated_at),
|
|
3401
3562
|
completedAt: row.completed_at == null ? undefined : Number(row.completed_at),
|
|
3563
|
+
cancelledAt: row.cancelled_at == null ? undefined : Number(row.cancelled_at),
|
|
3564
|
+
cancellationReason: row.cancellation_reason ?? undefined,
|
|
3565
|
+
replayOfId: row.replay_of_id ?? undefined,
|
|
3566
|
+
replayCount: Number(row.replay_count ?? 0),
|
|
3402
3567
|
};
|
|
3403
3568
|
}
|
|
3404
3569
|
|
|
@@ -3810,6 +3975,38 @@ export class DevFlowDatabase {
|
|
|
3810
3975
|
} : null;
|
|
3811
3976
|
}
|
|
3812
3977
|
|
|
3978
|
+
getContextReceiptForRequest(
|
|
3979
|
+
projectRoot: string,
|
|
3980
|
+
sessionId: string,
|
|
3981
|
+
requestId: string,
|
|
3982
|
+
): ContextReceiptRecord | null {
|
|
3983
|
+
const row = this.db.prepare(`
|
|
3984
|
+
SELECT project_root, session_id, execution_id, context_hash, issued_at, expires_at,
|
|
3985
|
+
selected_files, memory_ids, canonical_next_action, canonical_action_json,
|
|
3986
|
+
action_attempts, action_satisfied_at, action_degradation_json, request_id
|
|
3987
|
+
FROM devflow_context_receipts
|
|
3988
|
+
WHERE project_root = ? AND session_id = ? AND request_id = ?
|
|
3989
|
+
ORDER BY issued_at DESC
|
|
3990
|
+
LIMIT 1
|
|
3991
|
+
`).get(projectRoot, sessionId, requestId) as any;
|
|
3992
|
+
return row ? {
|
|
3993
|
+
projectRoot: row.project_root,
|
|
3994
|
+
sessionId: row.session_id,
|
|
3995
|
+
executionId: row.execution_id,
|
|
3996
|
+
contextHash: row.context_hash,
|
|
3997
|
+
issuedAt: row.issued_at,
|
|
3998
|
+
expiresAt: row.expires_at,
|
|
3999
|
+
selectedFiles: parseJsonStringArray(row.selected_files),
|
|
4000
|
+
memoryIds: parseJsonStringArray(row.memory_ids),
|
|
4001
|
+
canonicalNextAction: row.canonical_next_action ?? undefined,
|
|
4002
|
+
canonicalAction: parseJsonObject(row.canonical_action_json),
|
|
4003
|
+
actionAttempts: parseJsonArray(row.action_attempts),
|
|
4004
|
+
actionSatisfiedAt: row.action_satisfied_at ?? undefined,
|
|
4005
|
+
actionDegradation: parseJsonObject(row.action_degradation_json),
|
|
4006
|
+
requestId: row.request_id ?? undefined,
|
|
4007
|
+
} : null;
|
|
4008
|
+
}
|
|
4009
|
+
|
|
3813
4010
|
recordContextSelectionEvent(event: ContextSelectionEventRecord): boolean {
|
|
3814
4011
|
return this.db.prepare(`
|
|
3815
4012
|
INSERT OR IGNORE INTO devflow_context_selection_events
|
|
@@ -3842,7 +4039,8 @@ export class DevFlowDatabase {
|
|
|
3842
4039
|
id, project_root, session_id, execution_id, turn_id, request_id, context_receipt,
|
|
3843
4040
|
source_type, source_id, stage, rank, raw_score, normalized_score, final_score,
|
|
3844
4041
|
applicability, reason, tool_evidence, verification_receipt, payload, created_at
|
|
3845
|
-
|
|
4042
|
+
, schema_version, task_spec_hash, actor, source_version, source_content_hash, evidence_ids, reason_code
|
|
4043
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3846
4044
|
`).run(
|
|
3847
4045
|
event.id, event.projectRoot, event.sessionId, event.executionId ?? null, event.turnId ?? null,
|
|
3848
4046
|
event.requestId, event.contextReceipt, event.sourceType, event.sourceId, event.stage,
|
|
@@ -3850,6 +4048,9 @@ export class DevFlowDatabase {
|
|
|
3850
4048
|
event.finalScore ?? null, JSON.stringify(event.applicability), event.reason ?? null,
|
|
3851
4049
|
JSON.stringify(event.toolEvidence), event.verificationReceipt ?? null,
|
|
3852
4050
|
JSON.stringify(event.payload), event.createdAt,
|
|
4051
|
+
event.schemaVersion ?? 'retrieval-ledger-event.v1', event.taskSpecHash ?? null,
|
|
4052
|
+
event.actor ?? null, event.sourceVersion ?? null, event.sourceContentHash ?? null,
|
|
4053
|
+
JSON.stringify(event.evidenceIds ?? []), event.reasonCode ?? null,
|
|
3853
4054
|
).changes > 0;
|
|
3854
4055
|
}
|
|
3855
4056
|
|
|
@@ -3940,6 +4141,96 @@ export class DevFlowDatabase {
|
|
|
3940
4141
|
return row ? mapTaskIntentArtifactRow(row) : null;
|
|
3941
4142
|
}
|
|
3942
4143
|
|
|
4144
|
+
appendSemanticResolution(record: SemanticResolutionRecord): boolean {
|
|
4145
|
+
assertSemanticResolutionRecord(record);
|
|
4146
|
+
const existing = this.getSemanticResolution(record.frameHash);
|
|
4147
|
+
if (existing) {
|
|
4148
|
+
if (stableSemanticResolutionJson(existing) !== stableSemanticResolutionJson(record)) {
|
|
4149
|
+
throw new Error(`SEMANTIC_RESOLUTION_HASH_CONFLICT:${record.frameHash}`);
|
|
4150
|
+
}
|
|
4151
|
+
return false;
|
|
4152
|
+
}
|
|
4153
|
+
this.db.exec('BEGIN IMMEDIATE');
|
|
4154
|
+
try {
|
|
4155
|
+
const conflicting = this.db.prepare(`
|
|
4156
|
+
SELECT frame_hash FROM devflow_semantic_resolutions
|
|
4157
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ? AND artifact_revision = ?
|
|
4158
|
+
`).get(
|
|
4159
|
+
record.projectRoot, record.sessionId, record.turnId, record.artifactRevision,
|
|
4160
|
+
) as Record<string, unknown> | undefined;
|
|
4161
|
+
if (conflicting) {
|
|
4162
|
+
throw new Error(`SEMANTIC_RESOLUTION_REVISION_CONFLICT:${record.turnId}:${record.artifactRevision}`);
|
|
4163
|
+
}
|
|
4164
|
+
if (record.supersedesFrameHash) {
|
|
4165
|
+
const superseded = this.getSemanticResolution(record.supersedesFrameHash);
|
|
4166
|
+
if (!superseded) {
|
|
4167
|
+
throw new Error(`SEMANTIC_RESOLUTION_SUPERSEDED_NOT_FOUND:${record.supersedesFrameHash}`);
|
|
4168
|
+
}
|
|
4169
|
+
if (superseded.projectRoot !== record.projectRoot
|
|
4170
|
+
|| superseded.sessionId !== record.sessionId
|
|
4171
|
+
|| superseded.turnId !== record.turnId
|
|
4172
|
+
|| superseded.artifactRevision >= record.artifactRevision) {
|
|
4173
|
+
throw new Error('SEMANTIC_RESOLUTION_SUPERSEDES_INVALID');
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
this.db.prepare(`
|
|
4177
|
+
INSERT INTO devflow_semantic_resolutions (
|
|
4178
|
+
frame_hash, project_root, project_id, host_id, session_id, turn_id, request_id,
|
|
4179
|
+
source_hash, artifact_hash, artifact_revision, supersedes_frame_hash, state,
|
|
4180
|
+
generated_by, model_id, model_revision, route_catalog_version, threshold_version,
|
|
4181
|
+
route_json, sampling_json, conflicts_json, frame_json, duration_ms, created_at
|
|
4182
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
4183
|
+
`).run(
|
|
4184
|
+
record.frameHash, record.projectRoot, record.projectId, record.hostId,
|
|
4185
|
+
record.sessionId, record.turnId, record.requestId, record.sourceHash,
|
|
4186
|
+
record.artifactHash, record.artifactRevision, record.supersedesFrameHash ?? null,
|
|
4187
|
+
record.state, record.generatedBy, record.modelId ?? null, record.modelRevision ?? null,
|
|
4188
|
+
record.routeCatalogVersion, record.thresholdVersion,
|
|
4189
|
+
stableSemanticResolutionJson(record.route), stableSemanticResolutionJson(record.sampling),
|
|
4190
|
+
stableSemanticResolutionJson(record.conflicts), stableSemanticResolutionJson(record.frame),
|
|
4191
|
+
record.durationMs, record.createdAt,
|
|
4192
|
+
);
|
|
4193
|
+
this.db.exec('COMMIT');
|
|
4194
|
+
return true;
|
|
4195
|
+
} catch (error) {
|
|
4196
|
+
try { this.db.exec('ROLLBACK'); } catch {}
|
|
4197
|
+
throw error;
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
|
|
4201
|
+
getSemanticResolution(frameHash: string): SemanticResolutionRecord | null {
|
|
4202
|
+
const row = this.db.prepare(`
|
|
4203
|
+
SELECT * FROM devflow_semantic_resolutions WHERE frame_hash = ?
|
|
4204
|
+
`).get(frameHash) as Record<string, unknown> | undefined;
|
|
4205
|
+
return row ? mapSemanticResolutionRow(row) : null;
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4208
|
+
getLatestSemanticResolution(
|
|
4209
|
+
projectRoot: string,
|
|
4210
|
+
sessionId: string,
|
|
4211
|
+
turnId: string,
|
|
4212
|
+
): SemanticResolutionRecord | null {
|
|
4213
|
+
const row = this.db.prepare(`
|
|
4214
|
+
SELECT * FROM devflow_semantic_resolutions
|
|
4215
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ?
|
|
4216
|
+
ORDER BY artifact_revision DESC, created_at DESC LIMIT 1
|
|
4217
|
+
`).get(projectRoot, sessionId, turnId) as Record<string, unknown> | undefined;
|
|
4218
|
+
return row ? mapSemanticResolutionRow(row) : null;
|
|
4219
|
+
}
|
|
4220
|
+
|
|
4221
|
+
listSemanticResolutions(
|
|
4222
|
+
projectRoot: string,
|
|
4223
|
+
sessionId: string,
|
|
4224
|
+
turnId: string,
|
|
4225
|
+
): SemanticResolutionRecord[] {
|
|
4226
|
+
return (this.db.prepare(`
|
|
4227
|
+
SELECT * FROM devflow_semantic_resolutions
|
|
4228
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ?
|
|
4229
|
+
ORDER BY artifact_revision ASC, created_at ASC
|
|
4230
|
+
`).all(projectRoot, sessionId, turnId) as Array<Record<string, unknown>>)
|
|
4231
|
+
.map(mapSemanticResolutionRow);
|
|
4232
|
+
}
|
|
4233
|
+
|
|
3943
4234
|
listLatestTaskIntentArtifacts(projectRoot: string, sessionId: string): TaskIntentArtifactRecord[] {
|
|
3944
4235
|
return (this.db.prepare(`
|
|
3945
4236
|
SELECT artifact.* FROM devflow_task_intent_artifacts artifact
|
|
@@ -4085,6 +4376,123 @@ export class DevFlowDatabase {
|
|
|
4085
4376
|
return this.getTerminalTransition(record.receiptId)!;
|
|
4086
4377
|
}
|
|
4087
4378
|
|
|
4379
|
+
appendTaskRuntimeEvent(event: TaskRuntimeEventRecord): TaskRuntimeEventRecord {
|
|
4380
|
+
const existing = this.getTaskRuntimeEvent(event.eventId);
|
|
4381
|
+
if (existing) {
|
|
4382
|
+
if (stableTaskRuntimeJson(existing) !== stableTaskRuntimeJson(event)) {
|
|
4383
|
+
throw new Error(`TASK_RUNTIME_EVENT_CONFLICT:${event.eventId}`);
|
|
4384
|
+
}
|
|
4385
|
+
return existing;
|
|
4386
|
+
}
|
|
4387
|
+
const atSequence = this.db.prepare(`
|
|
4388
|
+
SELECT event_id FROM devflow_task_runtime_events
|
|
4389
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ? AND sequence = ?
|
|
4390
|
+
`).get(event.identity.projectRoot, event.identity.sessionId, event.identity.turnId, event.sequence) as
|
|
4391
|
+
{ event_id?: string } | undefined;
|
|
4392
|
+
if (atSequence) throw new Error(`TASK_RUNTIME_SEQUENCE_CONFLICT:${event.sequence}`);
|
|
4393
|
+
try {
|
|
4394
|
+
this.db.prepare(`
|
|
4395
|
+
INSERT INTO devflow_task_runtime_events (
|
|
4396
|
+
event_id, schema_version, producer, producer_version, project_root, project_id,
|
|
4397
|
+
host_id, session_id, turn_id, request_id, execution_id, task_spec_hash,
|
|
4398
|
+
sequence, kind, payload_json, created_at
|
|
4399
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
4400
|
+
`).run(
|
|
4401
|
+
event.eventId, event.schemaVersion, event.producer, event.producerVersion,
|
|
4402
|
+
event.identity.projectRoot, event.identity.projectId, event.identity.hostId,
|
|
4403
|
+
event.identity.sessionId, event.identity.turnId, event.identity.requestId,
|
|
4404
|
+
event.identity.executionId ?? null, event.taskSpecHash, event.sequence,
|
|
4405
|
+
event.kind, stableTaskRuntimeJson(event.payload), event.createdAt,
|
|
4406
|
+
);
|
|
4407
|
+
} catch (error) {
|
|
4408
|
+
const concurrentEvent = this.getTaskRuntimeEvent(event.eventId);
|
|
4409
|
+
if (concurrentEvent) {
|
|
4410
|
+
if (stableTaskRuntimeJson(concurrentEvent) === stableTaskRuntimeJson(event)) return concurrentEvent;
|
|
4411
|
+
throw new Error(`TASK_RUNTIME_EVENT_CONFLICT:${event.eventId}`);
|
|
4412
|
+
}
|
|
4413
|
+
const concurrentSequence = this.db.prepare(`
|
|
4414
|
+
SELECT event_id FROM devflow_task_runtime_events
|
|
4415
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ? AND sequence = ?
|
|
4416
|
+
`).get(event.identity.projectRoot, event.identity.sessionId, event.identity.turnId, event.sequence);
|
|
4417
|
+
if (concurrentSequence) throw new Error(`TASK_RUNTIME_SEQUENCE_CONFLICT:${event.sequence}`);
|
|
4418
|
+
throw error;
|
|
4419
|
+
}
|
|
4420
|
+
return this.getTaskRuntimeEvent(event.eventId)!;
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4423
|
+
getTaskRuntimeEvent(eventId: string): TaskRuntimeEventRecord | null {
|
|
4424
|
+
const row = this.db.prepare('SELECT * FROM devflow_task_runtime_events WHERE event_id = ?')
|
|
4425
|
+
.get(eventId) as Record<string, unknown> | undefined;
|
|
4426
|
+
return row ? mapTaskRuntimeEventRow(row) : null;
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
listTaskRuntimeEvents(projectRoot: string, sessionId: string, turnId: string): TaskRuntimeEventRecord[] {
|
|
4430
|
+
return (this.db.prepare(`
|
|
4431
|
+
SELECT * FROM devflow_task_runtime_events
|
|
4432
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ?
|
|
4433
|
+
ORDER BY sequence ASC
|
|
4434
|
+
`).all(projectRoot, sessionId, turnId) as Array<Record<string, unknown>>)
|
|
4435
|
+
.map(mapTaskRuntimeEventRow);
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
putTaskRuntimeSnapshot(snapshot: TaskRuntimeSnapshotRecord): TaskRuntimeSnapshotRecord {
|
|
4439
|
+
const current = this.getTaskRuntimeSnapshot(
|
|
4440
|
+
snapshot.identity.projectRoot, snapshot.identity.sessionId, snapshot.identity.turnId,
|
|
4441
|
+
);
|
|
4442
|
+
if (current && current.lastEventSequence > snapshot.lastEventSequence) {
|
|
4443
|
+
throw new Error('TASK_RUNTIME_SNAPSHOT_REGRESSION');
|
|
4444
|
+
}
|
|
4445
|
+
this.db.prepare(`
|
|
4446
|
+
INSERT INTO devflow_task_runtime_snapshots (
|
|
4447
|
+
project_root, session_id, turn_id, last_event_sequence, schema_version,
|
|
4448
|
+
snapshot_json, snapshot_hash, updated_at
|
|
4449
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
4450
|
+
ON CONFLICT(project_root, session_id, turn_id) DO UPDATE SET
|
|
4451
|
+
last_event_sequence = excluded.last_event_sequence,
|
|
4452
|
+
schema_version = excluded.schema_version,
|
|
4453
|
+
snapshot_json = excluded.snapshot_json,
|
|
4454
|
+
snapshot_hash = excluded.snapshot_hash,
|
|
4455
|
+
updated_at = excluded.updated_at
|
|
4456
|
+
WHERE excluded.last_event_sequence >= devflow_task_runtime_snapshots.last_event_sequence
|
|
4457
|
+
`).run(
|
|
4458
|
+
snapshot.identity.projectRoot, snapshot.identity.sessionId, snapshot.identity.turnId,
|
|
4459
|
+
snapshot.lastEventSequence, snapshot.schemaVersion, stableTaskRuntimeJson(snapshot),
|
|
4460
|
+
snapshot.snapshotHash, snapshot.updatedAt,
|
|
4461
|
+
);
|
|
4462
|
+
return this.getTaskRuntimeSnapshot(
|
|
4463
|
+
snapshot.identity.projectRoot, snapshot.identity.sessionId, snapshot.identity.turnId,
|
|
4464
|
+
)!;
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4467
|
+
appendTaskRuntimeEventAndSnapshot(
|
|
4468
|
+
event: TaskRuntimeEventRecord,
|
|
4469
|
+
snapshot: TaskRuntimeSnapshotRecord,
|
|
4470
|
+
): TaskRuntimeSnapshotRecord {
|
|
4471
|
+
return this.db.transaction(() => {
|
|
4472
|
+
this.appendTaskRuntimeEvent(event);
|
|
4473
|
+
return this.putTaskRuntimeSnapshot(snapshot);
|
|
4474
|
+
});
|
|
4475
|
+
}
|
|
4476
|
+
|
|
4477
|
+
getTaskRuntimeSnapshot(
|
|
4478
|
+
projectRoot: string,
|
|
4479
|
+
sessionId: string,
|
|
4480
|
+
turnId: string,
|
|
4481
|
+
): TaskRuntimeSnapshotRecord | null {
|
|
4482
|
+
const row = this.db.prepare(`
|
|
4483
|
+
SELECT * FROM devflow_task_runtime_snapshots
|
|
4484
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ?
|
|
4485
|
+
`).get(projectRoot, sessionId, turnId) as Record<string, unknown> | undefined;
|
|
4486
|
+
return row ? mapTaskRuntimeSnapshotRow(row) : null;
|
|
4487
|
+
}
|
|
4488
|
+
|
|
4489
|
+
deleteTaskRuntimeSnapshot(projectRoot: string, sessionId: string, turnId: string): boolean {
|
|
4490
|
+
return this.db.prepare(`
|
|
4491
|
+
DELETE FROM devflow_task_runtime_snapshots
|
|
4492
|
+
WHERE project_root = ? AND session_id = ? AND turn_id = ?
|
|
4493
|
+
`).run(projectRoot, sessionId, turnId).changes > 0;
|
|
4494
|
+
}
|
|
4495
|
+
|
|
4088
4496
|
getTerminalTransition(receiptId: string): TerminalTransitionRecord | null {
|
|
4089
4497
|
const row = this.db.prepare(`
|
|
4090
4498
|
SELECT * FROM devflow_terminal_transitions WHERE receipt_id = ?
|
|
@@ -4156,7 +4564,11 @@ export class DevFlowDatabase {
|
|
|
4156
4564
|
id: row.id, projectRoot: row.project_root, sessionId: row.session_id,
|
|
4157
4565
|
executionId: row.execution_id ?? undefined, turnId: row.turn_id ?? undefined,
|
|
4158
4566
|
requestId: row.request_id, contextReceipt: row.context_receipt,
|
|
4159
|
-
|
|
4567
|
+
schemaVersion: row.schema_version ?? 'retrieval-ledger-event.v1',
|
|
4568
|
+
sourceType: row.source_type, sourceId: row.source_id, stage: row.stage === 'adopted' ? 'consumed' : row.stage,
|
|
4569
|
+
taskSpecHash: row.task_spec_hash ?? undefined, actor: row.actor ?? undefined,
|
|
4570
|
+
sourceVersion: row.source_version ?? undefined, sourceContentHash: row.source_content_hash ?? undefined,
|
|
4571
|
+
evidenceIds: parseJsonStringArray(row.evidence_ids), reasonCode: row.reason_code ?? undefined,
|
|
4160
4572
|
rank: row.rank ?? undefined, rawScore: row.raw_score ?? undefined,
|
|
4161
4573
|
normalizedScore: row.normalized_score ?? undefined, finalScore: row.final_score ?? undefined,
|
|
4162
4574
|
applicability: parseJsonStringArray(row.applicability), reason: row.reason ?? undefined,
|
|
@@ -4501,16 +4913,18 @@ export class DevFlowDatabase {
|
|
|
4501
4913
|
turnId: string;
|
|
4502
4914
|
receiptId: string;
|
|
4503
4915
|
reason: string;
|
|
4916
|
+
source?: string;
|
|
4504
4917
|
decidedAt?: number;
|
|
4505
4918
|
}): MemoryTurnRecord {
|
|
4506
4919
|
const turnId = normalizeTurnId(input.turnId);
|
|
4507
4920
|
this.db.prepare(`
|
|
4508
4921
|
UPDATE devflow_memory_turns
|
|
4509
|
-
SET status = 'skipped', receipt_id = ?, memory_ids = '[]', source =
|
|
4922
|
+
SET status = 'skipped', receipt_id = ?, memory_ids = '[]', source = ?,
|
|
4510
4923
|
reason = ?, decided_at = ?
|
|
4511
4924
|
WHERE turn_id = ? AND status = 'pending'
|
|
4512
4925
|
`).run(
|
|
4513
4926
|
input.receiptId,
|
|
4927
|
+
input.source ?? 'host_skip',
|
|
4514
4928
|
input.reason,
|
|
4515
4929
|
input.decidedAt ?? Date.now(),
|
|
4516
4930
|
turnId,
|
package/src/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ export type {
|
|
|
31
31
|
WorkKind,
|
|
32
32
|
WorkQueueHealth,
|
|
33
33
|
WorkState,
|
|
34
|
+
ProjectMutationLeaseRecord,
|
|
34
35
|
} from './work-queue';
|
|
35
36
|
export type {
|
|
36
37
|
RetrievalLedgerEventRecord,
|
|
@@ -75,6 +76,22 @@ export {
|
|
|
75
76
|
mapTranscriptCheckpointRow,
|
|
76
77
|
stableSemanticJson,
|
|
77
78
|
} from './task-semantic-control';
|
|
79
|
+
export {
|
|
80
|
+
mapTaskRuntimeEventRow,
|
|
81
|
+
mapTaskRuntimeSnapshotRow,
|
|
82
|
+
stableTaskRuntimeHash,
|
|
83
|
+
stableTaskRuntimeJson,
|
|
84
|
+
} from './task-runtime';
|
|
85
|
+
export type {
|
|
86
|
+
TaskRuntimeChannelRecord,
|
|
87
|
+
TaskRuntimeChannelRequirement,
|
|
88
|
+
TaskRuntimeChannelStatus,
|
|
89
|
+
TaskRuntimeEventRecord,
|
|
90
|
+
TaskRuntimeIdentityRecord,
|
|
91
|
+
TaskRuntimeObligationRecord,
|
|
92
|
+
TaskRuntimeObligationState,
|
|
93
|
+
TaskRuntimeSnapshotRecord,
|
|
94
|
+
} from './task-runtime';
|
|
78
95
|
export type {
|
|
79
96
|
ChannelQueryPlanRecord,
|
|
80
97
|
TaskIdentityRecord,
|
|
@@ -124,3 +141,13 @@ export type {
|
|
|
124
141
|
SessionObligationRecord,
|
|
125
142
|
SessionObligationState,
|
|
126
143
|
} from './obligation-ledger';
|
|
144
|
+
export {
|
|
145
|
+
assertSemanticResolutionRecord,
|
|
146
|
+
mapSemanticResolutionRow,
|
|
147
|
+
stableSemanticResolutionJson,
|
|
148
|
+
} from './semantic-resolution';
|
|
149
|
+
export type {
|
|
150
|
+
PersistedSemanticGeneratedBy,
|
|
151
|
+
PersistedSemanticResolutionState,
|
|
152
|
+
SemanticResolutionRecord,
|
|
153
|
+
} from './semantic-resolution';
|
package/src/retrieval-ledger.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export type RetrievalLedgerStage =
|
|
2
|
-
| 'eligible' | 'candidate' | 'selected' | 'exposed' | 'adopted'
|
|
3
|
-
| 'positive_outcome' | 'negative_outcome' | 'unknown' | 'rejected';
|
|
2
|
+
| 'eligible' | 'candidate' | 'selected' | 'exposed' | 'adopted' | 'consumed' | 'verified'
|
|
3
|
+
| 'positive_outcome' | 'negative_outcome' | 'unknown' | 'unknown_outcome' | 'rejected';
|
|
4
4
|
|
|
5
5
|
export type RetrievalLedgerSourceType = 'code' | 'memory' | 'knowledge' | 'action';
|
|
6
6
|
|
|
7
7
|
export interface RetrievalLedgerEventRecord {
|
|
8
|
+
schemaVersion?: 'retrieval-ledger-event.v1';
|
|
8
9
|
id: string;
|
|
9
10
|
projectRoot: string;
|
|
10
11
|
sessionId: string;
|
|
@@ -14,6 +15,12 @@ export interface RetrievalLedgerEventRecord {
|
|
|
14
15
|
contextReceipt: string;
|
|
15
16
|
sourceType: RetrievalLedgerSourceType;
|
|
16
17
|
sourceId: string;
|
|
18
|
+
taskSpecHash?: string;
|
|
19
|
+
actor?: string;
|
|
20
|
+
sourceVersion?: string;
|
|
21
|
+
sourceContentHash?: string;
|
|
22
|
+
evidenceIds?: string[];
|
|
23
|
+
reasonCode?: string;
|
|
17
24
|
stage: RetrievalLedgerStage;
|
|
18
25
|
rank?: number;
|
|
19
26
|
rawScore?: number;
|