@principles/core 1.188.0 → 1.189.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.
Files changed (38) hide show
  1. package/dist/runtime-v2/__tests__/architecture-regression.test.js +9 -0
  2. package/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  3. package/dist/runtime-v2/diagnostician/diag-rootcause-output.d.ts +8 -0
  4. package/dist/runtime-v2/diagnostician/diag-rootcause-output.d.ts.map +1 -1
  5. package/dist/runtime-v2/diagnostician/diag-rootcause-output.js +23 -0
  6. package/dist/runtime-v2/diagnostician/diag-rootcause-output.js.map +1 -1
  7. package/dist/runtime-v2/index.d.ts +3 -2
  8. package/dist/runtime-v2/index.d.ts.map +1 -1
  9. package/dist/runtime-v2/index.js +3 -1
  10. package/dist/runtime-v2/index.js.map +1 -1
  11. package/dist/runtime-v2/intent/__tests__/intent-decision-record.test.d.ts +2 -0
  12. package/dist/runtime-v2/intent/__tests__/intent-decision-record.test.d.ts.map +1 -0
  13. package/dist/runtime-v2/intent/__tests__/intent-decision-record.test.js +183 -0
  14. package/dist/runtime-v2/intent/__tests__/intent-decision-record.test.js.map +1 -0
  15. package/dist/runtime-v2/intent/index.d.ts +1 -0
  16. package/dist/runtime-v2/intent/index.d.ts.map +1 -1
  17. package/dist/runtime-v2/intent/index.js +1 -0
  18. package/dist/runtime-v2/intent/index.js.map +1 -1
  19. package/dist/runtime-v2/intent/intent-decision-record.d.ts +105 -0
  20. package/dist/runtime-v2/intent/intent-decision-record.d.ts.map +1 -0
  21. package/dist/runtime-v2/intent/intent-decision-record.js +21 -0
  22. package/dist/runtime-v2/intent/intent-decision-record.js.map +1 -0
  23. package/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.d.ts +2 -0
  24. package/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.d.ts.map +1 -0
  25. package/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.js +207 -0
  26. package/dist/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.js.map +1 -0
  27. package/dist/runtime-v2/store/intent/index.d.ts +6 -0
  28. package/dist/runtime-v2/store/intent/index.d.ts.map +1 -0
  29. package/dist/runtime-v2/store/intent/index.js +5 -0
  30. package/dist/runtime-v2/store/intent/index.js.map +1 -0
  31. package/dist/runtime-v2/store/intent/sqlite-intent-decision-store.d.ts +36 -0
  32. package/dist/runtime-v2/store/intent/sqlite-intent-decision-store.d.ts.map +1 -0
  33. package/dist/runtime-v2/store/intent/sqlite-intent-decision-store.js +259 -0
  34. package/dist/runtime-v2/store/intent/sqlite-intent-decision-store.js.map +1 -0
  35. package/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
  36. package/dist/runtime-v2/store/sqlite-connection.js +33 -0
  37. package/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
  38. package/package.json +1 -1
