principles-disciple 1.197.1 → 1.197.3

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.
@@ -1,511 +0,0 @@
1
- // ../principles-core/dist/principle-tree-ledger.js
2
- import * as fs from "fs";
3
- import * as path from "path";
4
-
5
- // ../principles-core/dist/runtime-v2/types/ledger-store.js
6
- var TREE_NAMESPACE = "_tree";
7
-
8
- // ../principles-core/dist/runtime-v2/principle-tree/ledger-codec.js
9
- var VALID_EVALUABILITIES = ["deterministic", "weak_heuristic", "manual_only"];
10
- var VALID_INTERNALIZATION_STATUSES = [
11
- "prompt_only",
12
- "needs_training",
13
- "in_training",
14
- "deployed_pending_eval",
15
- "internalized",
16
- "regressed"
17
- ];
18
- function isRecord(value) {
19
- return typeof value === "object" && value !== null && !Array.isArray(value);
20
- }
21
- function stringArray(value) {
22
- return Array.isArray(value) ? value.filter((e) => typeof e === "string") : [];
23
- }
24
- function clampFloat(value, opts) {
25
- if (typeof value !== "number" || !Number.isFinite(value))
26
- return opts.fallback;
27
- return Math.max(opts.min, Math.min(opts.max, value));
28
- }
29
- function clampInt(value, opts) {
30
- if (typeof value !== "number" || !Number.isFinite(value))
31
- return opts.fallback;
32
- return Math.max(opts.min, Math.min(opts.max, Math.round(value)));
33
- }
34
- function parseLegacyTrainingStore(raw) {
35
- if (!isRecord(raw))
36
- return {};
37
- const result = {};
38
- for (const [principleId, candidate] of Object.entries(raw)) {
39
- if (principleId === TREE_NAMESPACE || !isRecord(candidate))
40
- continue;
41
- if (candidate.principleId !== principleId)
42
- continue;
43
- result[principleId] = {
44
- principleId,
45
- evaluability: VALID_EVALUABILITIES.includes(candidate.evaluability) ? candidate.evaluability : "manual_only",
46
- applicableOpportunityCount: clampInt(candidate.applicableOpportunityCount, { min: 0, max: Infinity, fallback: 0 }),
47
- observedViolationCount: clampInt(candidate.observedViolationCount, { min: 0, max: Infinity, fallback: 0 }),
48
- complianceRate: clampFloat(candidate.complianceRate, { min: 0, max: 1, fallback: 0 }),
49
- violationTrend: clampFloat(candidate.violationTrend, { min: -1, max: 1, fallback: 0 }),
50
- generatedSampleCount: clampInt(candidate.generatedSampleCount, { min: 0, max: Infinity, fallback: 0 }),
51
- approvedSampleCount: clampInt(candidate.approvedSampleCount, { min: 0, max: Infinity, fallback: 0 }),
52
- includedTrainRunIds: stringArray(candidate.includedTrainRunIds),
53
- deployedCheckpointIds: stringArray(candidate.deployedCheckpointIds),
54
- lastEvalScore: typeof candidate.lastEvalScore === "number" && Number.isFinite(candidate.lastEvalScore) ? clampFloat(candidate.lastEvalScore, { min: 0, max: 1, fallback: 0 }) : void 0,
55
- internalizationStatus: VALID_INTERNALIZATION_STATUSES.includes(candidate.internalizationStatus) ? candidate.internalizationStatus : "prompt_only"
56
- };
57
- }
58
- return result;
59
- }
60
- function parsePrinciples(raw) {
61
- if (!isRecord(raw))
62
- return {};
63
- const principles = {};
64
- for (const [id, value] of Object.entries(raw)) {
65
- if (!isRecord(value))
66
- continue;
67
- principles[id] = {
68
- ...value,
69
- id,
70
- ruleIds: stringArray(value.ruleIds),
71
- conflictsWithPrincipleIds: stringArray(value.conflictsWithPrincipleIds),
72
- derivedFromPainIds: stringArray(value.derivedFromPainIds)
73
- };
74
- }
75
- return principles;
76
- }
77
- function parseRules(raw) {
78
- if (!isRecord(raw))
79
- return {};
80
- const rules = {};
81
- for (const [id, value] of Object.entries(raw)) {
82
- if (!isRecord(value))
83
- continue;
84
- rules[id] = {
85
- ...value,
86
- id,
87
- principleId: typeof value.principleId === "string" ? value.principleId : "",
88
- implementationIds: stringArray(value.implementationIds)
89
- };
90
- }
91
- return rules;
92
- }
93
- function parseImplementations(raw) {
94
- if (!isRecord(raw))
95
- return {};
96
- const implementations = {};
97
- for (const [id, value] of Object.entries(raw)) {
98
- if (!isRecord(value) || typeof value.ruleId !== "string")
99
- continue;
100
- implementations[id] = { ...value, id, ruleId: value.ruleId };
101
- }
102
- return implementations;
103
- }
104
- function parseMetrics(raw) {
105
- if (!isRecord(raw))
106
- return {};
107
- const metrics = {};
108
- for (const [id, value] of Object.entries(raw)) {
109
- if (!isRecord(value))
110
- continue;
111
- metrics[id] = { ...value, principleId: typeof value.principleId === "string" ? value.principleId : id };
112
- }
113
- return metrics;
114
- }
115
- function createEmptyTree() {
116
- return { principles: {}, rules: {}, implementations: {}, metrics: {}, lastUpdated: (/* @__PURE__ */ new Date(0)).toISOString() };
117
- }
118
- function parseTree(raw) {
119
- if (!isRecord(raw))
120
- return createEmptyTree();
121
- return {
122
- principles: parsePrinciples(raw.principles),
123
- rules: parseRules(raw.rules),
124
- implementations: parseImplementations(raw.implementations),
125
- metrics: parseMetrics(raw.metrics),
126
- lastUpdated: typeof raw.lastUpdated === "string" ? raw.lastUpdated : (/* @__PURE__ */ new Date(0)).toISOString()
127
- };
128
- }
129
- function parseHybridLedger(raw) {
130
- if (!isRecord(raw))
131
- return { trainingStore: {}, tree: createEmptyTree() };
132
- const trainingStoreRaw = raw.trainingStore ?? raw;
133
- const treeRaw = raw[TREE_NAMESPACE] ?? raw.tree;
134
- return {
135
- trainingStore: parseLegacyTrainingStore(trainingStoreRaw),
136
- tree: parseTree(treeRaw)
137
- };
138
- }
139
- function serializeLedger(store) {
140
- return JSON.stringify({
141
- ...store.trainingStore,
142
- [TREE_NAMESPACE]: { ...store.tree, lastUpdated: (/* @__PURE__ */ new Date()).toISOString() }
143
- }, null, 2);
144
- }
145
-
146
- // ../principles-core/dist/principle-tree-ledger.js
147
- var PRINCIPLE_TRAINING_FILE = "principle_training_state.json";
148
- var RENAME_MAX_RETRIES = 3;
149
- var RENAME_BASE_DELAY_MS = 50;
150
- function atomicWriteFileSync(filePath, data) {
151
- const targetDir = path.dirname(filePath);
152
- const tmpDir = fs.mkdtempSync(path.join(targetDir, ".pd-write-"));
153
- const tmpPath = path.join(tmpDir, "tmp");
154
- try {
155
- fs.writeFileSync(tmpPath, data, { encoding: "utf8", mode: 384 });
156
- let lastError;
157
- for (let attempt = 0; attempt < RENAME_MAX_RETRIES; attempt++) {
158
- try {
159
- fs.renameSync(tmpPath, filePath);
160
- return;
161
- } catch (err) {
162
- lastError = err;
163
- const { code } = err;
164
- if (code === "EPERM" || code === "EBUSY" || code === "EACCES") {
165
- if (attempt < RENAME_MAX_RETRIES - 1) {
166
- const delay = RENAME_BASE_DELAY_MS * Math.pow(2, attempt);
167
- const waitUntil = Date.now() + delay;
168
- while (Date.now() < waitUntil) {
169
- try {
170
- fs.accessSync(tmpPath);
171
- } catch {
172
- }
173
- }
174
- }
175
- continue;
176
- }
177
- break;
178
- }
179
- }
180
- throw lastError ?? new Error("atomicWriteFileSync: rename failed");
181
- } finally {
182
- try {
183
- fs.unlinkSync(tmpPath);
184
- } catch {
185
- }
186
- try {
187
- fs.rmdirSync(tmpDir);
188
- } catch {
189
- }
190
- }
191
- }
192
- function getLedgerFilePath(stateDir) {
193
- return path.join(stateDir, PRINCIPLE_TRAINING_FILE);
194
- }
195
- function readLedgerFromFile(filePath) {
196
- if (!fs.existsSync(filePath)) {
197
- return { trainingStore: {}, tree: createEmptyTree() };
198
- }
199
- try {
200
- const content = fs.readFileSync(filePath, "utf-8");
201
- if (!content || content.trim() === "") {
202
- return { trainingStore: {}, tree: createEmptyTree() };
203
- }
204
- const parsed = JSON.parse(content);
205
- return parseHybridLedger(parsed);
206
- } catch {
207
- return { trainingStore: {}, tree: createEmptyTree() };
208
- }
209
- }
210
- var LockAcquisitionError = class extends Error {
211
- filePath;
212
- lockPath;
213
- constructor(message, filePath, lockPath) {
214
- super(message);
215
- this.name = "LockAcquisitionError";
216
- this.filePath = filePath;
217
- this.lockPath = lockPath;
218
- }
219
- };
220
- var DEFAULT_LOCK_OPTIONS = {
221
- maxRetries: 50,
222
- baseRetryDelayMs: 10,
223
- maxRetryDelayMs: 500,
224
- lockStaleMs: 1e4,
225
- lockSuffix: ".lock"
226
- };
227
- function isProcessAlive(pid) {
228
- try {
229
- process.kill(pid, 0);
230
- return true;
231
- } catch {
232
- return false;
233
- }
234
- }
235
- function isErrnoException(value) {
236
- return typeof value === "object" && value !== null && Object.hasOwn(value, "code");
237
- }
238
- function tryAcquireLock(lockPath, pid) {
239
- try {
240
- const lockDir = path.dirname(lockPath);
241
- if (!fs.existsSync(lockDir)) {
242
- fs.mkdirSync(lockDir, { recursive: true });
243
- }
244
- const flags = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL;
245
- const fd = fs.openSync(lockPath, flags, 384);
246
- fs.writeSync(fd, String(pid));
247
- fs.fsyncSync(fd);
248
- fs.closeSync(fd);
249
- return true;
250
- } catch (err) {
251
- if (isErrnoException(err) && err.code === "EEXIST") {
252
- return false;
253
- }
254
- throw err;
255
- }
256
- }
257
- function readLockPid(lockPath) {
258
- try {
259
- const content = fs.readFileSync(lockPath, "utf8");
260
- const pid = parseInt(content.trim(), 10);
261
- return Number.isNaN(pid) ? null : pid;
262
- } catch {
263
- return null;
264
- }
265
- }
266
- function safeReleaseLock(lockPath, expectedPid) {
267
- try {
268
- if (readLockPid(lockPath) === expectedPid) {
269
- fs.unlinkSync(lockPath);
270
- }
271
- } catch {
272
- }
273
- }
274
- function cleanupStaleLock(lockPath, _staleMs) {
275
- try {
276
- const pid = readLockPid(lockPath);
277
- const isDead = pid === null || !isProcessAlive(pid);
278
- if (isDead) {
279
- try {
280
- fs.unlinkSync(lockPath);
281
- return true;
282
- } catch {
283
- return false;
284
- }
285
- }
286
- return false;
287
- } catch {
288
- return false;
289
- }
290
- }
291
- function calculateBackoff(attempt, baseMs, maxMs) {
292
- const exponentialDelay = Math.min(baseMs * Math.pow(2, attempt), maxMs);
293
- const jitter = exponentialDelay * 0.2 * Math.random();
294
- return Math.floor(exponentialDelay + jitter);
295
- }
296
- function sleepSync(ms) {
297
- if (ms <= 0)
298
- return;
299
- const shared = new Int32Array(new SharedArrayBuffer(4));
300
- Atomics.wait(shared, 0, 0, ms);
301
- }
302
- function tryAcquireWithStaleCleanup(filePath, opts, pid) {
303
- const lockPath = filePath + opts.lockSuffix;
304
- if (tryAcquireLock(lockPath, pid) && readLockPid(lockPath) === pid) {
305
- return { lockPath, pid, acquiredAt: Date.now() };
306
- }
307
- cleanupStaleLock(lockPath, opts.lockStaleMs);
308
- if (tryAcquireLock(lockPath, pid) && readLockPid(lockPath) === pid) {
309
- return { lockPath, pid, acquiredAt: Date.now() };
310
- }
311
- return null;
312
- }
313
- function buildLockError(filePath, opts) {
314
- const lockPath = filePath + opts.lockSuffix;
315
- const holderPid = readLockPid(lockPath);
316
- const holderStatus = holderPid !== null ? isProcessAlive(holderPid) ? `alive (PID ${holderPid})` : `dead (PID ${holderPid})` : "unknown";
317
- return new LockAcquisitionError(`Failed to acquire lock for ${filePath}. Lock holder: ${holderStatus}.`, filePath, lockPath);
318
- }
319
- function acquireLock(filePath, options = {}) {
320
- const opts = { ...DEFAULT_LOCK_OPTIONS, ...options };
321
- const { pid } = process;
322
- for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
323
- const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
324
- if (ctx)
325
- return ctx;
326
- if (attempt < opts.maxRetries - 1) {
327
- sleepSync(calculateBackoff(attempt, opts.baseRetryDelayMs, opts.maxRetryDelayMs));
328
- }
329
- }
330
- throw buildLockError(filePath, opts);
331
- }
332
- async function acquireLockAsync(filePath, options = {}) {
333
- const opts = { ...DEFAULT_LOCK_OPTIONS, ...options };
334
- const { pid } = process;
335
- for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
336
- const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
337
- if (ctx)
338
- return ctx;
339
- if (attempt < opts.maxRetries - 1) {
340
- await new Promise((resolve) => setTimeout(resolve, calculateBackoff(attempt, opts.baseRetryDelayMs, opts.maxRetryDelayMs)));
341
- }
342
- }
343
- throw buildLockError(filePath, opts);
344
- }
345
- function releaseLock(ctx) {
346
- safeReleaseLock(ctx.lockPath, ctx.pid);
347
- }
348
- function withLock(filePath, fn, options) {
349
- const ctx = acquireLock(filePath, options);
350
- try {
351
- return fn();
352
- } finally {
353
- releaseLock(ctx);
354
- }
355
- }
356
- async function withLockAsync(filePath, fn, options) {
357
- const ctx = await acquireLockAsync(filePath, options);
358
- try {
359
- return await fn();
360
- } finally {
361
- releaseLock(ctx);
362
- }
363
- }
364
- function mutateLedger(stateDir, mutate) {
365
- const filePath = getLedgerFilePath(stateDir);
366
- return withLock(filePath, () => {
367
- const store = readLedgerFromFile(filePath);
368
- const result = mutate(store);
369
- const dir = path.dirname(filePath);
370
- if (!fs.existsSync(dir))
371
- fs.mkdirSync(dir, { recursive: true });
372
- atomicWriteFileSync(filePath, serializeLedger(store));
373
- return result;
374
- });
375
- }
376
- async function mutateLedgerAsync(stateDir, mutate) {
377
- const filePath = getLedgerFilePath(stateDir);
378
- return withLockAsync(filePath, async () => {
379
- const store = readLedgerFromFile(filePath);
380
- const result = await mutate(store);
381
- const dir = path.dirname(filePath);
382
- if (!fs.existsSync(dir))
383
- fs.mkdirSync(dir, { recursive: true });
384
- atomicWriteFileSync(filePath, serializeLedger(store));
385
- return result;
386
- });
387
- }
388
- function loadLedger(stateDir) {
389
- return readLedgerFromFile(getLedgerFilePath(stateDir));
390
- }
391
- function saveLedger(stateDir, store) {
392
- mutateLedger(stateDir, (current) => {
393
- current.trainingStore = store.trainingStore;
394
- current.tree = store.tree;
395
- });
396
- }
397
- async function saveLedgerAsync(stateDir, store) {
398
- await mutateLedgerAsync(stateDir, async (current) => {
399
- current.trainingStore = store.trainingStore;
400
- current.tree = store.tree;
401
- });
402
- }
403
- function updateTrainingStore(stateDir, mutate) {
404
- mutateLedger(stateDir, (store) => {
405
- mutate(store.trainingStore);
406
- });
407
- }
408
-
409
- // src/core/principle-training-state.ts
410
- var PRINCIPLE_TRAINING_FILE2 = "principle_training_state.json";
411
- function createDefaultPrincipleState(principleId) {
412
- return {
413
- principleId,
414
- evaluability: "manual_only",
415
- applicableOpportunityCount: 0,
416
- observedViolationCount: 0,
417
- complianceRate: 0,
418
- violationTrend: 0,
419
- generatedSampleCount: 0,
420
- approvedSampleCount: 0,
421
- includedTrainRunIds: [],
422
- deployedCheckpointIds: [],
423
- internalizationStatus: "prompt_only"
424
- };
425
- }
426
- function loadStore(stateDir) {
427
- return ledgerTrainingStore(stateDir);
428
- }
429
- function saveStore(stateDir, store) {
430
- const ledger = loadLedger(stateDir);
431
- saveLedger(stateDir, {
432
- ...ledger,
433
- trainingStore: store
434
- });
435
- }
436
- async function loadStoreAsync(stateDir) {
437
- return ledgerTrainingStore(stateDir);
438
- }
439
- async function saveStoreAsync(stateDir, store) {
440
- const ledger = loadLedger(stateDir);
441
- await saveLedgerAsync(stateDir, {
442
- ...ledger,
443
- trainingStore: store
444
- });
445
- }
446
- function getPrincipleState(stateDir, principleId) {
447
- const store = loadStore(stateDir);
448
- return store[principleId] ?? createDefaultPrincipleState(principleId);
449
- }
450
- function setPrincipleState(stateDir, state) {
451
- updateTrainingStore(stateDir, (store) => {
452
- store[state.principleId] = state;
453
- });
454
- }
455
- function removePrincipleState(stateDir, principleId) {
456
- updateTrainingStore(stateDir, (store) => {
457
- delete store[principleId];
458
- });
459
- }
460
- function listPrincipleIds(stateDir) {
461
- return Object.keys(loadStore(stateDir));
462
- }
463
- function listPrinciplesByStatus(stateDir, status) {
464
- return Object.values(loadStore(stateDir)).filter((state) => state.internalizationStatus === status);
465
- }
466
- function listEvaluablePrinciples(stateDir) {
467
- return Object.values(loadStore(stateDir)).filter(
468
- (state) => state.evaluability !== "manual_only" && state.internalizationStatus !== "prompt_only"
469
- );
470
- }
471
- var VALID_TRANSITIONS = {
472
- prompt_only: ["needs_training", "regressed"],
473
- needs_training: ["in_training", "regressed"],
474
- in_training: ["deployed_pending_eval", "regressed"],
475
- deployed_pending_eval: ["internalized", "regressed"],
476
- internalized: ["regressed"],
477
- regressed: ["needs_training"]
478
- };
479
- function transitionInternalizationStatus(stateDir, principleId, nextStatus) {
480
- updateTrainingStore(stateDir, (store) => {
481
- const state = store[principleId];
482
- if (!state) {
483
- throw new Error(`Cannot transition: principle ${principleId} not found in training store`);
484
- }
485
- const allowed = VALID_TRANSITIONS[state.internalizationStatus] ?? [];
486
- if (!allowed.includes(nextStatus)) {
487
- throw new Error(
488
- `Invalid transition: ${state.internalizationStatus} \u2192 ${nextStatus}. Allowed: ${allowed.join(", ") || "none (terminal state)"}`
489
- );
490
- }
491
- state.internalizationStatus = nextStatus;
492
- });
493
- }
494
- function ledgerTrainingStore(stateDir) {
495
- return loadLedger(stateDir).trainingStore;
496
- }
497
- export {
498
- PRINCIPLE_TRAINING_FILE2 as PRINCIPLE_TRAINING_FILE,
499
- createDefaultPrincipleState,
500
- getPrincipleState,
501
- listEvaluablePrinciples,
502
- listPrincipleIds,
503
- listPrinciplesByStatus,
504
- loadStore,
505
- loadStoreAsync,
506
- removePrincipleState,
507
- saveStore,
508
- saveStoreAsync,
509
- setPrincipleState,
510
- transitionInternalizationStatus
511
- };