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.
Files changed (233) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +66 -0
  3. package/esbuild.config.js +1 -1
  4. package/openclaw.plugin.json +4 -4
  5. package/package.json +2 -3
  6. package/run-nocturnal.mjs +30 -0
  7. package/scripts/db-migrate.mjs +170 -0
  8. package/scripts/sync-plugin.mjs +250 -6
  9. package/src/commands/archive-impl.ts +136 -0
  10. package/src/commands/capabilities.ts +4 -2
  11. package/src/commands/context.ts +5 -1
  12. package/src/commands/disable-impl.ts +151 -0
  13. package/src/commands/evolution-status.ts +64 -19
  14. package/src/commands/export.ts +8 -6
  15. package/src/commands/focus.ts +8 -20
  16. package/src/commands/nocturnal-review.ts +5 -7
  17. package/src/commands/nocturnal-rollout.ts +1 -12
  18. package/src/commands/nocturnal-train.ts +21 -47
  19. package/src/commands/pain.ts +10 -5
  20. package/src/commands/principle-rollback.ts +4 -2
  21. package/src/commands/promote-impl.ts +274 -0
  22. package/src/commands/rollback-impl.ts +234 -0
  23. package/src/commands/rollback.ts +6 -3
  24. package/src/commands/samples.ts +2 -0
  25. package/src/commands/thinking-os.ts +3 -4
  26. package/src/commands/workflow-debug.ts +2 -1
  27. package/src/config/errors.ts +1 -0
  28. package/src/core/AGENTS.md +34 -0
  29. package/src/core/adaptive-thresholds.ts +4 -3
  30. package/src/core/code-implementation-storage.ts +241 -0
  31. package/src/core/config.ts +5 -2
  32. package/src/core/control-ui-db.ts +29 -10
  33. package/src/core/detection-funnel.ts +12 -7
  34. package/src/core/diagnostician-task-store.ts +156 -0
  35. package/src/core/dictionary.ts +4 -4
  36. package/src/core/empathy-keyword-matcher.ts +7 -3
  37. package/src/core/empathy-types.ts +13 -2
  38. package/src/core/event-log.ts +14 -6
  39. package/src/core/evolution-engine.ts +27 -31
  40. package/src/core/evolution-logger.ts +3 -2
  41. package/src/core/evolution-reducer.ts +110 -31
  42. package/src/core/evolution-types.ts +10 -0
  43. package/src/core/external-training-contract.ts +1 -0
  44. package/src/core/focus-history.ts +38 -24
  45. package/src/core/hygiene/tracker.ts +10 -6
  46. package/src/core/init.ts +5 -2
  47. package/src/core/migration.ts +3 -3
  48. package/src/core/model-deployment-registry.ts +6 -4
  49. package/src/core/model-training-registry.ts +5 -3
  50. package/src/core/nocturnal-arbiter.ts +13 -14
  51. package/src/core/nocturnal-artifact-lineage.ts +117 -0
  52. package/src/core/nocturnal-artificer.ts +257 -0
  53. package/src/core/nocturnal-candidate-scoring.ts +4 -2
  54. package/src/core/nocturnal-compliance.ts +67 -19
  55. package/src/core/nocturnal-dataset.ts +95 -2
  56. package/src/core/nocturnal-executability.ts +2 -3
  57. package/src/core/nocturnal-export.ts +6 -3
  58. package/src/core/nocturnal-rule-implementation-validator.ts +245 -0
  59. package/src/core/nocturnal-trajectory-extractor.ts +10 -3
  60. package/src/core/nocturnal-trinity.ts +319 -61
  61. package/src/core/pain-context-extractor.ts +29 -15
  62. package/src/core/pain.ts +7 -5
  63. package/src/core/path-resolver.ts +16 -15
  64. package/src/core/paths.ts +2 -1
  65. package/src/core/pd-task-reconciler.ts +463 -0
  66. package/src/core/pd-task-service.ts +42 -0
  67. package/src/core/pd-task-store.ts +77 -0
  68. package/src/core/pd-task-types.ts +128 -0
  69. package/src/core/principle-internalization/deprecated-readiness.ts +91 -0
  70. package/src/core/principle-internalization/internalization-routing-policy.ts +208 -0
  71. package/src/core/principle-internalization/lifecycle-metrics.ts +149 -0
  72. package/src/core/principle-internalization/lifecycle-read-model.ts +243 -0
  73. package/src/core/principle-internalization/lifecycle-refresh.ts +11 -0
  74. package/src/core/principle-internalization/principle-lifecycle-service.ts +167 -0
  75. package/src/core/principle-training-state.ts +95 -370
  76. package/src/core/principle-tree-ledger.ts +733 -0
  77. package/src/core/principle-tree-migration.ts +195 -0
  78. package/src/core/profile.ts +3 -1
  79. package/src/core/promotion-gate.ts +14 -18
  80. package/src/core/replay-engine.ts +562 -0
  81. package/src/core/risk-calculator.ts +6 -4
  82. package/src/core/rule-host-helpers.ts +39 -0
  83. package/src/core/rule-host-types.ts +82 -0
  84. package/src/core/rule-host.ts +245 -0
  85. package/src/core/rule-implementation-runtime.ts +38 -0
  86. package/src/core/schema/db-types.ts +16 -0
  87. package/src/core/schema/index.ts +26 -0
  88. package/src/core/schema/migration-runner.ts +207 -0
  89. package/src/core/schema/migrations/001-init-trajectory.ts +211 -0
  90. package/src/core/schema/migrations/002-init-central.ts +122 -0
  91. package/src/core/schema/migrations/003-init-workflow.ts +55 -0
  92. package/src/core/schema/migrations/004-add-thinking-and-gfi.ts +74 -0
  93. package/src/core/schema/migrations/index.ts +31 -0
  94. package/src/core/schema/schema-definitions.ts +650 -0
  95. package/src/core/session-tracker.ts +6 -4
  96. package/src/core/shadow-observation-registry.ts +6 -3
  97. package/src/core/system-logger.ts +2 -2
  98. package/src/core/thinking-models.ts +182 -46
  99. package/src/core/thinking-os-parser.ts +156 -0
  100. package/src/core/training-program.ts +7 -7
  101. package/src/core/trajectory.ts +42 -36
  102. package/src/core/workspace-context.ts +77 -11
  103. package/src/core/workspace-dir-validation.ts +152 -0
  104. package/src/hooks/AGENTS.md +31 -0
  105. package/src/hooks/bash-risk.ts +3 -1
  106. package/src/hooks/edit-verification.ts +9 -5
  107. package/src/hooks/gate-block-helper.ts +5 -1
  108. package/src/hooks/gate.ts +152 -5
  109. package/src/hooks/gfi-gate.ts +9 -2
  110. package/src/hooks/lifecycle-routing.ts +124 -0
  111. package/src/hooks/lifecycle.ts +12 -12
  112. package/src/hooks/llm.ts +17 -109
  113. package/src/hooks/message-sanitize.ts +5 -3
  114. package/src/hooks/pain.ts +19 -15
  115. package/src/hooks/progressive-trust-gate.ts +7 -1
  116. package/src/hooks/prompt.ts +169 -60
  117. package/src/hooks/subagent.ts +5 -4
  118. package/src/hooks/thinking-checkpoint.ts +2 -0
  119. package/src/hooks/trajectory-collector.ts +15 -12
  120. package/src/http/principles-console-route.ts +31 -68
  121. package/src/i18n/commands.ts +2 -2
  122. package/src/index.ts +130 -40
  123. package/src/service/central-database.ts +131 -43
  124. package/src/service/central-health-service.ts +47 -0
  125. package/src/service/central-overview-service.ts +135 -0
  126. package/src/service/central-sync-service.ts +87 -0
  127. package/src/service/control-ui-query-service.ts +46 -36
  128. package/src/service/event-log-auditor.ts +261 -0
  129. package/src/service/evolution-query-service.ts +23 -22
  130. package/src/service/evolution-worker.ts +565 -261
  131. package/src/service/health-query-service.ts +213 -36
  132. package/src/service/nocturnal-runtime.ts +8 -4
  133. package/src/service/nocturnal-service.ts +503 -59
  134. package/src/service/nocturnal-target-selector.ts +5 -7
  135. package/src/service/runtime-summary-service.ts +2 -1
  136. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +25 -336
  137. package/src/service/subagent-workflow/dynamic-timeout.ts +30 -0
  138. package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +48 -386
  139. package/src/service/subagent-workflow/index.ts +2 -0
  140. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +169 -284
  141. package/src/service/subagent-workflow/runtime-direct-driver.ts +114 -16
  142. package/src/service/subagent-workflow/subagent-error-utils.ts +25 -0
  143. package/src/service/subagent-workflow/types.ts +9 -4
  144. package/src/service/subagent-workflow/workflow-manager-base.ts +573 -0
  145. package/src/service/subagent-workflow/workflow-store.ts +71 -11
  146. package/src/service/trajectory-service.ts +2 -1
  147. package/src/tools/critique-prompt.ts +1 -1
  148. package/src/tools/deep-reflect.ts +175 -209
  149. package/src/tools/model-index.ts +2 -1
  150. package/src/types/event-types.ts +2 -2
  151. package/src/types/principle-tree-schema.ts +29 -23
  152. package/src/utils/file-lock.ts +5 -3
  153. package/src/utils/io.ts +5 -2
  154. package/src/utils/nlp.ts +5 -46
  155. package/src/utils/node-vm-polyfill.ts +11 -0
  156. package/src/utils/plugin-logger.ts +2 -0
  157. package/src/utils/retry.ts +572 -0
  158. package/src/utils/subagent-probe.ts +1 -1
  159. package/templates/langs/en/core/AGENTS.md +0 -13
  160. package/templates/langs/en/core/SOUL.md +1 -31
  161. package/templates/langs/en/core/TOOLS.md +0 -4
  162. package/templates/langs/en/principles/THINKING_OS.md +77 -0
  163. package/templates/langs/en/skills/admin/SKILL.md +0 -1
  164. package/templates/langs/en/skills/evolution-framework-update/SKILL.md +1 -1
  165. package/templates/langs/en/skills/pd-diagnostician/SKILL.md +18 -5
  166. package/templates/langs/zh/core/AGENTS.md +0 -22
  167. package/templates/langs/zh/core/SOUL.md +1 -31
  168. package/templates/langs/zh/core/TOOLS.md +0 -4
  169. package/templates/langs/zh/principles/THINKING_OS.md +77 -0
  170. package/templates/langs/zh/skills/admin/SKILL.md +0 -1
  171. package/templates/langs/zh/skills/evolution-framework-update/SKILL.md +1 -1
  172. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +25 -4
  173. package/tests/commands/evolution-status.test.ts +119 -0
  174. package/tests/commands/implementation-lifecycle.test.ts +362 -0
  175. package/tests/core/code-implementation-storage.test.ts +398 -0
  176. package/tests/core/evolution-reducer.detector-metadata.test.ts +28 -28
  177. package/tests/core/nocturnal-artifact-lineage.test.ts +53 -0
  178. package/tests/core/nocturnal-artificer.test.ts +241 -0
  179. package/tests/core/nocturnal-compliance-p-principles.test.ts +133 -0
  180. package/tests/core/nocturnal-rule-implementation-validator.test.ts +127 -0
  181. package/tests/core/pd-task-store.test.ts +126 -0
  182. package/tests/core/principle-internalization/deprecated-readiness.test.ts +193 -0
  183. package/tests/core/principle-internalization/internalization-routing-policy.test.ts +212 -0
  184. package/tests/core/principle-internalization/lifecycle-metrics.test.ts +350 -0
  185. package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +211 -0
  186. package/tests/core/principle-training-state.test.ts +228 -1
  187. package/tests/core/principle-tree-ledger.test.ts +423 -0
  188. package/tests/core/regression-v1-9-1.test.ts +265 -0
  189. package/tests/core/replay-engine.test.ts +234 -0
  190. package/tests/core/rule-host-helpers.test.ts +120 -0
  191. package/tests/core/rule-host.test.ts +389 -0
  192. package/tests/core/rule-implementation-runtime.test.ts +64 -0
  193. package/tests/core/workspace-context.test.ts +53 -0
  194. package/tests/core/workspace-dir-validation.test.ts +272 -0
  195. package/tests/hooks/gate-rule-host-pipeline.test.ts +385 -0
  196. package/tests/hooks/pain.test.ts +74 -10
  197. package/tests/hooks/prompt.test.ts +63 -1
  198. package/tests/integration/principle-lifecycle.e2e.test.ts +197 -0
  199. package/tests/integration/tool-hooks-workspace-dir.e2e.test.ts +211 -0
  200. package/tests/service/data-endpoints-regression.test.ts +834 -0
  201. package/tests/service/evolution-worker.test.ts +0 -123
  202. package/tests/service/nocturnal-service-code-candidate.test.ts +330 -0
  203. package/tests/utils/nlp.test.ts +1 -19
  204. package/tests/utils/retry.test.ts +327 -0
  205. package/ui/src/App.tsx +1 -1
  206. package/ui/src/api.ts +4 -0
  207. package/ui/src/charts.tsx +366 -0
  208. package/ui/src/components/WorkspaceConfig.tsx +107 -75
  209. package/ui/src/i18n/ui.ts +89 -31
  210. package/ui/src/pages/EvolutionPage.tsx +1 -1
  211. package/ui/src/pages/OverviewPage.tsx +441 -81
  212. package/ui/src/pages/ThinkingModelsPage.tsx +287 -69
  213. package/ui/src/styles.css +43 -0
  214. package/ui/src/types.ts +17 -1
  215. package/src/agents/nocturnal-dreamer.md +0 -152
  216. package/src/agents/nocturnal-philosopher.md +0 -138
  217. package/src/agents/nocturnal-reflector.md +0 -126
  218. package/src/agents/nocturnal-scribe.md +0 -164
  219. package/templates/workspace/.principles/00-kernel.md +0 -51
  220. package/templates/workspace/.principles/DECISION_POLICY.json +0 -44
  221. package/templates/workspace/.principles/PRINCIPLES.md +0 -20
  222. package/templates/workspace/.principles/PROFILE.json +0 -54
  223. package/templates/workspace/.principles/PROFILE.schema.json +0 -56
  224. package/templates/workspace/.principles/THINKING_OS.md +0 -64
  225. package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +0 -7
  226. package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +0 -9
  227. package/templates/workspace/.principles/models/_INDEX.md +0 -27
  228. package/templates/workspace/.principles/models/first_principles.md +0 -62
  229. package/templates/workspace/.principles/models/marketing_4p.md +0 -52
  230. package/templates/workspace/.principles/models/porter_five.md +0 -63
  231. package/templates/workspace/.principles/models/swot.md +0 -60
  232. package/templates/workspace/.principles/models/user_story_map.md +0 -63
  233. 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
+ }
@@ -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 Array<{ pattern: string; message: string; severity: string }>,
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
- getDeployment,
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
- fn: (registry: PromotionRegistry) => T
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
- targetProfile,
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.delta;
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';