@principles/core 1.169.0 → 1.170.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/pain-signal.d.ts +11 -71
- package/dist/pain-signal.d.ts.map +1 -1
- package/dist/pain-signal.js +10 -120
- package/dist/pain-signal.js.map +1 -1
- package/dist/principle-tree-ledger.d.ts +4 -87
- package/dist/principle-tree-ledger.d.ts.map +1 -1
- package/dist/principle-tree-ledger.js +51 -148
- package/dist/principle-tree-ledger.js.map +1 -1
- package/dist/runtime-v2/__tests__/architecture-regression.test.js +69 -4
- package/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/dist/runtime-v2/__tests__/barrel-io-cleanup.test.d.ts +12 -0
- package/dist/runtime-v2/__tests__/barrel-io-cleanup.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/barrel-io-cleanup.test.js +46 -0
- package/dist/runtime-v2/__tests__/barrel-io-cleanup.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/io-deletion.test.d.ts +12 -0
- package/dist/runtime-v2/__tests__/io-deletion.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/io-deletion.test.js +92 -0
- package/dist/runtime-v2/__tests__/io-deletion.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/ledger-codec.test.d.ts +2 -0
- package/dist/runtime-v2/__tests__/ledger-codec.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/ledger-codec.test.js +133 -0
- package/dist/runtime-v2/__tests__/ledger-codec.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/ledger-store.test.d.ts +2 -0
- package/dist/runtime-v2/__tests__/ledger-store.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/ledger-store.test.js +65 -0
- package/dist/runtime-v2/__tests__/ledger-store.test.js.map +1 -0
- package/dist/runtime-v2/__tests__/pain-signal-unification.test.d.ts +2 -0
- package/dist/runtime-v2/__tests__/pain-signal-unification.test.d.ts.map +1 -0
- package/dist/runtime-v2/__tests__/pain-signal-unification.test.js +150 -0
- package/dist/runtime-v2/__tests__/pain-signal-unification.test.js.map +1 -0
- package/dist/runtime-v2/index.d.ts +1 -2
- package/dist/runtime-v2/index.d.ts.map +1 -1
- package/dist/runtime-v2/index.js +4 -2
- package/dist/runtime-v2/index.js.map +1 -1
- package/dist/runtime-v2/principle-tree/ledger-codec.d.ts +30 -0
- package/dist/runtime-v2/principle-tree/ledger-codec.d.ts.map +1 -0
- package/dist/runtime-v2/principle-tree/ledger-codec.js +154 -0
- package/dist/runtime-v2/principle-tree/ledger-codec.js.map +1 -0
- package/dist/runtime-v2/types/index.d.ts +2 -0
- package/dist/runtime-v2/types/index.d.ts.map +1 -1
- package/dist/runtime-v2/types/index.js +1 -0
- package/dist/runtime-v2/types/index.js.map +1 -1
- package/dist/runtime-v2/types/ledger-store.d.ts +101 -0
- package/dist/runtime-v2/types/ledger-store.d.ts.map +1 -0
- package/dist/runtime-v2/types/ledger-store.js +15 -0
- package/dist/runtime-v2/types/ledger-store.js.map +1 -0
- package/dist/runtime-v2/types/pain-signal.d.ts +5 -3
- package/dist/runtime-v2/types/pain-signal.d.ts.map +1 -1
- package/dist/runtime-v2/types/pain-signal.js +23 -3
- package/dist/runtime-v2/types/pain-signal.js.map +1 -1
- package/package.json +4 -4
- package/dist/io.d.ts +0 -35
- package/dist/io.d.ts.map +0 -1
- package/dist/io.js +0 -95
- package/dist/io.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ export { PainSignalAdapter } from './pain-signal-adapter.js';
|
|
|
16
16
|
export { TelemetryEventSchema, validateTelemetryEvent } from './telemetry-event.js';
|
|
17
17
|
export type { TelemetryEvent, TelemetryEventValidationResult, TelemetryEventType } from './telemetry-event.js';
|
|
18
18
|
export { PrincipleInjector, DefaultPrincipleInjector, InjectionContext } from './principle-injector.js';
|
|
19
|
-
export { atomicWriteFileSync } from './io.js';
|
|
20
19
|
export { buildAttitudeDirective, detectCorrectionCue, extractMessageContent, isMinimalTrigger, truncateInjectionToBudget, } from './prompt-builder/index.js';
|
|
21
20
|
export type { PromptInjectionPart, SizeGuardOptions } from './prompt-builder/index.js';
|
|
22
21
|
export { matchEmpathyKeywords, createDefaultKeywordStore, applyKeywordUpdates, shouldTriggerOptimization, getKeywordStoreSummary, EMPATHY_SEED_KEYWORDS, DEFAULT_EMPATHY_KEYWORD_CONFIG, scoreToSeverity, severityToPenalty, normalizeSeverity, } from './prompt-builder/index.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACtG,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/G,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGxG,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -16,8 +16,6 @@ export { PainSignalSchema, validatePainSignal, deriveSeverity, PainSeverity } fr
|
|
|
16
16
|
export { TelemetryEventSchema, validateTelemetryEvent } from './telemetry-event.js';
|
|
17
17
|
// PrincipleInjector interface and DefaultPrincipleInjector
|
|
18
18
|
export { DefaultPrincipleInjector } from './principle-injector.js';
|
|
19
|
-
// I/O utilities (D-03: atomicWriteFileSync for crash-safe writes)
|
|
20
|
-
export { atomicWriteFileSync } from './io.js';
|
|
21
19
|
// Prompt builder primitives — pure functions extracted from openclaw-plugin prompt hook (PRI-75)
|
|
22
20
|
export { buildAttitudeDirective, detectCorrectionCue, extractMessageContent, isMinimalTrigger, truncateInjectionToBudget, } from './prompt-builder/index.js';
|
|
23
21
|
// Prompt builder — empathy keyword matching (PRI-81 Phase A)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,mCAAmC;AACnC,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAMtG,wBAAwB;AACxB,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAGpF,2DAA2D;AAC3D,OAAO,EAAqB,wBAAwB,EAAoB,MAAM,yBAAyB,CAAC;AAExG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/pain-signal.d.ts
CHANGED
|
@@ -1,76 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Pain signal schema — re-exported from runtime-v2/types/pain-signal.ts.
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* cross-workspace evolution and multi-domain support.
|
|
4
|
+
* This file exists for backward compatibility with imports from
|
|
5
|
+
* @principles/core (top-level barrel). The canonical definition
|
|
6
|
+
* lives in runtime-v2/types/pain-signal.ts (PRI-443).
|
|
8
7
|
*
|
|
9
|
-
*
|
|
8
|
+
* The unified schema merges the stricter validations from both versions:
|
|
9
|
+
* - ISO 8601 timestamp format check
|
|
10
|
+
* - Context size limit (10KB)
|
|
11
|
+
* - version field with default
|
|
12
|
+
* - isStringRecord type guard (no `as` bypass)
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* Severity levels derived from pain score thresholds.
|
|
14
|
-
* - low: 0-39 (minor issue, informational)
|
|
15
|
-
* - medium: 40-69 (moderate error)
|
|
16
|
-
* - high: 70-89 (severe violation)
|
|
17
|
-
* - critical: 90-100 (systemic failure, spiral detected)
|
|
18
|
-
*/
|
|
19
|
-
export declare const PainSeverity: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"medium">, import("@sinclair/typebox").TLiteral<"high">, import("@sinclair/typebox").TLiteral<"critical">]>;
|
|
20
|
-
export type PainSeverity = Static<typeof PainSeverity>;
|
|
21
|
-
/**
|
|
22
|
-
* TypeBox schema for a universal pain signal.
|
|
23
|
-
*
|
|
24
|
-
* Every signal MUST have: source, score, timestamp, reason, sessionId,
|
|
25
|
-
* agentId, traceId, triggerTextPreview. Optional fields (domain, severity,
|
|
26
|
-
* context) default during validation.
|
|
27
|
-
*/
|
|
28
|
-
export declare const PainSignalSchema: import("@sinclair/typebox").TObject<{
|
|
29
|
-
/** What triggered this pain signal (e.g., 'tool_failure', 'human_intervention') */
|
|
30
|
-
source: import("@sinclair/typebox").TString;
|
|
31
|
-
/** Pain score 0-100 */
|
|
32
|
-
score: import("@sinclair/typebox").TNumber;
|
|
33
|
-
/** ISO 8601 timestamp */
|
|
34
|
-
timestamp: import("@sinclair/typebox").TString;
|
|
35
|
-
/** Human-readable reason / error description */
|
|
36
|
-
reason: import("@sinclair/typebox").TString;
|
|
37
|
-
/** Session ID — identifies which conversation this happened in */
|
|
38
|
-
sessionId: import("@sinclair/typebox").TString;
|
|
39
|
-
/** Agent ID — identifies which agent (main, builder, diagnostician, etc.) */
|
|
40
|
-
agentId: import("@sinclair/typebox").TString;
|
|
41
|
-
/** Correlation trace ID for linking events across the pipeline */
|
|
42
|
-
traceId: import("@sinclair/typebox").TString;
|
|
43
|
-
/** Preview of the text that triggered this pain */
|
|
44
|
-
triggerTextPreview: import("@sinclair/typebox").TString;
|
|
45
|
-
/** Schema version for forward compatibility (e.g., '0.1.0') */
|
|
46
|
-
version: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
47
|
-
/** Domain context (e.g., 'coding', 'writing', 'analysis') */
|
|
48
|
-
domain: import("@sinclair/typebox").TString;
|
|
49
|
-
/** Severity level derived from score */
|
|
50
|
-
severity: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"low">, import("@sinclair/typebox").TLiteral<"medium">, import("@sinclair/typebox").TLiteral<"high">, import("@sinclair/typebox").TLiteral<"critical">]>;
|
|
51
|
-
/** Additional structured context payload */
|
|
52
|
-
context: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
|
|
53
|
-
}>;
|
|
54
|
-
export type PainSignal = Static<typeof PainSignalSchema>;
|
|
55
|
-
/**
|
|
56
|
-
* Derives severity from a numeric pain score.
|
|
57
|
-
*/
|
|
58
|
-
export declare function deriveSeverity(score: number): PainSeverity;
|
|
59
|
-
export interface PainSignalValidationResult {
|
|
60
|
-
valid: boolean;
|
|
61
|
-
errors: string[];
|
|
62
|
-
signal?: PainSignal;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Validates an arbitrary object against the PainSignal schema.
|
|
66
|
-
*
|
|
67
|
-
* Returns a structured result with:
|
|
68
|
-
* - `valid`: whether the input conforms to the schema
|
|
69
|
-
* - `errors`: human-readable list of validation failures
|
|
70
|
-
* - `signal`: the typed signal (only present when valid)
|
|
71
|
-
*
|
|
72
|
-
* Missing optional fields (domain, severity, context, version) are filled with defaults
|
|
73
|
-
* before validation so callers get a fully-formed signal back.
|
|
74
|
-
*/
|
|
75
|
-
export declare function validatePainSignal(input: unknown): PainSignalValidationResult;
|
|
14
|
+
export { PainSeverity, PainSignalSchema, deriveSeverity, validatePainSignal, } from './runtime-v2/types/pain-signal.js';
|
|
15
|
+
export type { PainSignal, PainSignalValidationResult, } from './runtime-v2/types/pain-signal.js';
|
|
76
16
|
//# sourceMappingURL=pain-signal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pain-signal.d.ts","sourceRoot":"","sources":["../src/pain-signal.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pain-signal.d.ts","sourceRoot":"","sources":["../src/pain-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACnB,MAAM,mCAAmC,CAAC;AAE3C,YAAY,EACV,UAAU,EACV,0BAA0B,GAC3B,MAAM,mCAAmC,CAAC"}
|
package/dist/pain-signal.js
CHANGED
|
@@ -1,125 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Pain signal schema — re-exported from runtime-v2/types/pain-signal.ts.
|
|
3
3
|
*
|
|
4
|
-
* This
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* cross-workspace evolution and multi-domain support.
|
|
4
|
+
* This file exists for backward compatibility with imports from
|
|
5
|
+
* @principles/core (top-level barrel). The canonical definition
|
|
6
|
+
* lives in runtime-v2/types/pain-signal.ts (PRI-443).
|
|
8
7
|
*
|
|
9
|
-
*
|
|
8
|
+
* The unified schema merges the stricter validations from both versions:
|
|
9
|
+
* - ISO 8601 timestamp format check
|
|
10
|
+
* - Context size limit (10KB)
|
|
11
|
+
* - version field with default
|
|
12
|
+
* - isStringRecord type guard (no `as` bypass)
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
import { Value } from '@sinclair/typebox/value';
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// PainSignal Schema
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
/**
|
|
17
|
-
* Severity levels derived from pain score thresholds.
|
|
18
|
-
* - low: 0-39 (minor issue, informational)
|
|
19
|
-
* - medium: 40-69 (moderate error)
|
|
20
|
-
* - high: 70-89 (severe violation)
|
|
21
|
-
* - critical: 90-100 (systemic failure, spiral detected)
|
|
22
|
-
*/
|
|
23
|
-
export const PainSeverity = Type.Union([
|
|
24
|
-
Type.Literal('low'),
|
|
25
|
-
Type.Literal('medium'),
|
|
26
|
-
Type.Literal('high'),
|
|
27
|
-
Type.Literal('critical'),
|
|
28
|
-
]);
|
|
29
|
-
/**
|
|
30
|
-
* TypeBox schema for a universal pain signal.
|
|
31
|
-
*
|
|
32
|
-
* Every signal MUST have: source, score, timestamp, reason, sessionId,
|
|
33
|
-
* agentId, traceId, triggerTextPreview. Optional fields (domain, severity,
|
|
34
|
-
* context) default during validation.
|
|
35
|
-
*/
|
|
36
|
-
export const PainSignalSchema = Type.Object({
|
|
37
|
-
/** What triggered this pain signal (e.g., 'tool_failure', 'human_intervention') */
|
|
38
|
-
source: Type.String({ minLength: 1 }),
|
|
39
|
-
/** Pain score 0-100 */
|
|
40
|
-
score: Type.Number({ minimum: 0, maximum: 100 }),
|
|
41
|
-
/** ISO 8601 timestamp */
|
|
42
|
-
timestamp: Type.String({ minLength: 1 }),
|
|
43
|
-
/** Human-readable reason / error description */
|
|
44
|
-
reason: Type.String({ minLength: 1 }),
|
|
45
|
-
/** Session ID — identifies which conversation this happened in */
|
|
46
|
-
sessionId: Type.String({ minLength: 1 }),
|
|
47
|
-
/** Agent ID — identifies which agent (main, builder, diagnostician, etc.) */
|
|
48
|
-
agentId: Type.String({ minLength: 1 }),
|
|
49
|
-
/** Correlation trace ID for linking events across the pipeline */
|
|
50
|
-
traceId: Type.String({ minLength: 1 }),
|
|
51
|
-
/** Preview of the text that triggered this pain */
|
|
52
|
-
triggerTextPreview: Type.String(),
|
|
53
|
-
/** Schema version for forward compatibility (e.g., '0.1.0') */
|
|
54
|
-
version: Type.Optional(Type.String({ default: '0.1.0' })),
|
|
55
|
-
/** Domain context (e.g., 'coding', 'writing', 'analysis') */
|
|
56
|
-
domain: Type.String({ default: 'coding' }),
|
|
57
|
-
/** Severity level derived from score */
|
|
58
|
-
severity: PainSeverity,
|
|
59
|
-
/** Additional structured context payload */
|
|
60
|
-
context: Type.Record(Type.String(), Type.Unknown()),
|
|
61
|
-
});
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
// Default Derivation
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
/**
|
|
66
|
-
* Derives severity from a numeric pain score.
|
|
67
|
-
*/
|
|
68
|
-
export function deriveSeverity(score) {
|
|
69
|
-
if (score >= 90)
|
|
70
|
-
return 'critical';
|
|
71
|
-
if (score >= 70)
|
|
72
|
-
return 'high';
|
|
73
|
-
if (score >= 40)
|
|
74
|
-
return 'medium';
|
|
75
|
-
return 'low';
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Validates an arbitrary object against the PainSignal schema.
|
|
79
|
-
*
|
|
80
|
-
* Returns a structured result with:
|
|
81
|
-
* - `valid`: whether the input conforms to the schema
|
|
82
|
-
* - `errors`: human-readable list of validation failures
|
|
83
|
-
* - `signal`: the typed signal (only present when valid)
|
|
84
|
-
*
|
|
85
|
-
* Missing optional fields (domain, severity, context, version) are filled with defaults
|
|
86
|
-
* before validation so callers get a fully-formed signal back.
|
|
87
|
-
*/
|
|
88
|
-
export function validatePainSignal(input) {
|
|
89
|
-
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
90
|
-
return { valid: false, errors: ['Input must be a non-null object'] };
|
|
91
|
-
}
|
|
92
|
-
const raw = input;
|
|
93
|
-
// Apply defaults for optional fields before validation
|
|
94
|
-
const hydrated = {
|
|
95
|
-
...raw,
|
|
96
|
-
domain: raw.domain ?? 'coding',
|
|
97
|
-
version: raw.version ?? '0.1.0',
|
|
98
|
-
severity: raw.severity ?? deriveSeverity(typeof raw.score === 'number' ? raw.score : 0),
|
|
99
|
-
context: raw.context ?? {},
|
|
100
|
-
};
|
|
101
|
-
// Security: enforce context size limit to prevent memory exhaustion
|
|
102
|
-
const MAX_CONTEXT_SIZE = 10_000;
|
|
103
|
-
if (JSON.stringify(hydrated.context).length > MAX_CONTEXT_SIZE) {
|
|
104
|
-
return { valid: false, errors: ['Context object exceeds maximum size (10KB)'] };
|
|
105
|
-
}
|
|
106
|
-
// Validate ISO 8601 timestamp format
|
|
107
|
-
if (typeof hydrated.timestamp === 'string' &&
|
|
108
|
-
isNaN(Date.parse(hydrated.timestamp))) {
|
|
109
|
-
return { valid: false, errors: ['timestamp must be a valid ISO 8601 date string'] };
|
|
110
|
-
}
|
|
111
|
-
// Collect TypeBox errors using Decode (strict, not Cast which coerces)
|
|
112
|
-
const errors = [...Value.Errors(PainSignalSchema, hydrated)];
|
|
113
|
-
if (errors.length > 0) {
|
|
114
|
-
return {
|
|
115
|
-
valid: false,
|
|
116
|
-
errors: errors.map((e) => `${e.path ? `${e.path}: ` : ''}${e.message}`),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
valid: true,
|
|
121
|
-
errors: [],
|
|
122
|
-
signal: Value.Cast(PainSignalSchema, hydrated),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
14
|
+
export { PainSeverity, PainSignalSchema, deriveSeverity, validatePainSignal, } from './runtime-v2/types/pain-signal.js';
|
|
125
15
|
//# sourceMappingURL=pain-signal.js.map
|
package/dist/pain-signal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pain-signal.js","sourceRoot":"","sources":["../src/pain-signal.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pain-signal.js","sourceRoot":"","sources":["../src/pain-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACnB,MAAM,mCAAmC,CAAC"}
|
|
@@ -10,93 +10,10 @@
|
|
|
10
10
|
* M8 key insight: ledger operations are single-process. No cross-process
|
|
11
11
|
* locking needed for pd-cli usage. The file write is atomic (rename).
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export type
|
|
16
|
-
export
|
|
17
|
-
export interface Principle {
|
|
18
|
-
id: string;
|
|
19
|
-
version: number;
|
|
20
|
-
text: string;
|
|
21
|
-
triggerPattern: string;
|
|
22
|
-
action: string;
|
|
23
|
-
status: PrincipleStatus;
|
|
24
|
-
priority: PrinciplePriority;
|
|
25
|
-
scope: PrincipleScope;
|
|
26
|
-
evaluability: PrincipleEvaluability;
|
|
27
|
-
valueScore: number;
|
|
28
|
-
adherenceRate: number;
|
|
29
|
-
painPreventedCount: number;
|
|
30
|
-
derivedFromPainIds: string[];
|
|
31
|
-
ruleIds: string[];
|
|
32
|
-
conflictsWithPrincipleIds: string[];
|
|
33
|
-
createdAt: string;
|
|
34
|
-
updatedAt: string;
|
|
35
|
-
}
|
|
36
|
-
export interface Rule {
|
|
37
|
-
id: string;
|
|
38
|
-
principleId: string;
|
|
39
|
-
ruleIds: string[];
|
|
40
|
-
implementationIds: string[];
|
|
41
|
-
type?: string;
|
|
42
|
-
status?: string;
|
|
43
|
-
lifecycleState?: string;
|
|
44
|
-
createdAt?: string;
|
|
45
|
-
updatedAt?: string;
|
|
46
|
-
}
|
|
47
|
-
export interface Implementation {
|
|
48
|
-
id: string;
|
|
49
|
-
ruleId: string;
|
|
50
|
-
type?: string;
|
|
51
|
-
lifecycleState?: string;
|
|
52
|
-
[key: string]: unknown;
|
|
53
|
-
}
|
|
54
|
-
export interface PrincipleValueMetrics {
|
|
55
|
-
principleId: string;
|
|
56
|
-
painPreventedCount?: number;
|
|
57
|
-
lastPainPreventedAt?: string;
|
|
58
|
-
avgPainSeverityPrevented?: number;
|
|
59
|
-
totalOpportunities?: number;
|
|
60
|
-
adheredCount?: number;
|
|
61
|
-
violatedCount?: number;
|
|
62
|
-
implementationCost?: number;
|
|
63
|
-
benefitScore?: number;
|
|
64
|
-
calculatedAt?: string;
|
|
65
|
-
}
|
|
66
|
-
export interface LedgerPrinciple extends Principle {
|
|
67
|
-
suggestedRules?: string[];
|
|
68
|
-
lastTriggeredAt?: string;
|
|
69
|
-
}
|
|
70
|
-
export interface LedgerRule extends Rule {
|
|
71
|
-
implementationIds: string[];
|
|
72
|
-
}
|
|
73
|
-
export interface LedgerTreeStore {
|
|
74
|
-
principles: Record<string, LedgerPrinciple>;
|
|
75
|
-
rules: Record<string, LedgerRule>;
|
|
76
|
-
implementations: Record<string, Implementation>;
|
|
77
|
-
metrics: Record<string, PrincipleValueMetrics>;
|
|
78
|
-
lastUpdated: string;
|
|
79
|
-
}
|
|
80
|
-
export interface LegacyPrincipleTrainingState {
|
|
81
|
-
principleId: string;
|
|
82
|
-
evaluability: 'deterministic' | 'weak_heuristic' | 'manual_only';
|
|
83
|
-
applicableOpportunityCount: number;
|
|
84
|
-
observedViolationCount: number;
|
|
85
|
-
complianceRate: number;
|
|
86
|
-
violationTrend: number;
|
|
87
|
-
generatedSampleCount: number;
|
|
88
|
-
approvedSampleCount: number;
|
|
89
|
-
includedTrainRunIds: string[];
|
|
90
|
-
deployedCheckpointIds: string[];
|
|
91
|
-
lastEvalScore?: number;
|
|
92
|
-
internalizationStatus: 'prompt_only' | 'needs_training' | 'in_training' | 'deployed_pending_eval' | 'internalized' | 'regressed';
|
|
93
|
-
}
|
|
94
|
-
export type LegacyPrincipleTrainingStore = Record<string, LegacyPrincipleTrainingState>;
|
|
95
|
-
export interface HybridLedgerStore {
|
|
96
|
-
trainingStore: LegacyPrincipleTrainingStore;
|
|
97
|
-
tree: LedgerTreeStore;
|
|
98
|
-
}
|
|
99
|
-
export declare const TREE_NAMESPACE = "_tree";
|
|
13
|
+
import type { Principle, Rule, Implementation, PrincipleValueMetrics, LedgerPrinciple, LedgerRule, LedgerTreeStore, LegacyPrincipleTrainingState, LegacyPrincipleTrainingStore, HybridLedgerStore } from './runtime-v2/types/ledger-store.js';
|
|
14
|
+
import { TREE_NAMESPACE } from './runtime-v2/types/ledger-store.js';
|
|
15
|
+
export type { Principle, Rule, Implementation, PrincipleValueMetrics, LedgerPrinciple, LedgerRule, LedgerTreeStore, LegacyPrincipleTrainingState, LegacyPrincipleTrainingStore, HybridLedgerStore, };
|
|
16
|
+
export { TREE_NAMESPACE };
|
|
100
17
|
export declare function loadLedger(stateDir: string): HybridLedgerStore;
|
|
101
18
|
export declare function saveLedger(stateDir: string, store: HybridLedgerStore): void;
|
|
102
19
|
export declare function addPrincipleToLedger(stateDir: string, principle: LedgerPrinciple): LedgerPrinciple;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principle-tree-ledger.d.ts","sourceRoot":"","sources":["../src/principle-tree-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"principle-tree-ledger.d.ts","sourceRoot":"","sources":["../src/principle-tree-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EACV,SAAS,EACT,IAAI,EACJ,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,eAAe,EACf,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAYpE,YAAY,EACV,SAAS,EACT,IAAI,EACJ,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,eAAe,EACf,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,GAClB,CAAC;AACF,OAAO,EAAE,cAAc,EAAE,CAAC;AAkG1B,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAE9D;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAK3E;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,eAAe,CAMlG;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,eAAe,CAiBzH;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,qBAAqB,CAMxI;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE"}
|
|
@@ -12,148 +12,64 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import * as fs from 'fs';
|
|
14
14
|
import * as path from 'path';
|
|
15
|
-
import {
|
|
15
|
+
import { TREE_NAMESPACE } from './runtime-v2/types/ledger-store.js';
|
|
16
|
+
// PRI-443: Pure parse/serialize functions extracted to codec module
|
|
17
|
+
import { uniqueStrings, createEmptyTree, parseHybridLedger, serializeLedger, } from './runtime-v2/principle-tree/ledger-codec.js';
|
|
18
|
+
export { TREE_NAMESPACE };
|
|
16
19
|
const PRINCIPLE_TRAINING_FILE = 'principle_training_state.json';
|
|
17
20
|
// ---------------------------------------------------------------------------
|
|
18
|
-
//
|
|
21
|
+
// Atomic file write (inlined PRI-443 Phase 4)
|
|
19
22
|
// ---------------------------------------------------------------------------
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
continue;
|
|
60
|
-
result[principleId] = {
|
|
61
|
-
principleId,
|
|
62
|
-
evaluability: VALID_EVALUABILITIES.includes(candidate.evaluability)
|
|
63
|
-
? candidate.evaluability
|
|
64
|
-
: 'manual_only',
|
|
65
|
-
applicableOpportunityCount: clampInt(candidate.applicableOpportunityCount, { min: 0, max: Infinity, fallback: 0 }),
|
|
66
|
-
observedViolationCount: clampInt(candidate.observedViolationCount, { min: 0, max: Infinity, fallback: 0 }),
|
|
67
|
-
complianceRate: clampFloat(candidate.complianceRate, { min: 0, max: 1, fallback: 0 }),
|
|
68
|
-
violationTrend: clampFloat(candidate.violationTrend, { min: -1, max: 1, fallback: 0 }),
|
|
69
|
-
generatedSampleCount: clampInt(candidate.generatedSampleCount, { min: 0, max: Infinity, fallback: 0 }),
|
|
70
|
-
approvedSampleCount: clampInt(candidate.approvedSampleCount, { min: 0, max: Infinity, fallback: 0 }),
|
|
71
|
-
includedTrainRunIds: stringArray(candidate.includedTrainRunIds),
|
|
72
|
-
deployedCheckpointIds: stringArray(candidate.deployedCheckpointIds),
|
|
73
|
-
lastEvalScore: typeof candidate.lastEvalScore === 'number' && Number.isFinite(candidate.lastEvalScore)
|
|
74
|
-
? clampFloat(candidate.lastEvalScore, { min: 0, max: 1, fallback: 0 }) : undefined,
|
|
75
|
-
internalizationStatus: VALID_INTERNALIZATION_STATUSES.includes(candidate.internalizationStatus)
|
|
76
|
-
? candidate.internalizationStatus
|
|
77
|
-
: 'prompt_only',
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
return result;
|
|
81
|
-
}
|
|
82
|
-
function parsePrinciples(raw) {
|
|
83
|
-
if (!isRecord(raw))
|
|
84
|
-
return {};
|
|
85
|
-
const principles = {};
|
|
86
|
-
for (const [id, value] of Object.entries(raw)) {
|
|
87
|
-
if (!isRecord(value))
|
|
88
|
-
continue;
|
|
89
|
-
principles[id] = {
|
|
90
|
-
...value,
|
|
91
|
-
id,
|
|
92
|
-
ruleIds: stringArray(value.ruleIds),
|
|
93
|
-
conflictsWithPrincipleIds: stringArray(value.conflictsWithPrincipleIds),
|
|
94
|
-
derivedFromPainIds: stringArray(value.derivedFromPainIds),
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
return principles;
|
|
98
|
-
}
|
|
99
|
-
function parseRules(raw) {
|
|
100
|
-
if (!isRecord(raw))
|
|
101
|
-
return {};
|
|
102
|
-
const rules = {};
|
|
103
|
-
for (const [id, value] of Object.entries(raw)) {
|
|
104
|
-
if (!isRecord(value))
|
|
105
|
-
continue;
|
|
106
|
-
rules[id] = {
|
|
107
|
-
...value,
|
|
108
|
-
id,
|
|
109
|
-
principleId: typeof value.principleId === 'string' ? value.principleId : '',
|
|
110
|
-
implementationIds: stringArray(value.implementationIds),
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
return rules;
|
|
114
|
-
}
|
|
115
|
-
function parseImplementations(raw) {
|
|
116
|
-
if (!isRecord(raw))
|
|
117
|
-
return {};
|
|
118
|
-
const implementations = {};
|
|
119
|
-
for (const [id, value] of Object.entries(raw)) {
|
|
120
|
-
if (!isRecord(value) || typeof value.ruleId !== 'string')
|
|
121
|
-
continue;
|
|
122
|
-
implementations[id] = { ...value, id, ruleId: value.ruleId };
|
|
23
|
+
//
|
|
24
|
+
// Previously exported from ./io.ts. Inlined here as a private helper because
|
|
25
|
+
// this is the ONLY consumer in principles-core. The openclaw-plugin has its
|
|
26
|
+
// own copy at src/utils/io.ts.
|
|
27
|
+
//
|
|
28
|
+
// Crash-safe: writes to a .tmp file then renames. On Windows, retries with
|
|
29
|
+
// exponential backoff on EPERM/EBUSY/EACCES to handle transient file locks.
|
|
30
|
+
const RENAME_MAX_RETRIES = 3;
|
|
31
|
+
const RENAME_BASE_DELAY_MS = 50;
|
|
32
|
+
function atomicWriteFileSync(filePath, data) {
|
|
33
|
+
const tmpPath = filePath + '.tmp';
|
|
34
|
+
fs.writeFileSync(tmpPath, data, 'utf8');
|
|
35
|
+
let lastError;
|
|
36
|
+
for (let attempt = 0; attempt < RENAME_MAX_RETRIES; attempt++) {
|
|
37
|
+
try {
|
|
38
|
+
fs.renameSync(tmpPath, filePath);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
lastError = err;
|
|
43
|
+
const { code } = err;
|
|
44
|
+
// Only retry on Windows transient lock errors
|
|
45
|
+
if (code === 'EPERM' || code === 'EBUSY' || code === 'EACCES') {
|
|
46
|
+
if (attempt < RENAME_MAX_RETRIES - 1) {
|
|
47
|
+
const delay = RENAME_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
48
|
+
// Synchronous sleep using a tight spin with accessSync yield
|
|
49
|
+
const waitUntil = Date.now() + delay;
|
|
50
|
+
while (Date.now() < waitUntil) {
|
|
51
|
+
try {
|
|
52
|
+
fs.accessSync(tmpPath);
|
|
53
|
+
}
|
|
54
|
+
catch { /* ignore */ }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// Non-retryable error — throw immediately
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
123
62
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (!isRecord(raw))
|
|
128
|
-
return {};
|
|
129
|
-
const metrics = {};
|
|
130
|
-
for (const [id, value] of Object.entries(raw)) {
|
|
131
|
-
if (!isRecord(value))
|
|
132
|
-
continue;
|
|
133
|
-
metrics[id] = { ...value, principleId: typeof value.principleId === 'string' ? value.principleId : id };
|
|
63
|
+
// Clean up temp file on failure
|
|
64
|
+
try {
|
|
65
|
+
fs.unlinkSync(tmpPath);
|
|
134
66
|
}
|
|
135
|
-
|
|
67
|
+
catch { /* best effort */ }
|
|
68
|
+
throw lastError ?? new Error('atomicWriteFileSync: rename failed');
|
|
136
69
|
}
|
|
137
70
|
// ---------------------------------------------------------------------------
|
|
138
|
-
//
|
|
71
|
+
// Ledger file I/O (the only non-pure part of this module)
|
|
139
72
|
// ---------------------------------------------------------------------------
|
|
140
|
-
function createEmptyTree() {
|
|
141
|
-
return { principles: {}, rules: {}, implementations: {}, metrics: {}, lastUpdated: new Date(0).toISOString() };
|
|
142
|
-
}
|
|
143
|
-
// ---------------------------------------------------------------------------
|
|
144
|
-
// Parsers
|
|
145
|
-
// ---------------------------------------------------------------------------
|
|
146
|
-
function parseTree(raw) {
|
|
147
|
-
if (!isRecord(raw))
|
|
148
|
-
return createEmptyTree();
|
|
149
|
-
return {
|
|
150
|
-
principles: parsePrinciples(raw.principles),
|
|
151
|
-
rules: parseRules(raw.rules),
|
|
152
|
-
implementations: parseImplementations(raw.implementations),
|
|
153
|
-
metrics: parseMetrics(raw.metrics),
|
|
154
|
-
lastUpdated: typeof raw.lastUpdated === 'string' ? raw.lastUpdated : new Date(0).toISOString(),
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
73
|
function getLedgerFilePath(stateDir) {
|
|
158
74
|
return path.join(stateDir, PRINCIPLE_TRAINING_FILE);
|
|
159
75
|
}
|
|
@@ -167,25 +83,12 @@ function readLedgerFromFile(filePath) {
|
|
|
167
83
|
return { trainingStore: {}, tree: createEmptyTree() };
|
|
168
84
|
}
|
|
169
85
|
const parsed = JSON.parse(content);
|
|
170
|
-
|
|
171
|
-
return { trainingStore: {}, tree: createEmptyTree() };
|
|
172
|
-
const trainingStoreRaw = parsed.trainingStore ?? parsed;
|
|
173
|
-
const treeRaw = parsed[TREE_NAMESPACE] ?? parsed.tree;
|
|
174
|
-
return {
|
|
175
|
-
trainingStore: parseLegacyTrainingStore(trainingStoreRaw),
|
|
176
|
-
tree: parseTree(treeRaw),
|
|
177
|
-
};
|
|
86
|
+
return parseHybridLedger(parsed);
|
|
178
87
|
}
|
|
179
88
|
catch {
|
|
180
89
|
return { trainingStore: {}, tree: createEmptyTree() };
|
|
181
90
|
}
|
|
182
91
|
}
|
|
183
|
-
function serializeLedger(store) {
|
|
184
|
-
return JSON.stringify({
|
|
185
|
-
...store.trainingStore,
|
|
186
|
-
[TREE_NAMESPACE]: { ...store.tree, lastUpdated: new Date().toISOString() },
|
|
187
|
-
}, null, 2);
|
|
188
|
-
}
|
|
189
92
|
// ---------------------------------------------------------------------------
|
|
190
93
|
// Ledger mutations (synchronous — safe for single-process use)
|
|
191
94
|
// ---------------------------------------------------------------------------
|