@principles/core 1.287.7 → 1.287.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/principle-tree-ledger.d.ts +50 -0
- package/dist/principle-tree-ledger.d.ts.map +1 -1
- package/dist/principle-tree-ledger.js +133 -1
- package/dist/principle-tree-ledger.js.map +1 -1
- package/dist/runtime-v2/adapter/principle-tree-ledger-adapter.d.ts +24 -0
- package/dist/runtime-v2/adapter/principle-tree-ledger-adapter.d.ts.map +1 -1
- package/dist/runtime-v2/adapter/principle-tree-ledger-adapter.js +36 -1
- package/dist/runtime-v2/adapter/principle-tree-ledger-adapter.js.map +1 -1
- package/dist/runtime-v2/candidate-intake-service.d.ts +102 -3
- package/dist/runtime-v2/candidate-intake-service.d.ts.map +1 -1
- package/dist/runtime-v2/candidate-intake-service.js +280 -47
- package/dist/runtime-v2/candidate-intake-service.js.map +1 -1
- package/dist/runtime-v2/candidate-intake.d.ts +44 -0
- package/dist/runtime-v2/candidate-intake.d.ts.map +1 -1
- package/dist/runtime-v2/candidate-intake.js +7 -0
- package/dist/runtime-v2/candidate-intake.js.map +1 -1
- package/dist/runtime-v2/index.d.ts +6 -0
- package/dist/runtime-v2/index.d.ts.map +1 -1
- package/dist/runtime-v2/index.js +7 -0
- package/dist/runtime-v2/index.js.map +1 -1
- package/dist/runtime-v2/pain-signal-bridge.d.ts.map +1 -1
- package/dist/runtime-v2/pain-signal-bridge.js +14 -1
- package/dist/runtime-v2/pain-signal-bridge.js.map +1 -1
- package/dist/runtime-v2/principle-reuse/reuse-domain.d.ts +89 -0
- package/dist/runtime-v2/principle-reuse/reuse-domain.d.ts.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-domain.js +16 -0
- package/dist/runtime-v2/principle-reuse/reuse-domain.js.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-proposal.d.ts +87 -0
- package/dist/runtime-v2/principle-reuse/reuse-proposal.d.ts.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-proposal.js +99 -0
- package/dist/runtime-v2/principle-reuse/reuse-proposal.js.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-retrieval.d.ts +36 -0
- package/dist/runtime-v2/principle-reuse/reuse-retrieval.d.ts.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-retrieval.js +118 -0
- package/dist/runtime-v2/principle-reuse/reuse-retrieval.js.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-shortlist.d.ts +40 -0
- package/dist/runtime-v2/principle-reuse/reuse-shortlist.d.ts.map +1 -0
- package/dist/runtime-v2/principle-reuse/reuse-shortlist.js +184 -0
- package/dist/runtime-v2/principle-reuse/reuse-shortlist.js.map +1 -0
- package/dist/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.d.ts +7 -0
- package/dist/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.d.ts.map +1 -1
- package/dist/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.js.map +1 -1
- package/dist/runtime-v2/store/pain-diagnosis/sqlite-pain-diagnosis-store.d.ts +1 -0
- package/dist/runtime-v2/store/pain-diagnosis/sqlite-pain-diagnosis-store.d.ts.map +1 -1
- package/dist/runtime-v2/store/pain-diagnosis/sqlite-pain-diagnosis-store.js +12 -0
- package/dist/runtime-v2/store/pain-diagnosis/sqlite-pain-diagnosis-store.js.map +1 -1
- package/dist/runtime-v2/store/runtime-state-manager.d.ts +5 -0
- package/dist/runtime-v2/store/runtime-state-manager.d.ts.map +1 -1
- package/dist/runtime-v2/store/runtime-state-manager.js +8 -0
- package/dist/runtime-v2/store/runtime-state-manager.js.map +1 -1
- package/dist/runtime-v2/types/principle-schema.d.ts +65 -0
- package/dist/runtime-v2/types/principle-schema.d.ts.map +1 -1
- package/dist/runtime-v2/types/principle-schema.js +14 -0
- package/dist/runtime-v2/types/principle-schema.js.map +1 -1
- package/dist/runtime-v2/types/principle-tree-store.d.ts +12 -0
- package/dist/runtime-v2/types/principle-tree-store.d.ts.map +1 -1
- package/dist/telemetry-event.d.ts +2 -2
- package/dist/telemetry-event.d.ts.map +1 -1
- package/dist/telemetry-event.js +2 -0
- package/dist/telemetry-event.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-917 Slice 2 — reuse proposal + decision contract (internal).
|
|
3
|
+
*
|
|
4
|
+
* This slice delivers the FLOW only: given a candidate, produce a bounded
|
|
5
|
+
* proposal of existing Principles that may already cover it, and let an
|
|
6
|
+
* injected decision function answer `reuse` or `create`.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately NOT in this slice (SPEC v0.2 / task scope):
|
|
9
|
+
* - persistence of the decision or the relation (`reuseEvidence[]` is Slice 3)
|
|
10
|
+
* - any Console page, new approval subsystem, or automated decision model
|
|
11
|
+
* - any change to `derivedFromPainIds`, the ledger schema, or candidate status
|
|
12
|
+
*
|
|
13
|
+
* @see docs/specs/PRI-917-reuse-before-create-v0.1.md (SPEC v0.2)
|
|
14
|
+
*/
|
|
15
|
+
import type { ReuseShortlist } from './reuse-domain.js';
|
|
16
|
+
import type { ReuseEvidenceActor } from '../types/principle-schema.js';
|
|
17
|
+
/**
|
|
18
|
+
* `pending` — credible existing Principles were found and an Owner decision is
|
|
19
|
+
* required before anything is written.
|
|
20
|
+
* `no_candidates` — nothing credible was found; the caller proceeds to create.
|
|
21
|
+
*/
|
|
22
|
+
export type ReuseProposalStatus = 'pending' | 'no_candidates';
|
|
23
|
+
export interface ReuseProposalEntry {
|
|
24
|
+
/** Canonical Principle Ledger UUID. */
|
|
25
|
+
principleId: string;
|
|
26
|
+
score: number;
|
|
27
|
+
/** Human-readable reasons, one per evidence field. */
|
|
28
|
+
reasons: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface ReuseProposal {
|
|
31
|
+
candidateId: string;
|
|
32
|
+
status: ReuseProposalStatus;
|
|
33
|
+
candidates: ReuseProposalEntry[];
|
|
34
|
+
/** Principles that passed status eligibility. */
|
|
35
|
+
eligibleCount: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The Owner's answer. There is no automatic option.
|
|
39
|
+
*
|
|
40
|
+
* A `reuse` verdict carries the SPEC §11 decision-exchange fields (`actor`,
|
|
41
|
+
* `reason`, `decidedAt`) because PRI-917 PR3B materialises the verdict into
|
|
42
|
+
* `Principle.reuseEvidence[]` verbatim (SPEC §12): the durable evidence must
|
|
43
|
+
* record WHO decided, WHY, and WHEN — an answer without them cannot be
|
|
44
|
+
* persisted as a reuse resolution, so the validator rejects it fail-closed.
|
|
45
|
+
*/
|
|
46
|
+
export type ReuseDecision = {
|
|
47
|
+
decision: 'create';
|
|
48
|
+
} | {
|
|
49
|
+
decision: 'reuse';
|
|
50
|
+
selectedPrincipleId: string;
|
|
51
|
+
actor: ReuseEvidenceActor;
|
|
52
|
+
reason: string;
|
|
53
|
+
decidedAt: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Converts a deterministic shortlist into the proposal contract.
|
|
57
|
+
*
|
|
58
|
+
* The shortlist already guarantees determinism and a bounded Top-K, so this is
|
|
59
|
+
* a pure projection: it adds no ranking of its own and never widens the set.
|
|
60
|
+
*/
|
|
61
|
+
export declare function buildReuseProposal(candidateId: string, shortlist: ReuseShortlist): ReuseProposal;
|
|
62
|
+
/** True when the proposal needs an Owner answer before writing. */
|
|
63
|
+
export declare function proposalNeedsDecision(proposal: ReuseProposal): boolean;
|
|
64
|
+
export type ReuseDecisionValidation = {
|
|
65
|
+
ok: true;
|
|
66
|
+
decision: ReuseDecision;
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
reason: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Runtime validator for the reuse decision (rc-1/rc-2/rc-3).
|
|
73
|
+
*
|
|
74
|
+
* The decision function is an untrusted boundary — an AI Owner parses model
|
|
75
|
+
* output into it — so its TypeScript type cannot be the guard. A bare
|
|
76
|
+
* `"create"` string, `{}`, `{decision:'REUSE'}`, a non-string principle id, or
|
|
77
|
+
* a missing id for reuse are ALL rejected here, because the alternative is
|
|
78
|
+
* silently reading a malformed answer as "go ahead and create" — the exact
|
|
79
|
+
* duplicate manufacturing this gate exists to prevent.
|
|
80
|
+
*
|
|
81
|
+
* PRI-917 PR3B Phase 2: a `reuse` verdict must additionally carry the
|
|
82
|
+
* SPEC §11 accountability fields (`actor` / `reason` / `decidedAt`) — they are
|
|
83
|
+
* materialised verbatim into `Principle.reuseEvidence[]`, and an answer
|
|
84
|
+
* without them cannot produce a self-contained, auditable evidence entry.
|
|
85
|
+
*/
|
|
86
|
+
export declare function validateReuseDecision(raw: unknown): ReuseDecisionValidation;
|
|
87
|
+
//# sourceMappingURL=reuse-proposal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse-proposal.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/principle-reuse/reuse-proposal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAEvE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,eAAe,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,iDAAiD;IACjD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACtB;IACE,QAAQ,EAAE,OAAO,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,cAAc,GACxB,aAAa,CAef;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAEtE;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GACrC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,uBAAuB,CAwC3E"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-917 Slice 2 — reuse proposal + decision contract (internal).
|
|
3
|
+
*
|
|
4
|
+
* This slice delivers the FLOW only: given a candidate, produce a bounded
|
|
5
|
+
* proposal of existing Principles that may already cover it, and let an
|
|
6
|
+
* injected decision function answer `reuse` or `create`.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately NOT in this slice (SPEC v0.2 / task scope):
|
|
9
|
+
* - persistence of the decision or the relation (`reuseEvidence[]` is Slice 3)
|
|
10
|
+
* - any Console page, new approval subsystem, or automated decision model
|
|
11
|
+
* - any change to `derivedFromPainIds`, the ledger schema, or candidate status
|
|
12
|
+
*
|
|
13
|
+
* @see docs/specs/PRI-917-reuse-before-create-v0.1.md (SPEC v0.2)
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Converts a deterministic shortlist into the proposal contract.
|
|
17
|
+
*
|
|
18
|
+
* The shortlist already guarantees determinism and a bounded Top-K, so this is
|
|
19
|
+
* a pure projection: it adds no ranking of its own and never widens the set.
|
|
20
|
+
*/
|
|
21
|
+
export function buildReuseProposal(candidateId, shortlist) {
|
|
22
|
+
const candidates = shortlist.candidates.map((entry) => ({
|
|
23
|
+
principleId: entry.principleId,
|
|
24
|
+
score: entry.score,
|
|
25
|
+
reasons: [
|
|
26
|
+
entry.similarityReason,
|
|
27
|
+
...entry.evidence.map((e) => `${e.field}: ${e.sharedTerms.slice(0, 5).join('、')}`),
|
|
28
|
+
],
|
|
29
|
+
}));
|
|
30
|
+
return {
|
|
31
|
+
candidateId,
|
|
32
|
+
status: candidates.length > 0 ? 'pending' : 'no_candidates',
|
|
33
|
+
candidates,
|
|
34
|
+
eligibleCount: shortlist.eligibleCount,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** True when the proposal needs an Owner answer before writing. */
|
|
38
|
+
export function proposalNeedsDecision(proposal) {
|
|
39
|
+
return proposal.status === 'pending';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Runtime validator for the reuse decision (rc-1/rc-2/rc-3).
|
|
43
|
+
*
|
|
44
|
+
* The decision function is an untrusted boundary — an AI Owner parses model
|
|
45
|
+
* output into it — so its TypeScript type cannot be the guard. A bare
|
|
46
|
+
* `"create"` string, `{}`, `{decision:'REUSE'}`, a non-string principle id, or
|
|
47
|
+
* a missing id for reuse are ALL rejected here, because the alternative is
|
|
48
|
+
* silently reading a malformed answer as "go ahead and create" — the exact
|
|
49
|
+
* duplicate manufacturing this gate exists to prevent.
|
|
50
|
+
*
|
|
51
|
+
* PRI-917 PR3B Phase 2: a `reuse` verdict must additionally carry the
|
|
52
|
+
* SPEC §11 accountability fields (`actor` / `reason` / `decidedAt`) — they are
|
|
53
|
+
* materialised verbatim into `Principle.reuseEvidence[]`, and an answer
|
|
54
|
+
* without them cannot produce a self-contained, auditable evidence entry.
|
|
55
|
+
*/
|
|
56
|
+
export function validateReuseDecision(raw) {
|
|
57
|
+
if (raw === null || raw === undefined)
|
|
58
|
+
return { ok: false, reason: 'decision_is_nullish' };
|
|
59
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
60
|
+
return { ok: false, reason: 'decision_is_not_an_object' };
|
|
61
|
+
const record = raw;
|
|
62
|
+
const { decision } = record;
|
|
63
|
+
if (decision === 'create')
|
|
64
|
+
return { ok: true, decision: { decision: 'create' } };
|
|
65
|
+
if (decision !== 'reuse')
|
|
66
|
+
return { ok: false, reason: `unknown_decision_value:${String(decision)}` };
|
|
67
|
+
const selected = record.selectedPrincipleId;
|
|
68
|
+
if (typeof selected !== 'string' || selected.length === 0) {
|
|
69
|
+
return { ok: false, reason: 'reuse_without_principle_id' };
|
|
70
|
+
}
|
|
71
|
+
const actorRaw = record.actor;
|
|
72
|
+
if (typeof actorRaw !== 'object' || actorRaw === null || Array.isArray(actorRaw)) {
|
|
73
|
+
return { ok: false, reason: 'reuse_actor_invalid' };
|
|
74
|
+
}
|
|
75
|
+
const actorRecord = actorRaw;
|
|
76
|
+
if (!(actorRecord.kind === 'owner' || actorRecord.kind === 'ai_owner')
|
|
77
|
+
|| typeof actorRecord.id !== 'string'
|
|
78
|
+
|| actorRecord.id.length === 0) {
|
|
79
|
+
return { ok: false, reason: 'reuse_actor_invalid' };
|
|
80
|
+
}
|
|
81
|
+
const { reason, decidedAt } = record;
|
|
82
|
+
if (typeof reason !== 'string' || reason.length === 0) {
|
|
83
|
+
return { ok: false, reason: 'reuse_reason_missing' };
|
|
84
|
+
}
|
|
85
|
+
if (typeof decidedAt !== 'string' || decidedAt.length === 0 || Number.isNaN(Date.parse(decidedAt))) {
|
|
86
|
+
return { ok: false, reason: 'reuse_decidedAt_invalid' };
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
ok: true,
|
|
90
|
+
decision: {
|
|
91
|
+
decision: 'reuse',
|
|
92
|
+
selectedPrincipleId: selected,
|
|
93
|
+
actor: { kind: actorRecord.kind, id: actorRecord.id },
|
|
94
|
+
reason,
|
|
95
|
+
decidedAt,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=reuse-proposal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse-proposal.js","sourceRoot":"","sources":["../../../src/runtime-v2/principle-reuse/reuse-proposal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-917 Slice 1 — read-only reuse retrieval over the existing Principle
|
|
3
|
+
* Ledger.
|
|
4
|
+
*
|
|
5
|
+
* Reuses `loadLedger` (the single ledger authority) and the existing
|
|
6
|
+
* principle-kind guard. Creates no repository, no database, no index, no
|
|
7
|
+
* vector store, and no embedding service. It never writes: `derivedFromPainIds`,
|
|
8
|
+
* the ledger schema, and `activation_decisions` are all untouched.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/specs/PRI-917-reuse-before-create-v0.1.md (SPEC v0.2)
|
|
11
|
+
*/
|
|
12
|
+
import type { ReuseCandidateInput, ReusablePrinciple, ReuseShortlist, ReuseShortlistOptions } from './reuse-domain.js';
|
|
13
|
+
/**
|
|
14
|
+
* Statuses a Principle may be reused into (SPEC §15).
|
|
15
|
+
*
|
|
16
|
+
* `active` and `candidate`/`probation` are included because that is where real
|
|
17
|
+
* reusable knowledge lives — excluding `candidate` would leave almost nothing,
|
|
18
|
+
* as the live ledger is overwhelmingly `candidate`. `archived` and `deprecated`
|
|
19
|
+
* are excluded: reusing into a retired Principle would revive withdrawn
|
|
20
|
+
* knowledge. Any unrecognised status is excluded fail-closed.
|
|
21
|
+
*/
|
|
22
|
+
export declare const REUSABLE_PRINCIPLE_STATUSES: ReadonlySet<string>;
|
|
23
|
+
export declare function isReusablePrincipleStatus(status: unknown): boolean;
|
|
24
|
+
export declare function readReusablePrinciples(stateDir: string): ReusablePrinciple[];
|
|
25
|
+
/**
|
|
26
|
+
* Build the reuse shortlist for a candidate, from the canonical ledger.
|
|
27
|
+
*
|
|
28
|
+
* `recommendationKind` is checked with the SAME guard the intake write boundary
|
|
29
|
+
* uses, so a non-principle candidate can never reach the reuse path (SPEC T6 —
|
|
30
|
+
* the #1851 refusal semantics stay exactly as they are; this only makes the
|
|
31
|
+
* reuse path refuse them too).
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildReuseShortlist(input: ReuseCandidateInput, stateDir: string, options?: ReuseShortlistOptions & {
|
|
34
|
+
recommendationKind?: unknown;
|
|
35
|
+
}): ReuseShortlist;
|
|
36
|
+
//# sourceMappingURL=reuse-retrieval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse-retrieval.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/principle-reuse/reuse-retrieval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAI1D,CAAC;AAEH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAMlE;AA0CD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAa5E;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,mBAAmB,EAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,qBAAqB,GAAG;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GACrE,cAAc,CAWhB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-917 Slice 1 — read-only reuse retrieval over the existing Principle
|
|
3
|
+
* Ledger.
|
|
4
|
+
*
|
|
5
|
+
* Reuses `loadLedger` (the single ledger authority) and the existing
|
|
6
|
+
* principle-kind guard. Creates no repository, no database, no index, no
|
|
7
|
+
* vector store, and no embedding service. It never writes: `derivedFromPainIds`,
|
|
8
|
+
* the ledger schema, and `activation_decisions` are all untouched.
|
|
9
|
+
*
|
|
10
|
+
* @see docs/specs/PRI-917-reuse-before-create-v0.1.md (SPEC v0.2)
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from 'fs';
|
|
13
|
+
import { getLedgerFilePathPublic, loadLedger } from '../../principle-tree-ledger.js';
|
|
14
|
+
import { isPrincipleLedgerEligibleKind } from '../store/candidate/recommendation-kind-resolver.js';
|
|
15
|
+
import { PRINCIPLE_STATUSES } from '../types/principle-enums.js';
|
|
16
|
+
import { isRecord } from '../candidate-intake.js';
|
|
17
|
+
import { selectReuseShortlist } from './reuse-shortlist.js';
|
|
18
|
+
/**
|
|
19
|
+
* Statuses a Principle may be reused into (SPEC §15).
|
|
20
|
+
*
|
|
21
|
+
* `active` and `candidate`/`probation` are included because that is where real
|
|
22
|
+
* reusable knowledge lives — excluding `candidate` would leave almost nothing,
|
|
23
|
+
* as the live ledger is overwhelmingly `candidate`. `archived` and `deprecated`
|
|
24
|
+
* are excluded: reusing into a retired Principle would revive withdrawn
|
|
25
|
+
* knowledge. Any unrecognised status is excluded fail-closed.
|
|
26
|
+
*/
|
|
27
|
+
export const REUSABLE_PRINCIPLE_STATUSES = new Set([
|
|
28
|
+
'active',
|
|
29
|
+
'candidate',
|
|
30
|
+
'probation',
|
|
31
|
+
]);
|
|
32
|
+
export function isReusablePrincipleStatus(status) {
|
|
33
|
+
if (typeof status !== 'string')
|
|
34
|
+
return false;
|
|
35
|
+
// Fail closed on a status outside the known enum: an unrecognised value is
|
|
36
|
+
// treated as not reusable rather than optimistically reusable.
|
|
37
|
+
if (!PRINCIPLE_STATUSES.includes(status))
|
|
38
|
+
return false;
|
|
39
|
+
return REUSABLE_PRINCIPLE_STATUSES.has(status);
|
|
40
|
+
}
|
|
41
|
+
function assertLedgerReadable(stateDir) {
|
|
42
|
+
const filePath = getLedgerFilePathPublic(stateDir);
|
|
43
|
+
if (!existsSync(filePath))
|
|
44
|
+
return; // no corpus yet — nothing to reuse
|
|
45
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
46
|
+
if (raw.trim() === '')
|
|
47
|
+
return; // an empty document is an empty corpus
|
|
48
|
+
// Throws on malformed JSON so the caller fails the gate rather than silently
|
|
49
|
+
// treating unreadable knowledge as absent knowledge.
|
|
50
|
+
JSON.parse(raw);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Read every reusable Principle from the canonical ledger.
|
|
54
|
+
*
|
|
55
|
+
* Read-only: opens the ledger document and filters in memory. No caching is
|
|
56
|
+
* introduced here — the corpus is small (order 10^2) and a cache would be a
|
|
57
|
+
* second place where ledger truth could go stale.
|
|
58
|
+
*
|
|
59
|
+
* Fail-closed on an UNREADABLE corpus. The shared `loadLedger` deliberately
|
|
60
|
+
* swallows a parse error and returns an empty store, which is indistinguishable
|
|
61
|
+
* from "nothing has been learned yet" — and the write that follows would then
|
|
62
|
+
* overwrite the unreadable file. Reporting that as an empty candidate set is
|
|
63
|
+
* precisely the silent duplicate this whole path exists to prevent, so an
|
|
64
|
+
* existing-but-unparseable ledger throws here instead.
|
|
65
|
+
*
|
|
66
|
+
* A genuinely MISSING ledger is not a failure: there is simply nothing to
|
|
67
|
+
* reuse yet, and blocking the first write of a fresh workspace would be wrong.
|
|
68
|
+
*/
|
|
69
|
+
function normalizeLedgerEntry(entry) {
|
|
70
|
+
if (!isRecord(entry))
|
|
71
|
+
return null;
|
|
72
|
+
const { id, text, triggerPattern, action, status } = entry;
|
|
73
|
+
if (typeof id !== 'string' || id.length === 0)
|
|
74
|
+
return null;
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
text: typeof text === 'string' ? text : '',
|
|
78
|
+
triggerPattern: typeof triggerPattern === 'string' ? triggerPattern : '',
|
|
79
|
+
action: typeof action === 'string' ? action : '',
|
|
80
|
+
status: typeof status === 'string' ? status : '',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function readReusablePrinciples(stateDir) {
|
|
84
|
+
assertLedgerReadable(stateDir);
|
|
85
|
+
const store = loadLedger(stateDir);
|
|
86
|
+
// The ledger is an untrusted document (rc-1/rc-2): validate each entry's
|
|
87
|
+
// fields instead of asserting the shape, so a malformed entry is skipped
|
|
88
|
+
// rather than flowing a non-string into the tokenizer as if it were text.
|
|
89
|
+
const entries = Object.values(store.tree.principles);
|
|
90
|
+
const reusable = [];
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
const normalized = normalizeLedgerEntry(entry);
|
|
93
|
+
if (normalized && isReusablePrincipleStatus(normalized.status))
|
|
94
|
+
reusable.push(normalized);
|
|
95
|
+
}
|
|
96
|
+
return reusable;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Build the reuse shortlist for a candidate, from the canonical ledger.
|
|
100
|
+
*
|
|
101
|
+
* `recommendationKind` is checked with the SAME guard the intake write boundary
|
|
102
|
+
* uses, so a non-principle candidate can never reach the reuse path (SPEC T6 —
|
|
103
|
+
* the #1851 refusal semantics stay exactly as they are; this only makes the
|
|
104
|
+
* reuse path refuse them too).
|
|
105
|
+
*/
|
|
106
|
+
export function buildReuseShortlist(input, stateDir, options = {}) {
|
|
107
|
+
const { recommendationKind, ...shortlistOptions } = options;
|
|
108
|
+
if (recommendationKind !== undefined && !isPrincipleLedgerEligibleKind(recommendationKind)) {
|
|
109
|
+
return {
|
|
110
|
+
candidates: [],
|
|
111
|
+
eligibleCount: 0,
|
|
112
|
+
consideredCount: 0,
|
|
113
|
+
candidateKindEligible: false,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return selectReuseShortlist(input, readReusablePrinciples(stateDir), shortlistOptions);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=reuse-retrieval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse-retrieval.js","sourceRoot":"","sources":["../../../src/runtime-v2/principle-reuse/reuse-retrieval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-917 Slice 1 — deterministic shortlist scoring (pure, no LLM, no I/O).
|
|
3
|
+
*
|
|
4
|
+
* Why a hand-rolled tokenizer: the Principle corpus is Chinese prose, so
|
|
5
|
+
* whitespace tokenization collapses a sentence into one useless token.
|
|
6
|
+
* This module therefore emits CJK character bigrams plus lower-cased latin /
|
|
7
|
+
* numeric word runs. The result is deterministic, dependency-free, and
|
|
8
|
+
* explainable — every score decomposes into named shared terms.
|
|
9
|
+
*
|
|
10
|
+
* Explicit non-goals (SPEC §6): no embedding, no vector store, no semantic
|
|
11
|
+
* search service, no background process, no clock, no randomness.
|
|
12
|
+
*/
|
|
13
|
+
import type { ReuseCandidate, ReuseCandidateInput, ReusablePrinciple, ReuseShortlist, ReuseShortlistOptions } from './reuse-domain.js';
|
|
14
|
+
/**
|
|
15
|
+
* Deterministic, dependency-free tokenizer.
|
|
16
|
+
*
|
|
17
|
+
* - latin / numeric runs → lower-cased word tokens (length >= 2)
|
|
18
|
+
* - CJK runs → character bigrams (single char when the run is length 1)
|
|
19
|
+
* - everything else is a separator
|
|
20
|
+
*
|
|
21
|
+
* The output is sorted, so two equal texts always tokenize identically.
|
|
22
|
+
*/
|
|
23
|
+
export declare function tokenizeForReuse(input: string): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Score one existing Principle against the candidate.
|
|
26
|
+
*
|
|
27
|
+
* Returns `null` when no field pair shares anything — an entry with no
|
|
28
|
+
* evidence is not a proposal.
|
|
29
|
+
*/
|
|
30
|
+
export declare function scoreReuseCandidate(input: ReuseCandidateInput, principle: ReusablePrinciple, maxEvidenceTerms?: number): ReuseCandidate | null;
|
|
31
|
+
/**
|
|
32
|
+
* Build a deterministic, bounded shortlist of existing Principles that may
|
|
33
|
+
* already cover the candidate.
|
|
34
|
+
*
|
|
35
|
+
* Pure: no I/O, no clock, no randomness. Total order is `score` desc then
|
|
36
|
+
* `principleId` asc, so identical input always yields identical output
|
|
37
|
+
* regardless of ledger insertion order.
|
|
38
|
+
*/
|
|
39
|
+
export declare function selectReuseShortlist(input: ReuseCandidateInput, principles: readonly ReusablePrinciple[], options?: ReuseShortlistOptions): ReuseShortlist;
|
|
40
|
+
//# sourceMappingURL=reuse-shortlist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse-shortlist.d.ts","sourceRoot":"","sources":["../../../src/runtime-v2/principle-reuse/reuse-shortlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,mBAAmB,EAGnB,iBAAiB,EAEjB,cAAc,EACd,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AA0C3B;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqCxD;AAQD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,iBAAiB,EAC5B,gBAAgB,GAAE,MAAmC,GACpD,cAAc,GAAG,IAAI,CAoDvB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,mBAAmB,EAC1B,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,OAAO,GAAE,qBAA0B,GAClC,cAAc,CAkBhB"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-917 Slice 1 — deterministic shortlist scoring (pure, no LLM, no I/O).
|
|
3
|
+
*
|
|
4
|
+
* Why a hand-rolled tokenizer: the Principle corpus is Chinese prose, so
|
|
5
|
+
* whitespace tokenization collapses a sentence into one useless token.
|
|
6
|
+
* This module therefore emits CJK character bigrams plus lower-cased latin /
|
|
7
|
+
* numeric word runs. The result is deterministic, dependency-free, and
|
|
8
|
+
* explainable — every score decomposes into named shared terms.
|
|
9
|
+
*
|
|
10
|
+
* Explicit non-goals (SPEC §6): no embedding, no vector store, no semantic
|
|
11
|
+
* search service, no background process, no clock, no randomness.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_TOP_K = 3;
|
|
14
|
+
const DEFAULT_MIN_SCORE = 0.15;
|
|
15
|
+
const DEFAULT_MAX_EVIDENCE_TERMS = 8;
|
|
16
|
+
/**
|
|
17
|
+
* Field-pair weights. Same-field agreement is the strong signal; a
|
|
18
|
+
* cross-field pair catches a candidate that states the claim in `action` where
|
|
19
|
+
* the existing Principle states it in `text`.
|
|
20
|
+
*/
|
|
21
|
+
const FIELD_PAIR_WEIGHTS = [
|
|
22
|
+
{ from: 'text', to: 'text', weight: 3 },
|
|
23
|
+
{ from: 'action', to: 'action', weight: 3 },
|
|
24
|
+
{ from: 'triggerPattern', to: 'triggerPattern', weight: 2 },
|
|
25
|
+
{ from: 'text', to: 'action', weight: 1 },
|
|
26
|
+
{ from: 'action', to: 'text', weight: 1 },
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Minimal Chinese function-word stop list. Kept deliberately small: over-pruning
|
|
30
|
+
* would erase real signal, and the scoring is advisory (a human/AI Owner
|
|
31
|
+
* decides), not authoritative.
|
|
32
|
+
*/
|
|
33
|
+
const CJK_STOP_TERMS = new Set([
|
|
34
|
+
'的', '了', '是', '在', '和', '与', '或', '及', '对', '为', '以', '等', '中',
|
|
35
|
+
'上', '下', '时', '后', '前', '将', '被', '把', '就', '都', '也', '而', '但',
|
|
36
|
+
'并', '不', '有', '无', '一', '个', '这', '那', '其', '之', '所', '使', '由',
|
|
37
|
+
'如', '若', '则', '于', '从', '到', '向', '再', '更', '最', '很', '会', '能',
|
|
38
|
+
'应', '须', '要', '可', '个', '种', '些', '之', '者', '此', '该', '某',
|
|
39
|
+
]);
|
|
40
|
+
const CJK_RANGE = /[㐀-䶿一-鿿]/;
|
|
41
|
+
function isCjk(ch) {
|
|
42
|
+
return CJK_RANGE.test(ch);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Deterministic, dependency-free tokenizer.
|
|
46
|
+
*
|
|
47
|
+
* - latin / numeric runs → lower-cased word tokens (length >= 2)
|
|
48
|
+
* - CJK runs → character bigrams (single char when the run is length 1)
|
|
49
|
+
* - everything else is a separator
|
|
50
|
+
*
|
|
51
|
+
* The output is sorted, so two equal texts always tokenize identically.
|
|
52
|
+
*/
|
|
53
|
+
export function tokenizeForReuse(input) {
|
|
54
|
+
const normalized = input.normalize('NFKC').toLowerCase();
|
|
55
|
+
const tokens = [];
|
|
56
|
+
let latinRun = '';
|
|
57
|
+
let cjkRun = '';
|
|
58
|
+
const flushLatin = () => {
|
|
59
|
+
if (latinRun.length >= 2)
|
|
60
|
+
tokens.push(latinRun);
|
|
61
|
+
latinRun = '';
|
|
62
|
+
};
|
|
63
|
+
const flushCjk = () => {
|
|
64
|
+
if (cjkRun.length === 1) {
|
|
65
|
+
tokens.push(cjkRun);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
for (let i = 0; i + 1 < cjkRun.length; i++)
|
|
69
|
+
tokens.push(cjkRun.slice(i, i + 2));
|
|
70
|
+
}
|
|
71
|
+
cjkRun = '';
|
|
72
|
+
};
|
|
73
|
+
for (const ch of normalized) {
|
|
74
|
+
if (isCjk(ch)) {
|
|
75
|
+
flushLatin();
|
|
76
|
+
cjkRun += ch;
|
|
77
|
+
}
|
|
78
|
+
else if (/[a-z0-9]/.test(ch)) {
|
|
79
|
+
flushCjk();
|
|
80
|
+
latinRun += ch;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
flushLatin();
|
|
84
|
+
flushCjk();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
flushLatin();
|
|
88
|
+
flushCjk();
|
|
89
|
+
const deduped = new Set(tokens);
|
|
90
|
+
for (const stop of CJK_STOP_TERMS)
|
|
91
|
+
deduped.delete(stop);
|
|
92
|
+
return [...deduped].sort();
|
|
93
|
+
}
|
|
94
|
+
function intersect(a, b) {
|
|
95
|
+
const shared = [];
|
|
96
|
+
for (const term of a)
|
|
97
|
+
if (b.has(term))
|
|
98
|
+
shared.push(term);
|
|
99
|
+
return shared.sort();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Score one existing Principle against the candidate.
|
|
103
|
+
*
|
|
104
|
+
* Returns `null` when no field pair shares anything — an entry with no
|
|
105
|
+
* evidence is not a proposal.
|
|
106
|
+
*/
|
|
107
|
+
export function scoreReuseCandidate(input, principle, maxEvidenceTerms = DEFAULT_MAX_EVIDENCE_TERMS) {
|
|
108
|
+
const inputTerms = {
|
|
109
|
+
text: new Set(tokenizeForReuse(input.text)),
|
|
110
|
+
triggerPattern: new Set(tokenizeForReuse(input.triggerPattern)),
|
|
111
|
+
action: new Set(tokenizeForReuse(input.action)),
|
|
112
|
+
};
|
|
113
|
+
const principleTerms = {
|
|
114
|
+
text: new Set(tokenizeForReuse(principle.text)),
|
|
115
|
+
triggerPattern: new Set(tokenizeForReuse(principle.triggerPattern)),
|
|
116
|
+
action: new Set(tokenizeForReuse(principle.action)),
|
|
117
|
+
};
|
|
118
|
+
const evidence = [];
|
|
119
|
+
let weighted = 0;
|
|
120
|
+
let totalWeight = 0;
|
|
121
|
+
for (const pair of FIELD_PAIR_WEIGHTS) {
|
|
122
|
+
const from = inputTerms[pair.from];
|
|
123
|
+
const to = principleTerms[pair.to];
|
|
124
|
+
const smaller = Math.min(from.size, to.size);
|
|
125
|
+
// An empty side can never produce evidence.
|
|
126
|
+
if (smaller === 0)
|
|
127
|
+
continue;
|
|
128
|
+
totalWeight += pair.weight;
|
|
129
|
+
const shared = intersect(from, to);
|
|
130
|
+
if (shared.length === 0)
|
|
131
|
+
continue;
|
|
132
|
+
const coverage = shared.length / smaller;
|
|
133
|
+
weighted += pair.weight * coverage;
|
|
134
|
+
const field = pair.from === pair.to ? pair.from : `${pair.from}~${pair.to}`;
|
|
135
|
+
evidence.push({
|
|
136
|
+
field,
|
|
137
|
+
sharedTerms: shared.slice(0, maxEvidenceTerms),
|
|
138
|
+
coverage,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (evidence.length === 0 || totalWeight === 0)
|
|
142
|
+
return null;
|
|
143
|
+
const score = weighted / totalWeight;
|
|
144
|
+
const [top] = evidence
|
|
145
|
+
.slice()
|
|
146
|
+
.sort((a, b) => b.coverage - a.coverage || a.field.localeCompare(b.field));
|
|
147
|
+
const reason = top
|
|
148
|
+
? `shares ${top.sharedTerms.slice(0, 5).join('、')} on ${top.field} (coverage ${(top.coverage * 100).toFixed(0)}%)`
|
|
149
|
+
: 'no field overlap';
|
|
150
|
+
return {
|
|
151
|
+
principleId: principle.id,
|
|
152
|
+
principleText: principle.text,
|
|
153
|
+
score,
|
|
154
|
+
evidence,
|
|
155
|
+
similarityReason: reason,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Build a deterministic, bounded shortlist of existing Principles that may
|
|
160
|
+
* already cover the candidate.
|
|
161
|
+
*
|
|
162
|
+
* Pure: no I/O, no clock, no randomness. Total order is `score` desc then
|
|
163
|
+
* `principleId` asc, so identical input always yields identical output
|
|
164
|
+
* regardless of ledger insertion order.
|
|
165
|
+
*/
|
|
166
|
+
export function selectReuseShortlist(input, principles, options = {}) {
|
|
167
|
+
const topK = options.topK ?? DEFAULT_TOP_K;
|
|
168
|
+
const minScore = options.minScore ?? DEFAULT_MIN_SCORE;
|
|
169
|
+
const maxEvidenceTerms = options.maxEvidenceTerms ?? DEFAULT_MAX_EVIDENCE_TERMS;
|
|
170
|
+
const scored = [];
|
|
171
|
+
for (const principle of principles) {
|
|
172
|
+
const candidate = scoreReuseCandidate(input, principle, maxEvidenceTerms);
|
|
173
|
+
if (candidate && candidate.score >= minScore)
|
|
174
|
+
scored.push(candidate);
|
|
175
|
+
}
|
|
176
|
+
scored.sort((a, b) => b.score - a.score || a.principleId.localeCompare(b.principleId));
|
|
177
|
+
return {
|
|
178
|
+
candidates: scored.slice(0, topK),
|
|
179
|
+
eligibleCount: principles.length,
|
|
180
|
+
consideredCount: scored.length,
|
|
181
|
+
candidateKindEligible: true,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=reuse-shortlist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reuse-shortlist.js","sourceRoot":"","sources":["../../../src/runtime-v2/principle-reuse/reuse-shortlist.ts"],"names":[],"mappings":"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"}
|
|
@@ -58,6 +58,13 @@ export interface PainDiagnosisStore {
|
|
|
58
58
|
recordPainDiagnosis(input: PainDiagnosisWriteInput): Promise<PainDiagnosisRecord>;
|
|
59
59
|
/** All diagnosis rows for a pain, oldest first. */
|
|
60
60
|
getDiagnosesByPainId(painId: string): Promise<PainDiagnosisRecord[]>;
|
|
61
|
+
/**
|
|
62
|
+
* All diagnosis rows produced by one diagnostician task, oldest first
|
|
63
|
+
* (PRI-917 PR3B Phase 2: the candidate → pain bridge for reuse evidence —
|
|
64
|
+
* a candidate knows only its task; its Pain resolves through this query).
|
|
65
|
+
* Uses the existing idx_pain_diagnoses_task_id index; no schema change.
|
|
66
|
+
*/
|
|
67
|
+
getDiagnosesByTaskId(taskId: string): Promise<PainDiagnosisRecord[]>;
|
|
61
68
|
}
|
|
62
69
|
export declare function isRootCauseCategory(value: unknown): value is RootCauseCategory;
|
|
63
70
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pain-diagnosis-store.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAEtF,8FAA8F;AAC9F,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kDAAkD;AAClD,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mFAAmF;IACnF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gEAAgE;AAChE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAElF,mDAAmD;IACnD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;CACtE;AAID,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAKlF;AAED,oEAAoE;AACpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhF"}
|
|
1
|
+
{"version":3,"file":"pain-diagnosis-store.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAEtF,8FAA8F;AAC9F,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kDAAkD;AAClD,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mFAAmF;IACnF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,gEAAgE;AAChE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAElF,mDAAmD;IACnD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAErE;;;;;OAKG;IACH,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;CACtE;AAID,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAKlF;AAED,oEAAoE;AACpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pain-diagnosis-store.js","sourceRoot":"","sources":["../../../../src/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"pain-diagnosis-store.js","sourceRoot":"","sources":["../../../../src/runtime-v2/store/pain-diagnosis/pain-diagnosis-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgEH,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;AAErG,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,KAAK,MAAM,QAAQ,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAU,EAAE,CAAC;QAC9E,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,QAAQ,IAAI,CAAC;YAAE,OAAO,QAAQ,CAAC;IAC7D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,WAAmB;IACtE,OAAO,GAAG,MAAM,KAAK,WAAW,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -5,5 +5,6 @@ export declare class SqlitePainDiagnosisStore implements PainDiagnosisStore {
|
|
|
5
5
|
constructor(connection: SqliteConnection);
|
|
6
6
|
recordPainDiagnosis(input: PainDiagnosisWriteInput): Promise<PainDiagnosisRecord>;
|
|
7
7
|
getDiagnosesByPainId(painId: string): Promise<PainDiagnosisRecord[]>;
|
|
8
|
+
getDiagnosesByTaskId(taskId: string): Promise<PainDiagnosisRecord[]>;
|
|
8
9
|
}
|
|
9
10
|
//# sourceMappingURL=sqlite-pain-diagnosis-store.d.ts.map
|