principles-disciple 1.197.2 → 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,658 +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 uniqueStrings(values) {
35
- return Array.from(new Set(values));
36
- }
37
- function parseLegacyTrainingStore(raw) {
38
- if (!isRecord(raw))
39
- return {};
40
- const result = {};
41
- for (const [principleId, candidate] of Object.entries(raw)) {
42
- if (principleId === TREE_NAMESPACE || !isRecord(candidate))
43
- continue;
44
- if (candidate.principleId !== principleId)
45
- continue;
46
- result[principleId] = {
47
- principleId,
48
- evaluability: VALID_EVALUABILITIES.includes(candidate.evaluability) ? candidate.evaluability : "manual_only",
49
- applicableOpportunityCount: clampInt(candidate.applicableOpportunityCount, { min: 0, max: Infinity, fallback: 0 }),
50
- observedViolationCount: clampInt(candidate.observedViolationCount, { min: 0, max: Infinity, fallback: 0 }),
51
- complianceRate: clampFloat(candidate.complianceRate, { min: 0, max: 1, fallback: 0 }),
52
- violationTrend: clampFloat(candidate.violationTrend, { min: -1, max: 1, fallback: 0 }),
53
- generatedSampleCount: clampInt(candidate.generatedSampleCount, { min: 0, max: Infinity, fallback: 0 }),
54
- approvedSampleCount: clampInt(candidate.approvedSampleCount, { min: 0, max: Infinity, fallback: 0 }),
55
- includedTrainRunIds: stringArray(candidate.includedTrainRunIds),
56
- deployedCheckpointIds: stringArray(candidate.deployedCheckpointIds),
57
- lastEvalScore: typeof candidate.lastEvalScore === "number" && Number.isFinite(candidate.lastEvalScore) ? clampFloat(candidate.lastEvalScore, { min: 0, max: 1, fallback: 0 }) : void 0,
58
- internalizationStatus: VALID_INTERNALIZATION_STATUSES.includes(candidate.internalizationStatus) ? candidate.internalizationStatus : "prompt_only"
59
- };
60
- }
61
- return result;
62
- }
63
- function parsePrinciples(raw) {
64
- if (!isRecord(raw))
65
- return {};
66
- const principles = {};
67
- for (const [id, value] of Object.entries(raw)) {
68
- if (!isRecord(value))
69
- continue;
70
- principles[id] = {
71
- ...value,
72
- id,
73
- ruleIds: stringArray(value.ruleIds),
74
- conflictsWithPrincipleIds: stringArray(value.conflictsWithPrincipleIds),
75
- derivedFromPainIds: stringArray(value.derivedFromPainIds)
76
- };
77
- }
78
- return principles;
79
- }
80
- function parseRules(raw) {
81
- if (!isRecord(raw))
82
- return {};
83
- const rules = {};
84
- for (const [id, value] of Object.entries(raw)) {
85
- if (!isRecord(value))
86
- continue;
87
- rules[id] = {
88
- ...value,
89
- id,
90
- principleId: typeof value.principleId === "string" ? value.principleId : "",
91
- implementationIds: stringArray(value.implementationIds)
92
- };
93
- }
94
- return rules;
95
- }
96
- function parseImplementations(raw) {
97
- if (!isRecord(raw))
98
- return {};
99
- const implementations = {};
100
- for (const [id, value] of Object.entries(raw)) {
101
- if (!isRecord(value) || typeof value.ruleId !== "string")
102
- continue;
103
- implementations[id] = { ...value, id, ruleId: value.ruleId };
104
- }
105
- return implementations;
106
- }
107
- function parseMetrics(raw) {
108
- if (!isRecord(raw))
109
- return {};
110
- const metrics = {};
111
- for (const [id, value] of Object.entries(raw)) {
112
- if (!isRecord(value))
113
- continue;
114
- metrics[id] = { ...value, principleId: typeof value.principleId === "string" ? value.principleId : id };
115
- }
116
- return metrics;
117
- }
118
- function createEmptyTree() {
119
- return { principles: {}, rules: {}, implementations: {}, metrics: {}, lastUpdated: (/* @__PURE__ */ new Date(0)).toISOString() };
120
- }
121
- function parseTree(raw) {
122
- if (!isRecord(raw))
123
- return createEmptyTree();
124
- return {
125
- principles: parsePrinciples(raw.principles),
126
- rules: parseRules(raw.rules),
127
- implementations: parseImplementations(raw.implementations),
128
- metrics: parseMetrics(raw.metrics),
129
- lastUpdated: typeof raw.lastUpdated === "string" ? raw.lastUpdated : (/* @__PURE__ */ new Date(0)).toISOString()
130
- };
131
- }
132
- function parseHybridLedger(raw) {
133
- if (!isRecord(raw))
134
- return { trainingStore: {}, tree: createEmptyTree() };
135
- const trainingStoreRaw = raw.trainingStore ?? raw;
136
- const treeRaw = raw[TREE_NAMESPACE] ?? raw.tree;
137
- return {
138
- trainingStore: parseLegacyTrainingStore(trainingStoreRaw),
139
- tree: parseTree(treeRaw)
140
- };
141
- }
142
- function serializeLedger(store) {
143
- return JSON.stringify({
144
- ...store.trainingStore,
145
- [TREE_NAMESPACE]: { ...store.tree, lastUpdated: (/* @__PURE__ */ new Date()).toISOString() }
146
- }, null, 2);
147
- }
148
-
149
- // ../principles-core/dist/principle-tree-ledger.js
150
- var PRINCIPLE_TRAINING_FILE = "principle_training_state.json";
151
- var RENAME_MAX_RETRIES = 3;
152
- var RENAME_BASE_DELAY_MS = 50;
153
- function atomicWriteFileSync(filePath, data) {
154
- const targetDir = path.dirname(filePath);
155
- const tmpDir = fs.mkdtempSync(path.join(targetDir, ".pd-write-"));
156
- const tmpPath = path.join(tmpDir, "tmp");
157
- try {
158
- fs.writeFileSync(tmpPath, data, { encoding: "utf8", mode: 384 });
159
- let lastError;
160
- for (let attempt = 0; attempt < RENAME_MAX_RETRIES; attempt++) {
161
- try {
162
- fs.renameSync(tmpPath, filePath);
163
- return;
164
- } catch (err) {
165
- lastError = err;
166
- const { code } = err;
167
- if (code === "EPERM" || code === "EBUSY" || code === "EACCES") {
168
- if (attempt < RENAME_MAX_RETRIES - 1) {
169
- const delay = RENAME_BASE_DELAY_MS * Math.pow(2, attempt);
170
- const waitUntil = Date.now() + delay;
171
- while (Date.now() < waitUntil) {
172
- try {
173
- fs.accessSync(tmpPath);
174
- } catch {
175
- }
176
- }
177
- }
178
- continue;
179
- }
180
- break;
181
- }
182
- }
183
- throw lastError ?? new Error("atomicWriteFileSync: rename failed");
184
- } finally {
185
- try {
186
- fs.unlinkSync(tmpPath);
187
- } catch {
188
- }
189
- try {
190
- fs.rmdirSync(tmpDir);
191
- } catch {
192
- }
193
- }
194
- }
195
- function getLedgerFilePath(stateDir) {
196
- return path.join(stateDir, PRINCIPLE_TRAINING_FILE);
197
- }
198
- function readLedgerFromFile(filePath) {
199
- if (!fs.existsSync(filePath)) {
200
- return { trainingStore: {}, tree: createEmptyTree() };
201
- }
202
- try {
203
- const content = fs.readFileSync(filePath, "utf-8");
204
- if (!content || content.trim() === "") {
205
- return { trainingStore: {}, tree: createEmptyTree() };
206
- }
207
- const parsed = JSON.parse(content);
208
- return parseHybridLedger(parsed);
209
- } catch {
210
- return { trainingStore: {}, tree: createEmptyTree() };
211
- }
212
- }
213
- var LockAcquisitionError = class extends Error {
214
- filePath;
215
- lockPath;
216
- constructor(message, filePath, lockPath) {
217
- super(message);
218
- this.name = "LockAcquisitionError";
219
- this.filePath = filePath;
220
- this.lockPath = lockPath;
221
- }
222
- };
223
- var DEFAULT_LOCK_OPTIONS = {
224
- maxRetries: 50,
225
- baseRetryDelayMs: 10,
226
- maxRetryDelayMs: 500,
227
- lockStaleMs: 1e4,
228
- lockSuffix: ".lock"
229
- };
230
- function isProcessAlive(pid) {
231
- try {
232
- process.kill(pid, 0);
233
- return true;
234
- } catch {
235
- return false;
236
- }
237
- }
238
- function isErrnoException(value) {
239
- return typeof value === "object" && value !== null && Object.hasOwn(value, "code");
240
- }
241
- function tryAcquireLock(lockPath, pid) {
242
- try {
243
- const lockDir = path.dirname(lockPath);
244
- if (!fs.existsSync(lockDir)) {
245
- fs.mkdirSync(lockDir, { recursive: true });
246
- }
247
- const flags = fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL;
248
- const fd = fs.openSync(lockPath, flags, 384);
249
- fs.writeSync(fd, String(pid));
250
- fs.fsyncSync(fd);
251
- fs.closeSync(fd);
252
- return true;
253
- } catch (err) {
254
- if (isErrnoException(err) && err.code === "EEXIST") {
255
- return false;
256
- }
257
- throw err;
258
- }
259
- }
260
- function readLockPid(lockPath) {
261
- try {
262
- const content = fs.readFileSync(lockPath, "utf8");
263
- const pid = parseInt(content.trim(), 10);
264
- return Number.isNaN(pid) ? null : pid;
265
- } catch {
266
- return null;
267
- }
268
- }
269
- function safeReleaseLock(lockPath, expectedPid) {
270
- try {
271
- if (readLockPid(lockPath) === expectedPid) {
272
- fs.unlinkSync(lockPath);
273
- }
274
- } catch {
275
- }
276
- }
277
- function cleanupStaleLock(lockPath, _staleMs) {
278
- try {
279
- const pid = readLockPid(lockPath);
280
- const isDead = pid === null || !isProcessAlive(pid);
281
- if (isDead) {
282
- try {
283
- fs.unlinkSync(lockPath);
284
- return true;
285
- } catch {
286
- return false;
287
- }
288
- }
289
- return false;
290
- } catch {
291
- return false;
292
- }
293
- }
294
- function calculateBackoff(attempt, baseMs, maxMs) {
295
- const exponentialDelay = Math.min(baseMs * Math.pow(2, attempt), maxMs);
296
- const jitter = exponentialDelay * 0.2 * Math.random();
297
- return Math.floor(exponentialDelay + jitter);
298
- }
299
- function sleepSync(ms) {
300
- if (ms <= 0)
301
- return;
302
- const shared = new Int32Array(new SharedArrayBuffer(4));
303
- Atomics.wait(shared, 0, 0, ms);
304
- }
305
- function tryAcquireWithStaleCleanup(filePath, opts, pid) {
306
- const lockPath = filePath + opts.lockSuffix;
307
- if (tryAcquireLock(lockPath, pid) && readLockPid(lockPath) === pid) {
308
- return { lockPath, pid, acquiredAt: Date.now() };
309
- }
310
- cleanupStaleLock(lockPath, opts.lockStaleMs);
311
- if (tryAcquireLock(lockPath, pid) && readLockPid(lockPath) === pid) {
312
- return { lockPath, pid, acquiredAt: Date.now() };
313
- }
314
- return null;
315
- }
316
- function buildLockError(filePath, opts) {
317
- const lockPath = filePath + opts.lockSuffix;
318
- const holderPid = readLockPid(lockPath);
319
- const holderStatus = holderPid !== null ? isProcessAlive(holderPid) ? `alive (PID ${holderPid})` : `dead (PID ${holderPid})` : "unknown";
320
- return new LockAcquisitionError(`Failed to acquire lock for ${filePath}. Lock holder: ${holderStatus}.`, filePath, lockPath);
321
- }
322
- function acquireLock(filePath, options = {}) {
323
- const opts = { ...DEFAULT_LOCK_OPTIONS, ...options };
324
- const { pid } = process;
325
- for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
326
- const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
327
- if (ctx)
328
- return ctx;
329
- if (attempt < opts.maxRetries - 1) {
330
- sleepSync(calculateBackoff(attempt, opts.baseRetryDelayMs, opts.maxRetryDelayMs));
331
- }
332
- }
333
- throw buildLockError(filePath, opts);
334
- }
335
- async function acquireLockAsync(filePath, options = {}) {
336
- const opts = { ...DEFAULT_LOCK_OPTIONS, ...options };
337
- const { pid } = process;
338
- for (let attempt = 0; attempt < opts.maxRetries; attempt++) {
339
- const ctx = tryAcquireWithStaleCleanup(filePath, opts, pid);
340
- if (ctx)
341
- return ctx;
342
- if (attempt < opts.maxRetries - 1) {
343
- await new Promise((resolve) => setTimeout(resolve, calculateBackoff(attempt, opts.baseRetryDelayMs, opts.maxRetryDelayMs)));
344
- }
345
- }
346
- throw buildLockError(filePath, opts);
347
- }
348
- function releaseLock(ctx) {
349
- safeReleaseLock(ctx.lockPath, ctx.pid);
350
- }
351
- function withLock(filePath, fn, options) {
352
- const ctx = acquireLock(filePath, options);
353
- try {
354
- return fn();
355
- } finally {
356
- releaseLock(ctx);
357
- }
358
- }
359
- async function withLockAsync(filePath, fn, options) {
360
- const ctx = await acquireLockAsync(filePath, options);
361
- try {
362
- return await fn();
363
- } finally {
364
- releaseLock(ctx);
365
- }
366
- }
367
- function mutateLedger(stateDir, mutate) {
368
- const filePath = getLedgerFilePath(stateDir);
369
- return withLock(filePath, () => {
370
- const store = readLedgerFromFile(filePath);
371
- const result = mutate(store);
372
- const dir = path.dirname(filePath);
373
- if (!fs.existsSync(dir))
374
- fs.mkdirSync(dir, { recursive: true });
375
- atomicWriteFileSync(filePath, serializeLedger(store));
376
- return result;
377
- });
378
- }
379
- async function mutateLedgerAsync(stateDir, mutate) {
380
- const filePath = getLedgerFilePath(stateDir);
381
- return withLockAsync(filePath, async () => {
382
- const store = readLedgerFromFile(filePath);
383
- const result = await mutate(store);
384
- const dir = path.dirname(filePath);
385
- if (!fs.existsSync(dir))
386
- fs.mkdirSync(dir, { recursive: true });
387
- atomicWriteFileSync(filePath, serializeLedger(store));
388
- return result;
389
- });
390
- }
391
- function loadLedger(stateDir) {
392
- return readLedgerFromFile(getLedgerFilePath(stateDir));
393
- }
394
- function saveLedger(stateDir, store) {
395
- mutateLedger(stateDir, (current) => {
396
- current.trainingStore = store.trainingStore;
397
- current.tree = store.tree;
398
- });
399
- }
400
- function addPrincipleToLedger(stateDir, principle) {
401
- return mutateLedger(stateDir, (store) => {
402
- store.tree.principles[principle.id] = principle;
403
- store.tree.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
404
- return principle;
405
- });
406
- }
407
- function updatePrinciple(stateDir, principleId, updates) {
408
- return mutateLedger(stateDir, (store) => {
409
- const existing = store.tree.principles[principleId];
410
- if (!existing)
411
- throw new Error(`Cannot update missing principle "${principleId}".`);
412
- const next = {
413
- ...existing,
414
- ...updates,
415
- id: principleId,
416
- ruleIds: updates.ruleIds ? uniqueStrings(updates.ruleIds) : existing.ruleIds,
417
- conflictsWithPrincipleIds: updates.conflictsWithPrincipleIds ? uniqueStrings(updates.conflictsWithPrincipleIds) : existing.conflictsWithPrincipleIds,
418
- derivedFromPainIds: updates.derivedFromPainIds ? uniqueStrings(updates.derivedFromPainIds) : existing.derivedFromPainIds
419
- };
420
- store.tree.principles[principleId] = next;
421
- return next;
422
- });
423
- }
424
- function updatePrincipleValueMetrics(stateDir, principleId, metrics) {
425
- return mutateLedger(stateDir, (store) => {
426
- const next = { ...metrics, principleId };
427
- store.tree.metrics[principleId] = next;
428
- return next;
429
- });
430
- }
431
- function getLedgerFilePathPublic(stateDir) {
432
- return getLedgerFilePath(stateDir);
433
- }
434
- function createRule(stateDir, rule) {
435
- return mutateLedger(stateDir, (store) => {
436
- const principle = store.tree.principles[rule.principleId];
437
- if (!principle) {
438
- throw new Error(`Cannot create rule "${rule.id}" for missing principle "${rule.principleId}".`);
439
- }
440
- if (Object.hasOwn(store.tree.rules, rule.id)) {
441
- throw new Error(`Cannot create rule "${rule.id}": it already exists. Use updateRule instead.`);
442
- }
443
- const nextRule = {
444
- ...rule,
445
- implementationIds: uniqueStrings(rule.implementationIds)
446
- };
447
- store.tree.rules[nextRule.id] = nextRule;
448
- principle.ruleIds = uniqueStrings([...principle.ruleIds, nextRule.id]);
449
- return nextRule;
450
- });
451
- }
452
- function createImplementation(stateDir, implementation) {
453
- return mutateLedger(stateDir, (store) => {
454
- const rule = store.tree.rules[implementation.ruleId];
455
- if (!rule) {
456
- throw new Error(`Cannot create implementation "${implementation.id}" for missing rule "${implementation.ruleId}".`);
457
- }
458
- if (Object.hasOwn(store.tree.implementations, implementation.id)) {
459
- throw new Error(`Cannot create implementation "${implementation.id}": it already exists. Use updateImplementation instead.`);
460
- }
461
- store.tree.implementations[implementation.id] = implementation;
462
- rule.implementationIds = uniqueStrings([...rule.implementationIds, implementation.id]);
463
- return implementation;
464
- });
465
- }
466
- function updateRule(stateDir, ruleId, updates) {
467
- return mutateLedger(stateDir, (store) => {
468
- const existingRule = store.tree.rules[ruleId];
469
- if (!existingRule) {
470
- throw new Error(`Cannot update missing rule "${ruleId}".`);
471
- }
472
- const nextPrincipleId = updates.principleId ?? existingRule.principleId;
473
- const nextPrinciple = store.tree.principles[nextPrincipleId];
474
- if (!nextPrinciple) {
475
- throw new Error(`Cannot move rule "${ruleId}" to missing principle "${nextPrincipleId}".`);
476
- }
477
- const nextRule = {
478
- ...existingRule,
479
- ...updates,
480
- id: ruleId,
481
- principleId: nextPrincipleId,
482
- implementationIds: updates.implementationIds ? uniqueStrings(updates.implementationIds) : existingRule.implementationIds
483
- };
484
- if (existingRule.principleId !== nextPrincipleId) {
485
- const previousPrinciple = store.tree.principles[existingRule.principleId];
486
- if (previousPrinciple) {
487
- previousPrinciple.ruleIds = previousPrinciple.ruleIds.filter((candidateId) => candidateId !== ruleId);
488
- }
489
- nextPrinciple.ruleIds = uniqueStrings([...nextPrinciple.ruleIds, ruleId]);
490
- }
491
- store.tree.rules[ruleId] = nextRule;
492
- return nextRule;
493
- });
494
- }
495
- function deleteRule(stateDir, ruleId) {
496
- return mutateLedger(stateDir, (store) => {
497
- const existingRule = store.tree.rules[ruleId];
498
- if (!existingRule) {
499
- return void 0;
500
- }
501
- const parentPrinciple = store.tree.principles[existingRule.principleId];
502
- if (parentPrinciple) {
503
- parentPrinciple.ruleIds = parentPrinciple.ruleIds.filter((candidateId) => candidateId !== ruleId);
504
- }
505
- const implementationIds = uniqueStrings([
506
- ...existingRule.implementationIds,
507
- ...Object.values(store.tree.implementations).filter((implementation) => implementation.ruleId === ruleId).map((implementation) => implementation.id)
508
- ]);
509
- for (const implementationId of implementationIds) {
510
- delete store.tree.implementations[implementationId];
511
- }
512
- delete store.tree.rules[ruleId];
513
- return existingRule;
514
- });
515
- }
516
- function updateImplementation(stateDir, implementationId, updates) {
517
- return mutateLedger(stateDir, (store) => {
518
- const existingImplementation = store.tree.implementations[implementationId];
519
- if (!existingImplementation) {
520
- throw new Error(`Cannot update missing implementation "${implementationId}".`);
521
- }
522
- const nextRuleId = updates.ruleId ?? existingImplementation.ruleId;
523
- const nextRule = store.tree.rules[nextRuleId];
524
- if (!nextRule) {
525
- throw new Error(`Cannot move implementation "${implementationId}" to missing rule "${nextRuleId}".`);
526
- }
527
- const nextImplementation = {
528
- ...existingImplementation,
529
- ...updates,
530
- id: implementationId,
531
- ruleId: nextRuleId
532
- };
533
- if (existingImplementation.ruleId !== nextRuleId) {
534
- const previousRule = store.tree.rules[existingImplementation.ruleId];
535
- if (previousRule) {
536
- previousRule.implementationIds = previousRule.implementationIds.filter((candidateId) => candidateId !== implementationId);
537
- }
538
- nextRule.implementationIds = uniqueStrings([...nextRule.implementationIds, implementationId]);
539
- }
540
- store.tree.implementations[implementationId] = nextImplementation;
541
- return nextImplementation;
542
- });
543
- }
544
- function deleteImplementation(stateDir, implementationId) {
545
- return mutateLedger(stateDir, (store) => {
546
- const existingImplementation = store.tree.implementations[implementationId];
547
- if (!existingImplementation) {
548
- return void 0;
549
- }
550
- const parentRule = store.tree.rules[existingImplementation.ruleId];
551
- if (parentRule) {
552
- parentRule.implementationIds = parentRule.implementationIds.filter((candidateId) => candidateId !== implementationId);
553
- }
554
- delete store.tree.implementations[implementationId];
555
- return existingImplementation;
556
- });
557
- }
558
- function listImplementationsForRule(stateDir, ruleId) {
559
- const ledger = loadLedger(stateDir);
560
- const rule = ledger.tree.rules[ruleId];
561
- if (!rule) {
562
- return [];
563
- }
564
- return rule.implementationIds.map((implementationId) => ledger.tree.implementations[implementationId]).filter((implementation) => implementation !== void 0);
565
- }
566
- function getPrincipleSubtree(stateDir, principleId) {
567
- const ledger = loadLedger(stateDir);
568
- const principle = ledger.tree.principles[principleId];
569
- if (!principle) {
570
- return void 0;
571
- }
572
- return {
573
- principle,
574
- rules: principle.ruleIds.map((ruleId) => ledger.tree.rules[ruleId]).filter((rule) => rule !== void 0).map((rule) => ({
575
- rule,
576
- implementations: rule.implementationIds.map((implementationId) => ledger.tree.implementations[implementationId]).filter((implementation) => implementation !== void 0)
577
- }))
578
- };
579
- }
580
- var VALID_LIFECYCLE_TRANSITIONS = {
581
- candidate: ["active", "archived"],
582
- active: ["disabled", "archived"],
583
- disabled: ["active", "archived"],
584
- archived: []
585
- };
586
- function isValidLifecycleTransition(from, to) {
587
- return VALID_LIFECYCLE_TRANSITIONS[from]?.includes(to) ?? false;
588
- }
589
- function getAllowedTransitions(from) {
590
- return VALID_LIFECYCLE_TRANSITIONS[from] ?? [];
591
- }
592
- function transitionImplementationState(stateDir, implementationId, newState) {
593
- return mutateLedger(stateDir, (store) => {
594
- const impl = store.tree.implementations[implementationId];
595
- if (!impl) {
596
- throw new Error(`Implementation not found: ${implementationId}`);
597
- }
598
- const currentState = impl.lifecycleState ?? "candidate";
599
- if (!isValidLifecycleTransition(currentState, newState)) {
600
- const allowed = getAllowedTransitions(currentState);
601
- throw new Error(`Invalid lifecycle transition: ${currentState} -> ${newState}. Allowed: ${allowed.length > 0 ? allowed.join(", ") : "none (terminal state)"}`);
602
- }
603
- const updated = {
604
- ...impl,
605
- lifecycleState: newState,
606
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
607
- };
608
- store.tree.implementations[implementationId] = updated;
609
- return updated;
610
- });
611
- }
612
- function listRuleImplementationsByState(stateDir, ruleId, state) {
613
- const implementations = listImplementationsForRule(stateDir, ruleId);
614
- return implementations.filter((impl) => (impl.lifecycleState ?? "candidate") === state);
615
- }
616
- function findActiveImplementation(stateDir, ruleId) {
617
- const implementations = listImplementationsForRule(stateDir, ruleId);
618
- return implementations.find((impl) => impl.lifecycleState === "active") ?? null;
619
- }
620
- async function saveLedgerAsync(stateDir, store) {
621
- await mutateLedgerAsync(stateDir, async (current) => {
622
- current.trainingStore = store.trainingStore;
623
- current.tree = store.tree;
624
- });
625
- }
626
- function updateTrainingStore(stateDir, mutate) {
627
- mutateLedger(stateDir, (store) => {
628
- mutate(store.trainingStore);
629
- });
630
- }
631
-
632
- // src/core/principle-tree-ledger.ts
633
- var getLedgerFilePath2 = getLedgerFilePathPublic;
634
- export {
635
- LockAcquisitionError,
636
- TREE_NAMESPACE,
637
- addPrincipleToLedger,
638
- createImplementation,
639
- createRule,
640
- deleteImplementation,
641
- deleteRule,
642
- findActiveImplementation,
643
- getAllowedTransitions,
644
- getLedgerFilePath2 as getLedgerFilePath,
645
- getPrincipleSubtree,
646
- isValidLifecycleTransition,
647
- listImplementationsForRule,
648
- listRuleImplementationsByState,
649
- loadLedger,
650
- saveLedger,
651
- saveLedgerAsync,
652
- transitionImplementationState,
653
- updateImplementation,
654
- updatePrinciple,
655
- updatePrincipleValueMetrics,
656
- updateRule,
657
- updateTrainingStore
658
- };