@@ -0,0 +1,105 @@
1
+ /**
2
+ * IntentDecisionRecord — durable audit record of Owner decisions on surfaced
3
+ * intentTension (PRI-470, SPEC §21.7).
4
+ *
5
+ * Owner decisions on intentTension MUST form an auditable record. This module
6
+ * defines the pure types and the store interface; the SQLite implementation
7
+ * lives in `runtime-v2/store/intent/`.
8
+ *
9
+ * Persistence boundary (SPEC §21.7):
10
+ * - Records are durable (state.db `intent_decisions` table), never transient.
11
+ * - Same `painId + intentDocHash + ownerAction` resubmission is idempotent.
12
+ * - Records are refresh-safe: read side can query by painId / taskId.
13
+ * - Write failure fails loud with reason + nextAction.
14
+ *
15
+ * ERR checklist:
16
+ * - EP-01 / ERR-001, ERR-005: enum fields validated via type guards, never `as`
17
+ * - EP-03 / ERR-002: store failures surface reason, never silent
18
+ * - EP-09: pure types — independently usable without I/O mocks
19
+ */
20
+ import type { IntentTensionSource, EvidenceStrength, IntentRelatedField, SuggestedOwnerAction } from '../diagnostician/diag-rootcause-output.js';
21
+ /**
22
+ * Durable record of an Owner decision on a surfaced intentTension.
23
+ *
24
+ * Per SPEC §21.7, this is the minimal auditable field set. `evidenceRefs`
25
+ * MUST point to Pain Evidence, trace, Owner correction, or an INTENT field.
26
+ */
27
+ export interface IntentDecisionRecord {
28
+ id: string;
29
+ painId?: string;
30
+ taskId?: string;
31
+ runId?: string;
32
+ intentDocHash?: string;
33
+ source: IntentTensionSource;
34
+ evidenceStrength: EvidenceStrength;
35
+ relatedIntentFields: IntentRelatedField[];
36
+ ownerAction: SuggestedOwnerAction;
37
+ evidenceRefs: string[];
38
+ resultingCandidateId?: string;
39
+ resultingRuleCandidateId?: string;
40
+ patchProposalId?: string;
41
+ createdAt: string;
42
+ }
43
+ /**
44
+ * Input for creating an IntentDecisionRecord.
45
+ *
46
+ * `id` is caller-supplied so the Console API can return the canonical id
47
+ * before persistence completes. `note` is an optional Owner free-text note
48
+ * that the store persists alongside the decision.
49
+ */
50
+ export interface IntentDecisionInput {
51
+ id: string;
52
+ painId?: string;
53
+ taskId?: string;
54
+ runId?: string;
55
+ intentDocHash?: string;
56
+ source: IntentTensionSource;
57
+ evidenceStrength: EvidenceStrength;
58
+ relatedIntentFields: IntentRelatedField[];
59
+ ownerAction: SuggestedOwnerAction;
60
+ evidenceRefs: string[];
61
+ note?: string;
62
+ }
63
+ /**
64
+ * Result of recording a decision.
65
+ *
66
+ * `created=false` means an idempotent hit — the same decision already exists
67
+ * and `record` is the pre-existing record. Callers SHOULD return 200 (not 201)
68
+ * in this case so clients can distinguish a fresh write from a replay.
69
+ */
70
+ export interface IntentDecisionRecordResult {
71
+ record: IntentDecisionRecord;
72
+ created: boolean;
73
+ }
74
+ /**
75
+ * Lightweight audit summary derived from IntentDecisionRecord (SPEC §22.1.1).
76
+ *
77
+ * `counts` holds a tally per SuggestedOwnerAction (every key is present,
78
+ * defaulting to 0). `lastDecisionAt` is the most recent `createdAt` across
79
+ * all records, or null when no records exist.
80
+ */
81
+ export interface IntentDecisionSummary {
82
+ counts: Record<SuggestedOwnerAction, number>;
83
+ lastDecisionAt: string | null;
84
+ }
85
+ /**
86
+ * Durable store contract for IntentDecisionRecord (SPEC §21.7 persistence).
87
+ *
88
+ * Implementations MUST:
89
+ * - Be idempotent on (painId + intentDocHash + ownerAction) when painId is
90
+ * non-null; fall back to (taskId + intentDocHash + ownerAction) when painId
91
+ * is null.
92
+ * - Store immutable snapshots of source / evidenceStrength /
93
+ * relatedIntentFields / evidenceRefs so the audit trail stays accurate even
94
+ * if the underlying artifact is later modified.
95
+ * - Truncate evidence to max 3 items before storing.
96
+ * - Fail loud (throw) on write failure — never return a silent "success".
97
+ */
98
+ export interface IntentDecisionStore {
99
+ record(input: IntentDecisionInput): Promise<IntentDecisionRecordResult>;
100
+ getById(id: string): Promise<IntentDecisionRecord | null>;
101
+ listByPainId(painId: string): Promise<IntentDecisionRecord[]>;
102
+ listByTaskId(taskId: string): Promise<IntentDecisionRecord[]>;
103
+ getSummary(): Promise<IntentDecisionSummary>;
104
+ }
105
+ //# sourceMappingURL=intent-decision-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-decision-record.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/intent/intent-decision-record.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,2CAA2C,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,WAAW,EAAE,oBAAoB,CAAC;IAClC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,WAAW,EAAE,oBAAoB,CAAC;IAClC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAC7C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACxE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC1D,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC9D,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAC9D,UAAU,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;CAC9C"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * IntentDecisionRecord — durable audit record of Owner decisions on surfaced
3
+ * intentTension (PRI-470, SPEC §21.7).
4
+ *
5
+ * Owner decisions on intentTension MUST form an auditable record. This module
6
+ * defines the pure types and the store interface; the SQLite implementation
7
+ * lives in `runtime-v2/store/intent/`.
8
+ *
9
+ * Persistence boundary (SPEC §21.7):
10
+ * - Records are durable (state.db `intent_decisions` table), never transient.
11
+ * - Same `painId + intentDocHash + ownerAction` resubmission is idempotent.
12
+ * - Records are refresh-safe: read side can query by painId / taskId.
13
+ * - Write failure fails loud with reason + nextAction.
14
+ *
15
+ * ERR checklist:
16
+ * - EP-01 / ERR-001, ERR-005: enum fields validated via type guards, never `as`
17
+ * - EP-03 / ERR-002: store failures surface reason, never silent
18
+ * - EP-09: pure types — independently usable without I/O mocks
19
+ */
20
+ export {};
21
+ //# sourceMappingURL=intent-decision-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-decision-record.js","sourceRoot":"","sources":["../../../src/runtime-v2/intent/intent-decision-record.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sqlite-intent-decision-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-intent-decision-store.test.d.ts","sourceRoot":"","sources":["../../../../../src/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * SqliteIntentDecisionStore tests (PRI-470).
3
+ *
4
+ * Verifies idempotency, snapshot storage, evidence truncation, ordering, and
5
+ * summary aggregation against a real SQLite database.
6
+ *
7
+ * ERR checklist:
8
+ * - EP-01 / ERR-001, ERR-005: store treats DB rows as unknown and validates via guards
9
+ * - EP-03 / ERR-002: write failures throw (fail loud), never silent
10
+ * - EP-07 / ERR-015, ERR-018: idempotency distinguishes current vs recorded state
11
+ */
12
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
13
+ import * as path from 'node:path';
14
+ import * as os from 'node:os';
15
+ import * as fs from 'node:fs';
16
+ import { SqliteConnection } from '../../sqlite-connection.js';
17
+ import { SqliteIntentDecisionStore } from '../sqlite-intent-decision-store.js';
18
+ function createTestConnection() {
19
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-test-intent-decision-'));
20
+ return new SqliteConnection(tmpDir);
21
+ }
22
+ function makeInput(overrides = {}) {
23
+ return {
24
+ id: 'rec-' + Math.random().toString(36).slice(2, 8),
25
+ painId: 'pain-1',
26
+ taskId: 'task-1',
27
+ runId: 'run-1',
28
+ intentDocHash: 'sha256:abc',
29
+ source: 'action_drift',
30
+ evidenceStrength: 'moderate',
31
+ relatedIntentFields: ['why'],
32
+ ownerAction: 'confirm_drift',
33
+ evidenceRefs: ['ref-1', 'ref-2'],
34
+ ...overrides,
35
+ };
36
+ }
37
+ describe('SqliteIntentDecisionStore', () => {
38
+ let connection = null;
39
+ let store = null;
40
+ beforeEach(() => {
41
+ connection = createTestConnection();
42
+ // Touch getDb() so the schema (including intent_decisions) is initialized.
43
+ connection.getDb();
44
+ store = new SqliteIntentDecisionStore(connection);
45
+ });
46
+ afterEach(() => {
47
+ connection?.close();
48
+ });
49
+ describe('record()', () => {
50
+ it('creates a new record with correct fields', async () => {
51
+ const input = makeInput({ id: 'rec-new' });
52
+ const result = await store.record(input);
53
+ expect(result.created).toBe(true);
54
+ expect(result.record.id).toBe('rec-new');
55
+ expect(result.record.painId).toBe('pain-1');
56
+ expect(result.record.taskId).toBe('task-1');
57
+ expect(result.record.source).toBe('action_drift');
58
+ expect(result.record.evidenceStrength).toBe('moderate');
59
+ expect(result.record.relatedIntentFields).toEqual(['why']);
60
+ expect(result.record.ownerAction).toBe('confirm_drift');
61
+ expect(result.record.evidenceRefs).toEqual(['ref-1', 'ref-2']);
62
+ expect(result.record.createdAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
63
+ });
64
+ it('is idempotent when same painId + intentDocHash + ownerAction is resubmitted', async () => {
65
+ const input = makeInput({ id: 'rec-first', painId: 'pain-1', intentDocHash: 'sha256:abc', ownerAction: 'confirm_drift' });
66
+ const first = await store.record(input);
67
+ expect(first.created).toBe(true);
68
+ // Same idempotency key, different id — must return the existing record.
69
+ const replay = await store.record(makeInput({ id: 'rec-second', painId: 'pain-1', intentDocHash: 'sha256:abc', ownerAction: 'confirm_drift' }));
70
+ expect(replay.created).toBe(false);
71
+ expect(replay.record.id).toBe('rec-first');
72
+ });
73
+ it('does NOT treat different ownerAction as idempotent', async () => {
74
+ await store.record(makeInput({ id: 'rec-a', painId: 'pain-1', intentDocHash: 'sha256:abc', ownerAction: 'confirm_drift' }));
75
+ const second = await store.record(makeInput({ id: 'rec-b', painId: 'pain-1', intentDocHash: 'sha256:abc', ownerAction: 'observe' }));
76
+ expect(second.created).toBe(true);
77
+ expect(second.record.id).toBe('rec-b');
78
+ });
79
+ it('with null painId uses taskId-based idempotency', async () => {
80
+ const input = makeInput({
81
+ id: 'rec-task-1',
82
+ painId: undefined,
83
+ taskId: 'task-X',
84
+ intentDocHash: 'sha256:xyz',
85
+ ownerAction: 'dismiss',
86
+ });
87
+ const first = await store.record(input);
88
+ expect(first.created).toBe(true);
89
+ const replay = await store.record(makeInput({
90
+ id: 'rec-task-2',
91
+ painId: undefined,
92
+ taskId: 'task-X',
93
+ intentDocHash: 'sha256:xyz',
94
+ ownerAction: 'dismiss',
95
+ }));
96
+ expect(replay.created).toBe(false);
97
+ expect(replay.record.id).toBe('rec-task-1');
98
+ });
99
+ it('with null painId and null intentDocHash still idempotency-checks via IS operator', async () => {
100
+ await store.record(makeInput({
101
+ id: 'rec-null-1', painId: undefined, taskId: 'task-Y', intentDocHash: undefined, ownerAction: 'observe',
102
+ }));
103
+ const replay = await store.record(makeInput({
104
+ id: 'rec-null-2', painId: undefined, taskId: 'task-Y', intentDocHash: undefined, ownerAction: 'observe',
105
+ }));
106
+ expect(replay.created).toBe(false);
107
+ expect(replay.record.id).toBe('rec-null-1');
108
+ });
109
+ it('truncates evidence to max 3 items', async () => {
110
+ const input = makeInput({ id: 'rec-trunc', evidenceRefs: ['r1', 'r2', 'r3', 'r4', 'r5'] });
111
+ const result = await store.record(input);
112
+ expect(result.record.evidenceRefs).toEqual(['r1', 'r2', 'r3']);
113
+ });
114
+ it('stores immutable snapshots matching the decision-time values', async () => {
115
+ const input = makeInput({
116
+ id: 'rec-snap',
117
+ source: 'intent_suspect',
118
+ evidenceStrength: 'strong',
119
+ relatedIntentFields: ['why', 'desired_outcome'],
120
+ evidenceRefs: ['e1', 'e2'],
121
+ });
122
+ const result = await store.record(input);
123
+ // Read the raw row to verify snapshot columns exist and match.
124
+ const row = connection.getDb().prepare('SELECT source_snapshot, evidence_strength_snapshot, related_intent_fields_snapshot, evidence_refs_snapshot FROM intent_decisions WHERE id = ?').get(result.record.id);
125
+ expect(row.source_snapshot).toBe('intent_suspect');
126
+ expect(row.evidence_strength_snapshot).toBe('strong');
127
+ expect(JSON.parse(row.related_intent_fields_snapshot)).toEqual(['why', 'desired_outcome']);
128
+ expect(JSON.parse(row.evidence_refs_snapshot)).toEqual(['e1', 'e2']);
129
+ });
130
+ it('persists the optional note when provided', async () => {
131
+ const result = await store.record(makeInput({ id: 'rec-note', note: 'owner note text' }));
132
+ const row = connection.getDb().prepare('SELECT note FROM intent_decisions WHERE id = ?').get(result.record.id);
133
+ expect(row.note).toBe('owner note text');
134
+ });
135
+ });
136
+ describe('getById()', () => {
137
+ it('returns the record when found', async () => {
138
+ const created = await store.record(makeInput({ id: 'rec-get' }));
139
+ const found = await store.getById('rec-get');
140
+ expect(found).not.toBeNull();
141
+ expect(found?.id).toBe('rec-get');
142
+ expect(found?.source).toBe(created.record.source);
143
+ });
144
+ it('returns null when not found', async () => {
145
+ const found = await store.getById('does-not-exist');
146
+ expect(found).toBeNull();
147
+ });
148
+ });
149
+ describe('listByPainId()', () => {
150
+ it('returns records ordered by createdAt DESC', async () => {
151
+ await store.record(makeInput({ id: 'r1', painId: 'pain-list', ownerAction: 'confirm_drift' }));
152
+ await new Promise((r) => setTimeout(r, 10));
153
+ await store.record(makeInput({ id: 'r2', painId: 'pain-list', ownerAction: 'observe', intentDocHash: 'sha256:other' }));
154
+ const list = await store.listByPainId('pain-list');
155
+ expect(list).toHaveLength(2);
156
+ expect(list[0]?.id).toBe('r2');
157
+ expect(list[1]?.id).toBe('r1');
158
+ });
159
+ it('returns empty array for unknown painId', async () => {
160
+ const list = await store.listByPainId('unknown');
161
+ expect(list).toEqual([]);
162
+ });
163
+ });
164
+ describe('listByTaskId()', () => {
165
+ it('returns records ordered by createdAt DESC', async () => {
166
+ await store.record(makeInput({ id: 't1', taskId: 'task-list', painId: 'p1', intentDocHash: 'h1', ownerAction: 'confirm_drift' }));
167
+ await new Promise((r) => setTimeout(r, 10));
168
+ await store.record(makeInput({ id: 't2', taskId: 'task-list', painId: 'p2', intentDocHash: 'h2', ownerAction: 'observe' }));
169
+ const list = await store.listByTaskId('task-list');
170
+ expect(list).toHaveLength(2);
171
+ expect(list[0]?.id).toBe('t2');
172
+ expect(list[1]?.id).toBe('t1');
173
+ });
174
+ it('returns empty array for unknown taskId', async () => {
175
+ const list = await store.listByTaskId('unknown');
176
+ expect(list).toEqual([]);
177
+ });
178
+ });
179
+ describe('getSummary()', () => {
180
+ it('returns all-zero counts and null lastDecisionAt when no records exist', async () => {
181
+ const summary = await store.getSummary();
182
+ expect(summary.lastDecisionAt).toBeNull();
183
+ expect(summary.counts).toEqual({
184
+ confirm_drift: 0,
185
+ revise_intent: 0,
186
+ observe: 0,
187
+ dismiss: 0,
188
+ promote_to_principle: 0,
189
+ promote_to_rulehost: 0,
190
+ });
191
+ });
192
+ it('returns counts per ownerAction and the most recent lastDecisionAt', async () => {
193
+ await store.record(makeInput({ id: 's1', painId: 'p1', intentDocHash: 'h1', ownerAction: 'confirm_drift' }));
194
+ await store.record(makeInput({ id: 's2', painId: 'p2', intentDocHash: 'h2', ownerAction: 'confirm_drift' }));
195
+ await store.record(makeInput({ id: 's3', painId: 'p3', intentDocHash: 'h3', ownerAction: 'observe' }));
196
+ const summary = await store.getSummary();
197
+ expect(summary.counts.confirm_drift).toBe(2);
198
+ expect(summary.counts.observe).toBe(1);
199
+ expect(summary.counts.dismiss).toBe(0);
200
+ expect(summary.counts.revise_intent).toBe(0);
201
+ expect(summary.counts.promote_to_principle).toBe(0);
202
+ expect(summary.counts.promote_to_rulehost).toBe(0);
203
+ expect(summary.lastDecisionAt).not.toBeNull();
204
+ });
205
+ });
206
+ });
207
+ //# sourceMappingURL=sqlite-intent-decision-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-intent-decision-store.test.js","sourceRoot":"","sources":["../../../../../src/runtime-v2/store/intent/__tests__/sqlite-intent-decision-store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Barrel for the IntentDecisionRecord SQLite store (PRI-470).
3
+ */
4
+ export { SqliteIntentDecisionStore } from './sqlite-intent-decision-store.js';
5
+ export type { IntentDecisionStore } from '../../intent/intent-decision-record.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/store/intent/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,YAAY,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Barrel for the IntentDecisionRecord SQLite store (PRI-470).
3
+ */
4
+ export { SqliteIntentDecisionStore } from './sqlite-intent-decision-store.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/runtime-v2/store/intent/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * SqliteIntentDecisionStore — SQLite implementation of IntentDecisionStore.
3
+ *
4
+ * PRI-470 / SPEC §21.7 durable persistence for Owner decisions on
5
+ * intentTension. Records are written to the `intent_decisions` table
6
+ * (schema created by SqliteConnection.initSchema).
7
+ *
8
+ * Idempotency (SPEC §21.7 req 4):
9
+ * - When `painId` is non-null: dedupe on (pain_id, intent_doc_hash, owner_action).
10
+ * - When `painId` is null: dedupe on (task_id, intent_doc_hash, owner_action)
11
+ * using the NULL-safe `IS` operator so a null intentDocHash compares equal.
12
+ *
13
+ * Snapshots (SPEC §21.7 audit boundary):
14
+ * - source / evidenceStrength / relatedIntentFields / evidenceRefs are stored
15
+ * twice: once in the live columns and once in the `_snapshot` columns. The
16
+ * snapshot is the immutable audit copy; the live columns mirror it at write
17
+ * time. This keeps the audit trail accurate even if a future migration or
18
+ * artifact change alters the live columns.
19
+ *
20
+ * ERR checklist:
21
+ * - EP-01 / ERR-001, ERR-005: DB rows treated as unknown, mapped via guards
22
+ * - EP-03 / ERR-002: write failures throw (fail loud)
23
+ * - EP-07 / ERR-015, ERR-018: idempotency SELECT reads fresh state each call
24
+ */
25
+ import type { SqliteConnection } from '../sqlite-connection.js';
26
+ import type { IntentDecisionInput, IntentDecisionRecord, IntentDecisionRecordResult, IntentDecisionSummary, IntentDecisionStore } from '../../intent/intent-decision-record.js';
27
+ export declare class SqliteIntentDecisionStore implements IntentDecisionStore {
28
+ private readonly connection;
29
+ constructor(connection: SqliteConnection);
30
+ record(input: IntentDecisionInput): Promise<IntentDecisionRecordResult>;
31
+ getById(id: string): Promise<IntentDecisionRecord | null>;
32
+ listByPainId(painId: string): Promise<IntentDecisionRecord[]>;
33
+ listByTaskId(taskId: string): Promise<IntentDecisionRecord[]>;
34
+ getSummary(): Promise<IntentDecisionSummary>;
35
+ }
36
+ //# sourceMappingURL=sqlite-intent-decision-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-intent-decision-store.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/store/intent/sqlite-intent-decision-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,wCAAwC,CAAC;AAsJhD,qBAAa,yBAA0B,YAAW,mBAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,gBAAgB;IAEnD,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAiFvE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAOzD,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAS7D,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAS7D,UAAU,IAAI,OAAO,CAAC,qBAAqB,CAAC;CAsBnD"}