principles-disciple 1.11.0 → 1.13.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/CHANGELOG.md +26 -0
- package/README.md +66 -0
- package/esbuild.config.js +1 -1
- package/openclaw.plugin.json +4 -4
- package/package.json +2 -3
- package/run-nocturnal.mjs +30 -0
- package/scripts/db-migrate.mjs +170 -0
- package/scripts/sync-plugin.mjs +250 -6
- package/src/commands/archive-impl.ts +136 -0
- package/src/commands/capabilities.ts +4 -2
- package/src/commands/context.ts +5 -1
- package/src/commands/disable-impl.ts +151 -0
- package/src/commands/evolution-status.ts +64 -19
- package/src/commands/export.ts +8 -6
- package/src/commands/focus.ts +8 -20
- package/src/commands/nocturnal-review.ts +5 -7
- package/src/commands/nocturnal-rollout.ts +1 -12
- package/src/commands/nocturnal-train.ts +21 -47
- package/src/commands/pain.ts +10 -5
- package/src/commands/principle-rollback.ts +4 -2
- package/src/commands/promote-impl.ts +274 -0
- package/src/commands/rollback-impl.ts +234 -0
- package/src/commands/rollback.ts +6 -3
- package/src/commands/samples.ts +2 -0
- package/src/commands/thinking-os.ts +3 -4
- package/src/commands/workflow-debug.ts +2 -1
- package/src/config/errors.ts +1 -0
- package/src/core/AGENTS.md +34 -0
- package/src/core/adaptive-thresholds.ts +4 -3
- package/src/core/code-implementation-storage.ts +241 -0
- package/src/core/config.ts +5 -2
- package/src/core/control-ui-db.ts +29 -10
- package/src/core/detection-funnel.ts +12 -7
- package/src/core/diagnostician-task-store.ts +156 -0
- package/src/core/dictionary.ts +4 -4
- package/src/core/empathy-keyword-matcher.ts +7 -3
- package/src/core/empathy-types.ts +13 -2
- package/src/core/event-log.ts +14 -6
- package/src/core/evolution-engine.ts +27 -31
- package/src/core/evolution-logger.ts +3 -2
- package/src/core/evolution-reducer.ts +110 -31
- package/src/core/evolution-types.ts +10 -0
- package/src/core/external-training-contract.ts +1 -0
- package/src/core/focus-history.ts +38 -24
- package/src/core/hygiene/tracker.ts +10 -6
- package/src/core/init.ts +5 -2
- package/src/core/migration.ts +3 -3
- package/src/core/model-deployment-registry.ts +6 -4
- package/src/core/model-training-registry.ts +5 -3
- package/src/core/nocturnal-arbiter.ts +13 -14
- package/src/core/nocturnal-artifact-lineage.ts +117 -0
- package/src/core/nocturnal-artificer.ts +257 -0
- package/src/core/nocturnal-candidate-scoring.ts +4 -2
- package/src/core/nocturnal-compliance.ts +67 -19
- package/src/core/nocturnal-dataset.ts +95 -2
- package/src/core/nocturnal-executability.ts +2 -3
- package/src/core/nocturnal-export.ts +6 -3
- package/src/core/nocturnal-rule-implementation-validator.ts +245 -0
- package/src/core/nocturnal-trajectory-extractor.ts +10 -3
- package/src/core/nocturnal-trinity.ts +319 -61
- package/src/core/pain-context-extractor.ts +29 -15
- package/src/core/pain.ts +7 -5
- package/src/core/path-resolver.ts +16 -15
- package/src/core/paths.ts +2 -1
- package/src/core/pd-task-reconciler.ts +463 -0
- package/src/core/pd-task-service.ts +42 -0
- package/src/core/pd-task-store.ts +77 -0
- package/src/core/pd-task-types.ts +128 -0
- package/src/core/principle-internalization/deprecated-readiness.ts +91 -0
- package/src/core/principle-internalization/internalization-routing-policy.ts +208 -0
- package/src/core/principle-internalization/lifecycle-metrics.ts +149 -0
- package/src/core/principle-internalization/lifecycle-read-model.ts +243 -0
- package/src/core/principle-internalization/lifecycle-refresh.ts +11 -0
- package/src/core/principle-internalization/principle-lifecycle-service.ts +167 -0
- package/src/core/principle-training-state.ts +95 -370
- package/src/core/principle-tree-ledger.ts +733 -0
- package/src/core/principle-tree-migration.ts +195 -0
- package/src/core/profile.ts +3 -1
- package/src/core/promotion-gate.ts +14 -18
- package/src/core/replay-engine.ts +562 -0
- package/src/core/risk-calculator.ts +6 -4
- package/src/core/rule-host-helpers.ts +39 -0
- package/src/core/rule-host-types.ts +82 -0
- package/src/core/rule-host.ts +245 -0
- package/src/core/rule-implementation-runtime.ts +38 -0
- package/src/core/schema/db-types.ts +16 -0
- package/src/core/schema/index.ts +26 -0
- package/src/core/schema/migration-runner.ts +207 -0
- package/src/core/schema/migrations/001-init-trajectory.ts +211 -0
- package/src/core/schema/migrations/002-init-central.ts +122 -0
- package/src/core/schema/migrations/003-init-workflow.ts +55 -0
- package/src/core/schema/migrations/004-add-thinking-and-gfi.ts +74 -0
- package/src/core/schema/migrations/index.ts +31 -0
- package/src/core/schema/schema-definitions.ts +650 -0
- package/src/core/session-tracker.ts +6 -4
- package/src/core/shadow-observation-registry.ts +6 -3
- package/src/core/system-logger.ts +2 -2
- package/src/core/thinking-models.ts +182 -46
- package/src/core/thinking-os-parser.ts +156 -0
- package/src/core/training-program.ts +7 -7
- package/src/core/trajectory.ts +42 -36
- package/src/core/workspace-context.ts +77 -11
- package/src/core/workspace-dir-validation.ts +152 -0
- package/src/hooks/AGENTS.md +31 -0
- package/src/hooks/bash-risk.ts +3 -1
- package/src/hooks/edit-verification.ts +9 -5
- package/src/hooks/gate-block-helper.ts +5 -1
- package/src/hooks/gate.ts +152 -5
- package/src/hooks/gfi-gate.ts +9 -2
- package/src/hooks/lifecycle-routing.ts +124 -0
- package/src/hooks/lifecycle.ts +12 -12
- package/src/hooks/llm.ts +17 -109
- package/src/hooks/message-sanitize.ts +5 -3
- package/src/hooks/pain.ts +19 -15
- package/src/hooks/progressive-trust-gate.ts +7 -1
- package/src/hooks/prompt.ts +169 -60
- package/src/hooks/subagent.ts +5 -4
- package/src/hooks/thinking-checkpoint.ts +2 -0
- package/src/hooks/trajectory-collector.ts +15 -12
- package/src/http/principles-console-route.ts +31 -68
- package/src/i18n/commands.ts +2 -2
- package/src/index.ts +130 -40
- package/src/service/central-database.ts +131 -43
- package/src/service/central-health-service.ts +47 -0
- package/src/service/central-overview-service.ts +135 -0
- package/src/service/central-sync-service.ts +87 -0
- package/src/service/control-ui-query-service.ts +46 -36
- package/src/service/event-log-auditor.ts +261 -0
- package/src/service/evolution-query-service.ts +23 -22
- package/src/service/evolution-worker.ts +565 -261
- package/src/service/health-query-service.ts +213 -36
- package/src/service/nocturnal-runtime.ts +8 -4
- package/src/service/nocturnal-service.ts +503 -59
- package/src/service/nocturnal-target-selector.ts +5 -7
- package/src/service/runtime-summary-service.ts +2 -1
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +25 -336
- package/src/service/subagent-workflow/dynamic-timeout.ts +30 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +48 -386
- package/src/service/subagent-workflow/index.ts +2 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +169 -284
- package/src/service/subagent-workflow/runtime-direct-driver.ts +114 -16
- package/src/service/subagent-workflow/subagent-error-utils.ts +25 -0
- package/src/service/subagent-workflow/types.ts +9 -4
- package/src/service/subagent-workflow/workflow-manager-base.ts +573 -0
- package/src/service/subagent-workflow/workflow-store.ts +71 -11
- package/src/service/trajectory-service.ts +2 -1
- package/src/tools/critique-prompt.ts +1 -1
- package/src/tools/deep-reflect.ts +175 -209
- package/src/tools/model-index.ts +2 -1
- package/src/types/event-types.ts +2 -2
- package/src/types/principle-tree-schema.ts +29 -23
- package/src/utils/file-lock.ts +5 -3
- package/src/utils/io.ts +5 -2
- package/src/utils/nlp.ts +5 -46
- package/src/utils/node-vm-polyfill.ts +11 -0
- package/src/utils/plugin-logger.ts +2 -0
- package/src/utils/retry.ts +572 -0
- package/src/utils/subagent-probe.ts +1 -1
- package/templates/langs/en/core/AGENTS.md +0 -13
- package/templates/langs/en/core/SOUL.md +1 -31
- package/templates/langs/en/core/TOOLS.md +0 -4
- package/templates/langs/en/principles/THINKING_OS.md +77 -0
- package/templates/langs/en/skills/admin/SKILL.md +0 -1
- package/templates/langs/en/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/en/skills/pd-diagnostician/SKILL.md +18 -5
- package/templates/langs/zh/core/AGENTS.md +0 -22
- package/templates/langs/zh/core/SOUL.md +1 -31
- package/templates/langs/zh/core/TOOLS.md +0 -4
- package/templates/langs/zh/principles/THINKING_OS.md +77 -0
- package/templates/langs/zh/skills/admin/SKILL.md +0 -1
- package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +1 -1
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +25 -4
- package/tests/commands/evolution-status.test.ts +119 -0
- package/tests/commands/implementation-lifecycle.test.ts +362 -0
- package/tests/core/code-implementation-storage.test.ts +398 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +28 -28
- package/tests/core/nocturnal-artifact-lineage.test.ts +53 -0
- package/tests/core/nocturnal-artificer.test.ts +241 -0
- package/tests/core/nocturnal-compliance-p-principles.test.ts +133 -0
- package/tests/core/nocturnal-rule-implementation-validator.test.ts +127 -0
- package/tests/core/pd-task-store.test.ts +126 -0
- package/tests/core/principle-internalization/deprecated-readiness.test.ts +193 -0
- package/tests/core/principle-internalization/internalization-routing-policy.test.ts +212 -0
- package/tests/core/principle-internalization/lifecycle-metrics.test.ts +350 -0
- package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +211 -0
- package/tests/core/principle-training-state.test.ts +228 -1
- package/tests/core/principle-tree-ledger.test.ts +423 -0
- package/tests/core/regression-v1-9-1.test.ts +265 -0
- package/tests/core/replay-engine.test.ts +234 -0
- package/tests/core/rule-host-helpers.test.ts +120 -0
- package/tests/core/rule-host.test.ts +389 -0
- package/tests/core/rule-implementation-runtime.test.ts +64 -0
- package/tests/core/workspace-context.test.ts +53 -0
- package/tests/core/workspace-dir-validation.test.ts +272 -0
- package/tests/hooks/gate-rule-host-pipeline.test.ts +385 -0
- package/tests/hooks/pain.test.ts +74 -10
- package/tests/hooks/prompt.test.ts +63 -1
- package/tests/integration/principle-lifecycle.e2e.test.ts +197 -0
- package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +211 -0
- package/tests/service/data-endpoints-regression.test.ts +834 -0
- package/tests/service/evolution-worker.test.ts +0 -123
- package/tests/service/nocturnal-service-code-candidate.test.ts +330 -0
- package/tests/utils/nlp.test.ts +1 -19
- package/tests/utils/retry.test.ts +327 -0
- package/ui/src/App.tsx +1 -1
- package/ui/src/api.ts +4 -0
- package/ui/src/charts.tsx +366 -0
- package/ui/src/components/WorkspaceConfig.tsx +107 -75
- package/ui/src/i18n/ui.ts +89 -31
- package/ui/src/pages/EvolutionPage.tsx +1 -1
- package/ui/src/pages/OverviewPage.tsx +441 -81
- package/ui/src/pages/ThinkingModelsPage.tsx +287 -69
- package/ui/src/styles.css +43 -0
- package/ui/src/types.ts +17 -1
- package/src/agents/nocturnal-dreamer.md +0 -152
- package/src/agents/nocturnal-philosopher.md +0 -138
- package/src/agents/nocturnal-reflector.md +0 -126
- package/src/agents/nocturnal-scribe.md +0 -164
- package/templates/workspace/.principles/00-kernel.md +0 -51
- package/templates/workspace/.principles/DECISION_POLICY.json +0 -44
- package/templates/workspace/.principles/PRINCIPLES.md +0 -20
- package/templates/workspace/.principles/PROFILE.json +0 -54
- package/templates/workspace/.principles/PROFILE.schema.json +0 -56
- package/templates/workspace/.principles/THINKING_OS.md +0 -64
- package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
- package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
- package/templates/workspace/.principles/models/_INDEX.md +0 -27
- package/templates/workspace/.principles/models/first_principles.md +0 -62
- package/templates/workspace/.principles/models/marketing_4p.md +0 -52
- package/templates/workspace/.principles/models/porter_five.md +0 -63
- package/templates/workspace/.principles/models/swot.md +0 -60
- package/templates/workspace/.principles/models/user_story_map.md +0 -63
- package/templates/workspace/.state/WORKBOARD.json +0 -4
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Principle Tree Migration — Migrates trainingStore to tree.principles
|
|
3
|
+
*
|
|
4
|
+
* This migration handles the Phase 11 gap: existing principles in trainingStore
|
|
5
|
+
* were never written to tree.principles, blocking the Rule/Implementation layer.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* - Called automatically by migratePrincipleTree() during plugin initialization
|
|
9
|
+
* - Or run manually: node scripts/migrate-principle-tree.mjs <workspace-dir>
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import {
|
|
15
|
+
loadLedger,
|
|
16
|
+
createPrinciple,
|
|
17
|
+
type LedgerPrinciple,
|
|
18
|
+
} from './principle-tree-ledger.js';
|
|
19
|
+
import type { LegacyPrincipleTrainingState } from './principle-tree-ledger.js';
|
|
20
|
+
import { SystemLogger } from './system-logger.js';
|
|
21
|
+
|
|
22
|
+
export interface PrincipleTreeMigrationResult {
|
|
23
|
+
migratedCount: number;
|
|
24
|
+
skippedCount: number;
|
|
25
|
+
errorCount: number;
|
|
26
|
+
details: Array<{
|
|
27
|
+
principleId: string;
|
|
28
|
+
status: 'migrated' | 'skipped' | 'error';
|
|
29
|
+
reason?: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if migration is needed by comparing trainingStore and tree.principles
|
|
35
|
+
*/
|
|
36
|
+
export function needsMigration(stateDir: string): boolean {
|
|
37
|
+
const ledger = loadLedger(stateDir);
|
|
38
|
+
const trainingStoreCount = Object.keys(ledger.trainingStore).length;
|
|
39
|
+
const treePrinciplesCount = Object.keys(ledger.tree.principles).length;
|
|
40
|
+
|
|
41
|
+
// Migration needed if trainingStore has more principles than tree.principles
|
|
42
|
+
return trainingStoreCount > treePrinciplesCount;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create a minimal LedgerPrinciple from LegacyPrincipleTrainingState
|
|
47
|
+
*/
|
|
48
|
+
function trainingStateToTreePrinciple(
|
|
49
|
+
principleId: string,
|
|
50
|
+
state: LegacyPrincipleTrainingState,
|
|
51
|
+
now: string
|
|
52
|
+
): LedgerPrinciple {
|
|
53
|
+
return {
|
|
54
|
+
id: principleId,
|
|
55
|
+
version: 1,
|
|
56
|
+
text: `Principle ${principleId}`, // Minimal text, will be enriched from PRINCIPLES.md if available
|
|
57
|
+
triggerPattern: '', // Unknown from legacy data
|
|
58
|
+
action: '', // Unknown from legacy data
|
|
59
|
+
status: mapInternalizationStatusToPrincipleStatus(state.internalizationStatus),
|
|
60
|
+
priority: 'P1', // Default priority
|
|
61
|
+
scope: 'general',
|
|
62
|
+
evaluability: state.evaluability,
|
|
63
|
+
valueScore: 0,
|
|
64
|
+
adherenceRate: state.complianceRate * 100, // Convert 0-1 to 0-100
|
|
65
|
+
painPreventedCount: 0,
|
|
66
|
+
derivedFromPainIds: [],
|
|
67
|
+
ruleIds: [],
|
|
68
|
+
conflictsWithPrincipleIds: [],
|
|
69
|
+
createdAt: now,
|
|
70
|
+
updatedAt: now,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Map internalization status to principle status
|
|
76
|
+
*/
|
|
77
|
+
function mapInternalizationStatusToPrincipleStatus(
|
|
78
|
+
status: LegacyPrincipleTrainingState['internalizationStatus']
|
|
79
|
+
): 'candidate' | 'active' | 'deprecated' {
|
|
80
|
+
switch (status) {
|
|
81
|
+
case 'internalized':
|
|
82
|
+
case 'deployed_pending_eval':
|
|
83
|
+
return 'active';
|
|
84
|
+
case 'regressed':
|
|
85
|
+
case 'needs_training':
|
|
86
|
+
return 'candidate';
|
|
87
|
+
case 'prompt_only':
|
|
88
|
+
case 'in_training':
|
|
89
|
+
return 'candidate';
|
|
90
|
+
default:
|
|
91
|
+
return 'candidate';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Migrate trainingStore principles to tree.principles
|
|
97
|
+
*
|
|
98
|
+
* This function is idempotent: it only migrates principles that don't exist
|
|
99
|
+
* in tree.principles yet.
|
|
100
|
+
*/
|
|
101
|
+
export function migratePrincipleTree(
|
|
102
|
+
stateDir: string,
|
|
103
|
+
workspaceDir?: string
|
|
104
|
+
): PrincipleTreeMigrationResult {
|
|
105
|
+
const result: PrincipleTreeMigrationResult = {
|
|
106
|
+
migratedCount: 0,
|
|
107
|
+
skippedCount: 0,
|
|
108
|
+
errorCount: 0,
|
|
109
|
+
details: [],
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const ledger = loadLedger(stateDir);
|
|
114
|
+
const now = new Date().toISOString();
|
|
115
|
+
|
|
116
|
+
for (const [principleId, state] of Object.entries(ledger.trainingStore)) {
|
|
117
|
+
// Skip if already exists in tree.principles
|
|
118
|
+
if (ledger.tree.principles[principleId]) {
|
|
119
|
+
result.skippedCount++;
|
|
120
|
+
result.details.push({
|
|
121
|
+
principleId,
|
|
122
|
+
status: 'skipped',
|
|
123
|
+
reason: 'Already exists in tree.principles',
|
|
124
|
+
});
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const treePrinciple = trainingStateToTreePrinciple(principleId, state, now);
|
|
130
|
+
createPrinciple(stateDir, treePrinciple);
|
|
131
|
+
|
|
132
|
+
result.migratedCount++;
|
|
133
|
+
result.details.push({
|
|
134
|
+
principleId,
|
|
135
|
+
status: 'migrated',
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (workspaceDir) {
|
|
139
|
+
SystemLogger.log(
|
|
140
|
+
workspaceDir,
|
|
141
|
+
'PRINCIPLE_TREE_MIGRATED',
|
|
142
|
+
`Migrated ${principleId} from trainingStore to tree.principles`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
result.errorCount++;
|
|
147
|
+
result.details.push({
|
|
148
|
+
principleId,
|
|
149
|
+
status: 'error',
|
|
150
|
+
reason: String(err),
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
if (workspaceDir) {
|
|
154
|
+
SystemLogger.log(
|
|
155
|
+
workspaceDir,
|
|
156
|
+
'PRINCIPLE_TREE_MIGRATION_ERROR',
|
|
157
|
+
`Failed to migrate ${principleId}: ${String(err)}`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (workspaceDir && result.migratedCount > 0) {
|
|
164
|
+
SystemLogger.log(
|
|
165
|
+
workspaceDir,
|
|
166
|
+
'PRINCIPLE_TREE_MIGRATION_COMPLETE',
|
|
167
|
+
`Migrated ${result.migratedCount} principles to tree.principles (${result.skippedCount} skipped, ${result.errorCount} errors)`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
} catch (err) {
|
|
171
|
+
if (workspaceDir) {
|
|
172
|
+
SystemLogger.log(
|
|
173
|
+
workspaceDir,
|
|
174
|
+
'PRINCIPLE_TREE_MIGRATION_FAILED',
|
|
175
|
+
`Migration failed: ${String(err)}`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Run migration if needed (called during plugin initialization)
|
|
185
|
+
*/
|
|
186
|
+
export function runMigrationIfNeeded(
|
|
187
|
+
stateDir: string,
|
|
188
|
+
workspaceDir?: string
|
|
189
|
+
): PrincipleTreeMigrationResult | null {
|
|
190
|
+
if (!needsMigration(stateDir)) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return migratePrincipleTree(stateDir, workspaceDir);
|
|
195
|
+
}
|
package/src/core/profile.ts
CHANGED
|
@@ -54,9 +54,11 @@ export const PROFILE_DEFAULTS = {
|
|
|
54
54
|
window_ms: 5 * 60 * 1000, // 5 minute window
|
|
55
55
|
high_risk_tools: ['run_shell_command', 'delete_file', 'move_file'],
|
|
56
56
|
},
|
|
57
|
-
custom_guards: [] as
|
|
57
|
+
custom_guards: [] as { pattern: string; message: string; severity: string }[],
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
61
|
+
// Reason: normalizeProfile handles arbitrary JSON profile shapes where static typing cannot capture runtime field existence
|
|
60
62
|
export function normalizeProfile(rawProfile: any): any {
|
|
61
63
|
const defaults = JSON.parse(JSON.stringify(PROFILE_DEFAULTS));
|
|
62
64
|
const warnings: string[] = [];
|
|
@@ -44,25 +44,12 @@ import * as fs from 'fs';
|
|
|
44
44
|
import * as path from 'path';
|
|
45
45
|
import * as crypto from 'crypto';
|
|
46
46
|
import { withLock } from '../utils/file-lock.js';
|
|
47
|
-
import type { WorkerProfile } from './model-deployment-registry.js';
|
|
48
47
|
import {
|
|
49
48
|
getCheckpoint,
|
|
50
49
|
getEvalSummary,
|
|
51
|
-
listEvalSummaries,
|
|
52
|
-
getCheckpointLineage,
|
|
53
50
|
} from './model-training-registry.js';
|
|
54
|
-
import {
|
|
55
|
-
|
|
56
|
-
getActiveCheckpointForProfile,
|
|
57
|
-
rollbackDeployment,
|
|
58
|
-
} from './model-deployment-registry.js';
|
|
59
|
-
import {
|
|
60
|
-
type TrainableWorkerProfile,
|
|
61
|
-
} from './external-training-contract.js';
|
|
62
|
-
import {
|
|
63
|
-
computeShadowStats,
|
|
64
|
-
type ShadowStats,
|
|
65
|
-
} from './shadow-observation-registry.js';
|
|
51
|
+
import { type TrainableWorkerProfile } from './external-training-contract.js';
|
|
52
|
+
import { computeShadowStats } from './shadow-observation-registry.js';
|
|
66
53
|
|
|
67
54
|
// ---------------------------------------------------------------------------
|
|
68
55
|
// Constants
|
|
@@ -83,6 +70,7 @@ export const DEFAULT_ALLOWED_MARGIN = 0.05;
|
|
|
83
70
|
* Allowed worker profiles for Phase 7 shadow rollout.
|
|
84
71
|
* Only bounded local workers eligible. local-reader first, local-editor deferred.
|
|
85
72
|
*/
|
|
73
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -- Reason: reserved for Phase 7 shadow rollout profile validation
|
|
86
74
|
const ALLOWED_ROLLOUT_PROFILES: readonly TrainableWorkerProfile[] = ['local-reader'];
|
|
87
75
|
|
|
88
76
|
/**
|
|
@@ -245,7 +233,8 @@ function writeRegistry(stateDir: string, registry: PromotionRegistry): void {
|
|
|
245
233
|
*/
|
|
246
234
|
function withPromotionRegistryLock<T>(
|
|
247
235
|
stateDir: string,
|
|
248
|
-
|
|
236
|
+
// eslint-disable-next-line no-unused-vars -- Reason: callback parameter name is type documentation, actual value passed at call site
|
|
237
|
+
fn: (_registry: PromotionRegistry) => T
|
|
249
238
|
): T {
|
|
250
239
|
const registryPath = getRegistryPath(stateDir);
|
|
251
240
|
return withLock(registryPath, () => {
|
|
@@ -329,7 +318,8 @@ export function evaluatePromotionGate(
|
|
|
329
318
|
): PromotionGateResult {
|
|
330
319
|
const {
|
|
331
320
|
checkpointId,
|
|
332
|
-
|
|
321
|
+
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars -- Reason: reserved for Phase 7 profile-based targeting
|
|
322
|
+
targetProfile: _targetProfile,
|
|
333
323
|
baselineMetrics,
|
|
334
324
|
minDelta = DEFAULT_MIN_DELTA,
|
|
335
325
|
allowedMargin = DEFAULT_ALLOWED_MARGIN,
|
|
@@ -380,7 +370,7 @@ export function evaluatePromotionGate(
|
|
|
380
370
|
}
|
|
381
371
|
|
|
382
372
|
// --- Check 4: Delta must be positive and above threshold ---
|
|
383
|
-
const delta = evalSummary
|
|
373
|
+
const {delta} = evalSummary;
|
|
384
374
|
const deltaCheck = {
|
|
385
375
|
actual: delta,
|
|
386
376
|
threshold: minDelta,
|
|
@@ -398,7 +388,9 @@ export function evaluatePromotionGate(
|
|
|
398
388
|
// PREFER real shadow evidence over eval verdict proxy
|
|
399
389
|
// Shadow evidence comes from actual runtime routing decisions
|
|
400
390
|
const shadowStats = computeShadowStats(stateDir, { checkpointId });
|
|
391
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in both if/else branches
|
|
401
392
|
let arbiterRejectRate: number;
|
|
393
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in both if/else branches
|
|
402
394
|
let arbiterRejectSource: 'shadow' | 'eval-proxy';
|
|
403
395
|
|
|
404
396
|
if (shadowStats && shadowStats.isStatisticallySignificant) {
|
|
@@ -432,7 +424,9 @@ export function evaluatePromotionGate(
|
|
|
432
424
|
|
|
433
425
|
// --- Check 6: Executability reject rate constraint ---
|
|
434
426
|
// PREFER real shadow evidence: escalation rate + profile rejection rate
|
|
427
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in both if/else branches
|
|
435
428
|
let executabilityRejectRate: number;
|
|
429
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in both if/else branches
|
|
436
430
|
let executabilityRejectSource: 'shadow' | 'eval-proxy';
|
|
437
431
|
|
|
438
432
|
if (shadowStats && shadowStats.isStatisticallySignificant) {
|
|
@@ -490,6 +484,7 @@ export function evaluatePromotionGate(
|
|
|
490
484
|
qualityCheck.passed;
|
|
491
485
|
|
|
492
486
|
// --- Suggest state based on checks ---
|
|
487
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in all branches
|
|
493
488
|
let suggestedState: PromotionState | undefined;
|
|
494
489
|
if (allPassed) {
|
|
495
490
|
suggestedState = 'candidate_only';
|
|
@@ -590,6 +585,7 @@ export function advancePromotion(
|
|
|
590
585
|
// - rejected → candidate_only/shadow_ready: allowed via re-evaluation
|
|
591
586
|
// (new eval data may reverse a previous rejection)
|
|
592
587
|
//
|
|
588
|
+
// eslint-disable-next-line @typescript-eslint/init-declarations -- assigned in all branches
|
|
593
589
|
let targetState: PromotionState;
|
|
594
590
|
if (!gateResult.passes) {
|
|
595
591
|
targetState = 'rejected';
|