principles-disciple 1.8.0 → 1.8.2
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/ADVANCED_CONFIG_ZH.md +97 -0
- package/AGENT_INSTALL.md +173 -0
- package/AGENT_INSTALL_EN.md +173 -0
- package/INSTALL.md +256 -0
- package/SKILL.md +63 -0
- package/docs/COMMAND_REFERENCE.md +76 -0
- package/docs/COMMAND_REFERENCE_EN.md +79 -0
- package/esbuild.config.js +75 -0
- package/openclaw.plugin.json +6 -1
- package/package.json +13 -15
- package/scripts/build-web.mjs +46 -0
- package/scripts/install-dependencies.cjs +47 -0
- package/scripts/sync-plugin.mjs +802 -0
- package/scripts/verify-build.mjs +109 -0
- package/src/agents/nocturnal-dreamer.md +152 -0
- package/src/agents/nocturnal-philosopher.md +138 -0
- package/src/agents/nocturnal-reflector.md +126 -0
- package/src/agents/nocturnal-scribe.md +164 -0
- package/src/commands/capabilities.ts +85 -0
- package/{dist/commands/context.js → src/commands/context.ts} +78 -38
- package/src/commands/evolution-status.ts +146 -0
- package/src/commands/export.ts +111 -0
- package/src/commands/focus.ts +533 -0
- package/src/commands/nocturnal-review.ts +311 -0
- package/src/commands/nocturnal-rollout.ts +763 -0
- package/src/commands/nocturnal-train.ts +1002 -0
- package/{dist/commands/pain.js → src/commands/pain.ts} +68 -49
- package/src/commands/principle-rollback.ts +27 -0
- package/{dist/commands/rollback.js → src/commands/rollback.ts} +44 -12
- package/src/commands/samples.ts +60 -0
- package/src/commands/strategy.ts +38 -0
- package/{dist/commands/thinking-os.js → src/commands/thinking-os.ts} +59 -36
- package/src/commands/workflow-debug.ts +128 -0
- package/{dist/config/defaults/runtime.js → src/config/defaults/runtime.ts} +12 -5
- package/src/config/errors.ts +163 -0
- package/{dist/config/index.d.ts → src/config/index.ts} +2 -1
- package/src/constants/diagnostician.ts +66 -0
- package/src/constants/tools.ts +62 -0
- package/src/core/adaptive-thresholds.ts +476 -0
- package/{dist/core/config-service.js → src/core/config-service.ts} +7 -4
- package/{dist/core/config.js → src/core/config.ts} +158 -46
- package/src/core/control-ui-db.ts +435 -0
- package/{dist/core/detection-funnel.js → src/core/detection-funnel.ts} +36 -21
- package/{dist/core/detection-service.js → src/core/detection-service.ts} +7 -4
- package/{dist/core/dictionary-service.js → src/core/dictionary-service.ts} +7 -4
- package/{dist/core/dictionary.js → src/core/dictionary.ts} +57 -34
- package/src/core/empathy-keyword-matcher.ts +327 -0
- package/src/core/empathy-types.ts +218 -0
- package/src/core/event-log.ts +544 -0
- package/src/core/evolution-engine.ts +612 -0
- package/src/core/evolution-logger.ts +353 -0
- package/src/core/evolution-migration.ts +77 -0
- package/src/core/evolution-reducer.ts +731 -0
- package/src/core/evolution-types.ts +456 -0
- package/src/core/external-training-contract.ts +527 -0
- package/src/core/focus-history.ts +1458 -0
- package/src/core/hygiene/tracker.ts +117 -0
- package/{dist/core/init.js → src/core/init.ts} +39 -26
- package/src/core/local-worker-routing.ts +617 -0
- package/{dist/core/migration.js → src/core/migration.ts} +18 -11
- package/src/core/model-deployment-registry.ts +722 -0
- package/src/core/model-training-registry.ts +813 -0
- package/src/core/nocturnal-arbiter.ts +706 -0
- package/src/core/nocturnal-candidate-scoring.ts +392 -0
- package/src/core/nocturnal-compliance.ts +1075 -0
- package/src/core/nocturnal-dataset.ts +668 -0
- package/src/core/nocturnal-executability.ts +428 -0
- package/src/core/nocturnal-export.ts +390 -0
- package/{dist/core/nocturnal-paths.js → src/core/nocturnal-paths.ts} +49 -23
- package/src/core/nocturnal-trajectory-extractor.ts +484 -0
- package/src/core/nocturnal-trinity.ts +1384 -0
- package/src/core/pain.ts +122 -0
- package/{dist/core/path-resolver.js → src/core/path-resolver.ts} +157 -36
- package/{dist/core/paths.js → src/core/paths.ts} +13 -4
- package/src/core/principle-training-state.ts +450 -0
- package/src/core/profile.ts +226 -0
- package/src/core/promotion-gate.ts +822 -0
- package/{dist/core/risk-calculator.js → src/core/risk-calculator.ts} +42 -16
- package/{dist/core/session-tracker.js → src/core/session-tracker.ts} +185 -63
- package/src/core/shadow-observation-registry.ts +534 -0
- package/{dist/core/system-logger.js → src/core/system-logger.ts} +9 -5
- package/src/core/thinking-models.ts +217 -0
- package/src/core/training-program.ts +630 -0
- package/src/core/trajectory-types.ts +243 -0
- package/src/core/trajectory.ts +1673 -0
- package/{dist/core/workspace-context.js → src/core/workspace-context.ts} +57 -32
- package/src/hooks/bash-risk.ts +171 -0
- package/src/hooks/edit-verification.ts +295 -0
- package/src/hooks/gate-block-helper.ts +160 -0
- package/src/hooks/gate.ts +210 -0
- package/src/hooks/gfi-gate.ts +177 -0
- package/src/hooks/lifecycle.ts +326 -0
- package/{dist/hooks/llm.js → src/hooks/llm.ts} +166 -139
- package/src/hooks/message-sanitize.ts +45 -0
- package/src/hooks/pain.ts +384 -0
- package/src/hooks/progressive-trust-gate.ts +174 -0
- package/src/hooks/prompt.ts +920 -0
- package/src/hooks/subagent.ts +207 -0
- package/src/hooks/thinking-checkpoint.ts +73 -0
- package/src/hooks/trajectory-collector.ts +290 -0
- package/src/http/principles-console-route.ts +716 -0
- package/src/i18n/commands.ts +117 -0
- package/src/index.ts +694 -0
- package/src/service/central-database.ts +831 -0
- package/src/service/control-ui-query-service.ts +888 -0
- package/src/service/evolution-query-service.ts +405 -0
- package/src/service/evolution-worker.ts +1646 -0
- package/src/service/health-query-service.ts +836 -0
- package/{dist/service/nocturnal-runtime.js → src/service/nocturnal-runtime.ts} +263 -36
- package/src/service/nocturnal-service.ts +1015 -0
- package/src/service/nocturnal-target-selector.ts +532 -0
- package/src/service/phase3-input-filter.ts +237 -0
- package/src/service/runtime-summary-service.ts +757 -0
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +513 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +603 -0
- package/src/service/subagent-workflow/index.ts +51 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +856 -0
- package/src/service/subagent-workflow/runtime-direct-driver.ts +166 -0
- package/src/service/subagent-workflow/types.ts +378 -0
- package/src/service/subagent-workflow/workflow-store.ts +328 -0
- package/src/service/trajectory-service.ts +15 -0
- package/{dist/tools/critique-prompt.js → src/tools/critique-prompt.ts} +25 -8
- package/src/tools/deep-reflect.ts +349 -0
- package/{dist/tools/model-index.js → src/tools/model-index.ts} +33 -17
- package/src/types/event-types.ts +453 -0
- package/src/types/hygiene-types.ts +31 -0
- package/src/types/principle-tree-schema.ts +244 -0
- package/src/types/runtime-summary.ts +49 -0
- package/src/types.ts +74 -0
- package/src/utils/file-lock.ts +391 -0
- package/{dist/utils/glob-match.js → src/utils/glob-match.ts} +21 -20
- package/{dist/utils/hashing.js → src/utils/hashing.ts} +6 -4
- package/src/utils/io.ts +110 -0
- package/{dist/utils/nlp.js → src/utils/nlp.ts} +19 -12
- package/{dist/utils/plugin-logger.js → src/utils/plugin-logger.ts} +33 -8
- package/src/utils/subagent-probe.ts +94 -0
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +70 -1
- package/templates/pain_settings.json +2 -1
- package/tests/README.md +120 -0
- package/tests/build-artifacts.test.ts +111 -0
- package/tests/commands/evolution-status.test.ts +222 -0
- package/tests/commands/evolver.test.ts +22 -0
- package/tests/commands/export.test.ts +78 -0
- package/tests/commands/nocturnal-review.test.ts +448 -0
- package/tests/commands/nocturnal-train.test.ts +97 -0
- package/tests/commands/pain.test.ts +108 -0
- package/tests/commands/samples.test.ts +65 -0
- package/tests/commands/strategy.test.ts +34 -0
- package/tests/commands/thinking-os.test.ts +88 -0
- package/tests/core/adaptive-thresholds.test.ts +261 -0
- package/tests/core/config-service.test.ts +89 -0
- package/tests/core/config.test.ts +90 -0
- package/tests/core/control-ui-db.test.ts +75 -0
- package/tests/core/core-template-guidance.test.ts +21 -0
- package/tests/core/detection-funnel.test.ts +63 -0
- package/tests/core/detection-service.test.ts +50 -0
- package/tests/core/dictionary-service.test.ts +116 -0
- package/tests/core/dictionary.test.ts +168 -0
- package/tests/core/empathy-keyword-matcher.test.ts +209 -0
- package/tests/core/event-log.test.ts +181 -0
- package/tests/core/evolution-e2e.test.ts +58 -0
- package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
- package/tests/core/evolution-engine.test.ts +562 -0
- package/tests/core/evolution-logger.test.ts +148 -0
- package/tests/core/evolution-migration.test.ts +50 -0
- package/tests/core/evolution-paths.test.ts +21 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
- package/tests/core/evolution-reducer.test.ts +180 -0
- package/tests/core/evolution-types-loop.test.ts +48 -0
- package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
- package/tests/core/external-training-contract.test.ts +463 -0
- package/tests/core/focus-history.test.ts +682 -0
- package/tests/core/init-flatten.test.ts +69 -0
- package/tests/core/init-refactor.test.ts +87 -0
- package/tests/core/init-v1.3.test.ts +46 -0
- package/tests/core/init.test.ts +190 -0
- package/tests/core/local-worker-routing.test.ts +757 -0
- package/tests/core/migration.test.ts +84 -0
- package/tests/core/model-deployment-registry.test.ts +845 -0
- package/tests/core/model-training-registry.test.ts +889 -0
- package/tests/core/nocturnal-arbiter.test.ts +494 -0
- package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
- package/tests/core/nocturnal-compliance.test.ts +646 -0
- package/tests/core/nocturnal-dataset.test.ts +892 -0
- package/tests/core/nocturnal-executability.test.ts +357 -0
- package/tests/core/nocturnal-export.test.ts +462 -0
- package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
- package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
- package/tests/core/nocturnal-trinity.test.ts +953 -0
- package/tests/core/pain.test.ts +33 -0
- package/tests/core/path-resolver.test.ts +57 -0
- package/tests/core/paths-refactor.test.ts +42 -0
- package/tests/core/phase7-rollout-integration.test.ts +477 -0
- package/tests/core/principle-training-state.test.ts +712 -0
- package/tests/core/profile.test.ts +56 -0
- package/tests/core/promotion-gate.test.ts +556 -0
- package/tests/core/risk-calculator.test.ts +168 -0
- package/tests/core/session-tracker.test.ts +191 -0
- package/tests/core/training-program.test.ts +472 -0
- package/tests/core/trajectory.test.ts +265 -0
- package/tests/core/workspace-context-factory.test.ts +18 -0
- package/tests/core/workspace-context.test.ts +134 -0
- package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
- package/tests/fixtures/production-compatibility.test.ts +147 -0
- package/tests/fixtures/production-mock-generator.ts +282 -0
- package/tests/hooks/bash-risk-integration.test.ts +137 -0
- package/tests/hooks/bash-risk.test.ts +81 -0
- package/tests/hooks/edit-verification.test.ts +678 -0
- package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
- package/tests/hooks/gate-edit-verification.test.ts +435 -0
- package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
- package/tests/hooks/gate.test.ts +271 -0
- package/tests/hooks/gfi-gate-unit.test.ts +422 -0
- package/tests/hooks/gfi-gate.test.ts +669 -0
- package/tests/hooks/lifecycle.test.ts +248 -0
- package/tests/hooks/llm.test.ts +308 -0
- package/tests/hooks/message-sanitize.test.ts +36 -0
- package/tests/hooks/pain.test.ts +141 -0
- package/tests/hooks/progressive-trust-gate.test.ts +277 -0
- package/tests/hooks/prompt.test.ts +1411 -0
- package/tests/hooks/subagent.test.ts +467 -0
- package/tests/hooks/thinking-gate.test.ts +313 -0
- package/tests/http/principles-console-route.test.ts +140 -0
- package/tests/hygiene-tracker.test.ts +77 -0
- package/tests/index.integration.test.ts +179 -0
- package/tests/index.shadow-routing.integration.test.ts +140 -0
- package/tests/index.test.ts +9 -0
- package/tests/integration/empathy-workflow-integration.test.ts +627 -0
- package/tests/service/control-ui-query-service.test.ts +121 -0
- package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
- package/tests/service/evolution-worker.test.ts +585 -0
- package/tests/service/nocturnal-runtime.test.ts +470 -0
- package/tests/service/nocturnal-service.test.ts +577 -0
- package/tests/service/nocturnal-target-selector.test.ts +615 -0
- package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
- package/tests/service/phase3-input-filter.test.ts +289 -0
- package/tests/service/runtime-summary-service.test.ts +919 -0
- package/tests/task-compliance.test.ts +166 -0
- package/tests/test-utils.ts +48 -0
- package/tests/tools/critique-prompt.test.ts +260 -0
- package/tests/tools/deep-reflect.test.ts +232 -0
- package/tests/tools/model-index.test.ts +246 -0
- package/tests/ui/app.test.tsx +114 -0
- package/tests/utils/file-lock.test.ts +407 -0
- package/tests/utils/hashing.test.ts +32 -0
- package/tests/utils/io.test.ts +39 -0
- package/tests/utils/nlp.test.ts +53 -0
- package/tests/utils/plugin-logger.test.ts +156 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/ui/src/App.tsx +45 -0
- package/ui/src/api.ts +216 -0
- package/ui/src/charts.tsx +586 -0
- package/ui/src/components/ErrorState.tsx +6 -0
- package/ui/src/components/Loading.tsx +13 -0
- package/ui/src/components/ProtectedRoute.tsx +12 -0
- package/ui/src/components/Shell.tsx +91 -0
- package/ui/src/components/WorkspaceConfig.tsx +146 -0
- package/ui/src/components/index.ts +5 -0
- package/ui/src/context/auth.tsx +80 -0
- package/ui/src/context/theme.tsx +66 -0
- package/ui/src/hooks/useAutoRefresh.ts +39 -0
- package/ui/src/i18n/ui.ts +363 -0
- package/ui/src/main.tsx +16 -0
- package/ui/src/pages/EvolutionPage.tsx +352 -0
- package/ui/src/pages/FeedbackPage.tsx +140 -0
- package/ui/src/pages/GateMonitorPage.tsx +136 -0
- package/ui/src/pages/LoginPage.tsx +88 -0
- package/ui/src/pages/OverviewPage.tsx +238 -0
- package/ui/src/pages/SamplesPage.tsx +174 -0
- package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
- package/ui/src/styles.css +1661 -0
- package/ui/src/types.ts +368 -0
- package/ui/src/utils/format.ts +15 -0
- package/vitest.config.ts +23 -0
- package/dist/commands/capabilities.d.ts +0 -3
- package/dist/commands/capabilities.js +0 -73
- package/dist/commands/context.d.ts +0 -5
- package/dist/commands/evolution-status.d.ts +0 -4
- package/dist/commands/evolution-status.js +0 -117
- package/dist/commands/evolver.d.ts +0 -9
- package/dist/commands/evolver.js +0 -26
- package/dist/commands/export.d.ts +0 -2
- package/dist/commands/export.js +0 -98
- package/dist/commands/focus.d.ts +0 -14
- package/dist/commands/focus.js +0 -457
- package/dist/commands/nocturnal-review.d.ts +0 -24
- package/dist/commands/nocturnal-review.js +0 -265
- package/dist/commands/nocturnal-rollout.d.ts +0 -27
- package/dist/commands/nocturnal-rollout.js +0 -671
- package/dist/commands/nocturnal-train.d.ts +0 -25
- package/dist/commands/nocturnal-train.js +0 -919
- package/dist/commands/pain.d.ts +0 -5
- package/dist/commands/principle-rollback.d.ts +0 -4
- package/dist/commands/principle-rollback.js +0 -22
- package/dist/commands/rollback.d.ts +0 -19
- package/dist/commands/samples.d.ts +0 -2
- package/dist/commands/samples.js +0 -55
- package/dist/commands/strategy.d.ts +0 -3
- package/dist/commands/strategy.js +0 -29
- package/dist/commands/thinking-os.d.ts +0 -2
- package/dist/config/defaults/runtime.d.ts +0 -40
- package/dist/config/errors.d.ts +0 -84
- package/dist/config/errors.js +0 -94
- package/dist/config/index.js +0 -7
- package/dist/constants/diagnostician.d.ts +0 -12
- package/dist/constants/diagnostician.js +0 -56
- package/dist/constants/tools.d.ts +0 -17
- package/dist/constants/tools.js +0 -54
- package/dist/core/adaptive-thresholds.d.ts +0 -186
- package/dist/core/adaptive-thresholds.js +0 -300
- package/dist/core/config-service.d.ts +0 -15
- package/dist/core/config.d.ts +0 -127
- package/dist/core/control-ui-db.d.ts +0 -95
- package/dist/core/control-ui-db.js +0 -292
- package/dist/core/detection-funnel.d.ts +0 -33
- package/dist/core/detection-service.d.ts +0 -15
- package/dist/core/dictionary-service.d.ts +0 -15
- package/dist/core/dictionary.d.ts +0 -38
- package/dist/core/event-log.d.ts +0 -82
- package/dist/core/event-log.js +0 -463
- package/dist/core/evolution-engine.d.ts +0 -118
- package/dist/core/evolution-engine.js +0 -464
- package/dist/core/evolution-logger.d.ts +0 -137
- package/dist/core/evolution-logger.js +0 -256
- package/dist/core/evolution-migration.d.ts +0 -5
- package/dist/core/evolution-migration.js +0 -65
- package/dist/core/evolution-reducer.d.ts +0 -98
- package/dist/core/evolution-reducer.js +0 -465
- package/dist/core/evolution-types.d.ts +0 -287
- package/dist/core/evolution-types.js +0 -78
- package/dist/core/external-training-contract.d.ts +0 -276
- package/dist/core/external-training-contract.js +0 -269
- package/dist/core/focus-history.d.ts +0 -210
- package/dist/core/focus-history.js +0 -1185
- package/dist/core/hygiene/tracker.d.ts +0 -22
- package/dist/core/hygiene/tracker.js +0 -106
- package/dist/core/init.d.ts +0 -12
- package/dist/core/local-worker-routing.d.ts +0 -175
- package/dist/core/local-worker-routing.js +0 -525
- package/dist/core/migration.d.ts +0 -6
- package/dist/core/model-deployment-registry.d.ts +0 -218
- package/dist/core/model-deployment-registry.js +0 -503
- package/dist/core/model-training-registry.d.ts +0 -295
- package/dist/core/model-training-registry.js +0 -475
- package/dist/core/nocturnal-arbiter.d.ts +0 -159
- package/dist/core/nocturnal-arbiter.js +0 -534
- package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
- package/dist/core/nocturnal-candidate-scoring.js +0 -266
- package/dist/core/nocturnal-compliance.d.ts +0 -175
- package/dist/core/nocturnal-compliance.js +0 -824
- package/dist/core/nocturnal-dataset.d.ts +0 -224
- package/dist/core/nocturnal-dataset.js +0 -443
- package/dist/core/nocturnal-executability.d.ts +0 -85
- package/dist/core/nocturnal-executability.js +0 -331
- package/dist/core/nocturnal-export.d.ts +0 -124
- package/dist/core/nocturnal-export.js +0 -275
- package/dist/core/nocturnal-paths.d.ts +0 -124
- package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
- package/dist/core/nocturnal-trajectory-extractor.js +0 -307
- package/dist/core/nocturnal-trinity.d.ts +0 -311
- package/dist/core/nocturnal-trinity.js +0 -880
- package/dist/core/pain.d.ts +0 -4
- package/dist/core/pain.js +0 -70
- package/dist/core/path-resolver.d.ts +0 -46
- package/dist/core/paths.d.ts +0 -65
- package/dist/core/principle-training-state.d.ts +0 -121
- package/dist/core/principle-training-state.js +0 -321
- package/dist/core/profile.d.ts +0 -62
- package/dist/core/profile.js +0 -210
- package/dist/core/promotion-gate.d.ts +0 -238
- package/dist/core/promotion-gate.js +0 -529
- package/dist/core/risk-calculator.d.ts +0 -22
- package/dist/core/session-tracker.d.ts +0 -99
- package/dist/core/shadow-observation-registry.d.ts +0 -217
- package/dist/core/shadow-observation-registry.js +0 -308
- package/dist/core/system-logger.d.ts +0 -8
- package/dist/core/thinking-models.d.ts +0 -38
- package/dist/core/thinking-models.js +0 -170
- package/dist/core/training-program.d.ts +0 -233
- package/dist/core/training-program.js +0 -433
- package/dist/core/trajectory.d.ts +0 -411
- package/dist/core/trajectory.js +0 -1307
- package/dist/core/workspace-context.d.ts +0 -71
- package/dist/hooks/bash-risk.d.ts +0 -57
- package/dist/hooks/bash-risk.js +0 -137
- package/dist/hooks/edit-verification.d.ts +0 -62
- package/dist/hooks/edit-verification.js +0 -256
- package/dist/hooks/gate-block-helper.d.ts +0 -44
- package/dist/hooks/gate-block-helper.js +0 -119
- package/dist/hooks/gate.d.ts +0 -24
- package/dist/hooks/gate.js +0 -173
- package/dist/hooks/gfi-gate.d.ts +0 -40
- package/dist/hooks/gfi-gate.js +0 -113
- package/dist/hooks/lifecycle.d.ts +0 -5
- package/dist/hooks/lifecycle.js +0 -284
- package/dist/hooks/llm.d.ts +0 -12
- package/dist/hooks/message-sanitize.d.ts +0 -3
- package/dist/hooks/message-sanitize.js +0 -37
- package/dist/hooks/pain.d.ts +0 -5
- package/dist/hooks/pain.js +0 -301
- package/dist/hooks/progressive-trust-gate.d.ts +0 -51
- package/dist/hooks/progressive-trust-gate.js +0 -89
- package/dist/hooks/prompt.d.ts +0 -47
- package/dist/hooks/prompt.js +0 -884
- package/dist/hooks/subagent.d.ts +0 -10
- package/dist/hooks/subagent.js +0 -387
- package/dist/hooks/thinking-checkpoint.d.ts +0 -37
- package/dist/hooks/thinking-checkpoint.js +0 -51
- package/dist/hooks/trajectory-collector.d.ts +0 -32
- package/dist/hooks/trajectory-collector.js +0 -256
- package/dist/http/principles-console-route.d.ts +0 -9
- package/dist/http/principles-console-route.js +0 -567
- package/dist/i18n/commands.d.ts +0 -26
- package/dist/i18n/commands.js +0 -116
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -581
- package/dist/service/central-database.d.ts +0 -104
- package/dist/service/central-database.js +0 -649
- package/dist/service/control-ui-query-service.d.ts +0 -221
- package/dist/service/control-ui-query-service.js +0 -543
- package/dist/service/empathy-observer-manager.d.ts +0 -52
- package/dist/service/empathy-observer-manager.js +0 -229
- package/dist/service/evolution-query-service.d.ts +0 -155
- package/dist/service/evolution-query-service.js +0 -258
- package/dist/service/evolution-worker.d.ts +0 -101
- package/dist/service/evolution-worker.js +0 -974
- package/dist/service/nocturnal-runtime.d.ts +0 -183
- package/dist/service/nocturnal-service.d.ts +0 -163
- package/dist/service/nocturnal-service.js +0 -787
- package/dist/service/nocturnal-target-selector.d.ts +0 -145
- package/dist/service/nocturnal-target-selector.js +0 -315
- package/dist/service/phase3-input-filter.d.ts +0 -73
- package/dist/service/phase3-input-filter.js +0 -172
- package/dist/service/runtime-summary-service.d.ts +0 -122
- package/dist/service/runtime-summary-service.js +0 -485
- package/dist/service/trajectory-service.d.ts +0 -2
- package/dist/service/trajectory-service.js +0 -15
- package/dist/tools/critique-prompt.d.ts +0 -14
- package/dist/tools/deep-reflect.d.ts +0 -39
- package/dist/tools/deep-reflect.js +0 -350
- package/dist/tools/model-index.d.ts +0 -9
- package/dist/types/event-types.d.ts +0 -306
- package/dist/types/event-types.js +0 -106
- package/dist/types/hygiene-types.d.ts +0 -20
- package/dist/types/hygiene-types.js +0 -12
- package/dist/types/runtime-summary.d.ts +0 -47
- package/dist/types/runtime-summary.js +0 -1
- package/dist/types.d.ts +0 -50
- package/dist/types.js +0 -22
- package/dist/utils/file-lock.d.ts +0 -71
- package/dist/utils/file-lock.js +0 -309
- package/dist/utils/glob-match.d.ts +0 -28
- package/dist/utils/hashing.d.ts +0 -9
- package/dist/utils/io.d.ts +0 -6
- package/dist/utils/io.js +0 -106
- package/dist/utils/nlp.d.ts +0 -9
- package/dist/utils/plugin-logger.d.ts +0 -39
- package/dist/utils/subagent-probe.d.ts +0 -34
- package/dist/utils/subagent-probe.js +0 -81
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Principle Training State Store
|
|
3
|
+
* ================================================================
|
|
4
|
+
*
|
|
5
|
+
* Independent persistence layer for principle internalization tracking.
|
|
6
|
+
* Clearly separates the four truth states defined in the architecture:
|
|
7
|
+
* 1. sample_generated — reflection pair produced and passed arbiter
|
|
8
|
+
* 2. sample_included_in_train_run — training run consumed the sample
|
|
9
|
+
* 3. checkpoint_deployed — adapter/checkpoint is routable in OpenClaw
|
|
10
|
+
* 4. behavior_internalized — deployed worker improves on holdout eval
|
|
11
|
+
*
|
|
12
|
+
* DESIGN CONSTRAINTS (Phase 1):
|
|
13
|
+
* - No runtime target selection (Task 1.2 scope)
|
|
14
|
+
* - No training logic (Phase 2+ scope)
|
|
15
|
+
* - No evolution-reducer modifications
|
|
16
|
+
*
|
|
17
|
+
* FILE: {stateDir}/principle_training_state.json
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import * as fs from 'fs';
|
|
21
|
+
import * as path from 'path';
|
|
22
|
+
import { withLock, withLockAsync } from '../utils/file-lock.js';
|
|
23
|
+
import type { PrincipleEvaluatorLevel } from './evolution-types.js';
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Constants
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
/** File name for principle training state persistence */
|
|
30
|
+
export const PRINCIPLE_TRAINING_FILE = 'principle_training_state.json';
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Types
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
// PrincipleEvaluatorLevel is imported from evolution-types.ts to ensure a single canonical definition.
|
|
37
|
+
// Do not re-define here — use the import instead.
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Internalization status — tracks progress through the four truth states:
|
|
41
|
+
* sample_generated → sample_included_in_train_run → checkpoint_deployed → behavior_internalized
|
|
42
|
+
*/
|
|
43
|
+
export type InternalizationStatus =
|
|
44
|
+
| 'prompt_only' // Principle has no machine-checkable detector; stays in prompts only
|
|
45
|
+
| 'needs_training' // Evaluable but not yet included in any training run
|
|
46
|
+
| 'in_training' // Currently being used in an active training run
|
|
47
|
+
| 'deployed_pending_eval' // Checkpoint deployed, awaiting holdout evaluation
|
|
48
|
+
| 'internalized' // Passed holdout eval — behavior is learned
|
|
49
|
+
| 'regressed'; // Previously internalized but recent eval shows degradation
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Per-principle training state record.
|
|
53
|
+
* Tracks the full lineage from sample generation through deployment.
|
|
54
|
+
*/
|
|
55
|
+
export interface PrincipleTrainingState {
|
|
56
|
+
/** Principle identifier (e.g., "T-01", "P_write_before_delete") */
|
|
57
|
+
principleId: string;
|
|
58
|
+
|
|
59
|
+
/** Evaluability classification — controls whether automatic targeting is allowed */
|
|
60
|
+
evaluability: PrincipleEvaluatorLevel;
|
|
61
|
+
|
|
62
|
+
/** Number of applicable decision-point opportunities observed */
|
|
63
|
+
applicableOpportunityCount: number;
|
|
64
|
+
|
|
65
|
+
/** Number of violations of this principle observed */
|
|
66
|
+
observedViolationCount: number;
|
|
67
|
+
|
|
68
|
+
/** Observed compliance rate (0.0 – 1.0) */
|
|
69
|
+
complianceRate: number;
|
|
70
|
+
|
|
71
|
+
/** Trend direction for violations (+1 = improving, 0 = stable, -1 = worsening) */
|
|
72
|
+
violationTrend: number;
|
|
73
|
+
|
|
74
|
+
/** Number of reflection samples generated for this principle */
|
|
75
|
+
generatedSampleCount: number;
|
|
76
|
+
|
|
77
|
+
/** Number of generated samples approved by arbiter */
|
|
78
|
+
approvedSampleCount: number;
|
|
79
|
+
|
|
80
|
+
/** Training run IDs that included samples from this principle */
|
|
81
|
+
includedTrainRunIds: string[];
|
|
82
|
+
|
|
83
|
+
/** Deployed checkpoint IDs for this principle */
|
|
84
|
+
deployedCheckpointIds: string[];
|
|
85
|
+
|
|
86
|
+
/** Last holdout evaluation score (0.0 – 1.0), if available */
|
|
87
|
+
lastEvalScore?: number;
|
|
88
|
+
|
|
89
|
+
/** Current internalization status */
|
|
90
|
+
internalizationStatus: InternalizationStatus;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The full principle training store — a map of principleId -> state.
|
|
95
|
+
* Stored as a single JSON object in principle_training_state.json.
|
|
96
|
+
*/
|
|
97
|
+
export type PrincipleTrainingStore = Record<string, PrincipleTrainingState>;
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Valid Status Values (for validation)
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
const VALID_EVALUABILITIES: PrincipleEvaluatorLevel[] = ['deterministic', 'weak_heuristic', 'manual_only'];
|
|
104
|
+
const VALID_INTERNALIZATION_STATUSES: InternalizationStatus[] = [
|
|
105
|
+
'prompt_only',
|
|
106
|
+
'needs_training',
|
|
107
|
+
'in_training',
|
|
108
|
+
'deployed_pending_eval',
|
|
109
|
+
'internalized',
|
|
110
|
+
'regressed',
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// Schema Version
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Factory
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Creates a default principle training state for a newly tracked principle.
|
|
121
|
+
* Safe defaults: evaluability='manual_only' (requires explicit upgrade to auto-training),
|
|
122
|
+
* internalizationStatus='prompt_only' (starts as prompt-only, not eligible for
|
|
123
|
+
* automatic training until upgraded).
|
|
124
|
+
*/
|
|
125
|
+
export function createDefaultPrincipleState(principleId: string): PrincipleTrainingState {
|
|
126
|
+
return {
|
|
127
|
+
principleId,
|
|
128
|
+
evaluability: 'manual_only', // Safe default: requires explicit upgrade
|
|
129
|
+
applicableOpportunityCount: 0,
|
|
130
|
+
observedViolationCount: 0,
|
|
131
|
+
complianceRate: 0,
|
|
132
|
+
violationTrend: 0,
|
|
133
|
+
generatedSampleCount: 0,
|
|
134
|
+
approvedSampleCount: 0,
|
|
135
|
+
includedTrainRunIds: [],
|
|
136
|
+
deployedCheckpointIds: [],
|
|
137
|
+
internalizationStatus: 'prompt_only', // Safe default: starts as prompt-only
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// File Operations
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
|
|
145
|
+
function getFilePath(stateDir: string): string {
|
|
146
|
+
return path.join(stateDir, PRINCIPLE_TRAINING_FILE);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Applies migration-safe defaults to a raw parsed store.
|
|
151
|
+
* Handles:
|
|
152
|
+
* - Missing top-level entries (principles added since last load)
|
|
153
|
+
* - Missing fields on existing entries (schema evolution)
|
|
154
|
+
* - Invalid enum values (falls back to safe defaults)
|
|
155
|
+
* - NaN / out-of-range numeric values (clamped or defaulted)
|
|
156
|
+
*/
|
|
157
|
+
function applyMigrationDefaults(raw: unknown): PrincipleTrainingStore {
|
|
158
|
+
if (!raw || typeof raw !== 'object') {
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const store = raw as Record<string, unknown>;
|
|
163
|
+
const result: PrincipleTrainingStore = {};
|
|
164
|
+
|
|
165
|
+
for (const [principleId, state] of Object.entries(store)) {
|
|
166
|
+
if (!state || typeof state !== 'object') {
|
|
167
|
+
// Corrupted entry — skip
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const s = state as Record<string, unknown>;
|
|
172
|
+
|
|
173
|
+
// evaluability — validate enum
|
|
174
|
+
const rawEval = s.evaluability;
|
|
175
|
+
const evaluability: PrincipleEvaluatorLevel = VALID_EVALUABILITIES.includes(rawEval as PrincipleEvaluatorLevel)
|
|
176
|
+
? (rawEval as PrincipleEvaluatorLevel)
|
|
177
|
+
: 'manual_only';
|
|
178
|
+
|
|
179
|
+
// internalizationStatus — validate enum
|
|
180
|
+
const rawStatus = s.internalizationStatus;
|
|
181
|
+
const internalizationStatus: InternalizationStatus = VALID_INTERNALIZATION_STATUSES.includes(rawStatus as InternalizationStatus)
|
|
182
|
+
? (rawStatus as InternalizationStatus)
|
|
183
|
+
: 'prompt_only';
|
|
184
|
+
|
|
185
|
+
// Numeric fields — clamp to valid ranges
|
|
186
|
+
const applicableOpportunityCount = clampInt(s.applicableOpportunityCount, 0, Infinity, 0);
|
|
187
|
+
const observedViolationCount = clampInt(s.observedViolationCount, 0, Infinity, 0);
|
|
188
|
+
const complianceRate = clampFloat(s.complianceRate, 0, 1, 0);
|
|
189
|
+
const violationTrend = clampFloat(s.violationTrend, -1, 1, 0);
|
|
190
|
+
const generatedSampleCount = clampInt(s.generatedSampleCount, 0, Infinity, 0);
|
|
191
|
+
const approvedSampleCount = clampInt(s.approvedSampleCount, 0, Infinity, 0);
|
|
192
|
+
|
|
193
|
+
// Optional float — only set if in range [0, 1]
|
|
194
|
+
const rawLastEval = s.lastEvalScore;
|
|
195
|
+
let lastEvalScore: number | undefined;
|
|
196
|
+
if (rawLastEval != null && typeof rawLastEval === 'number') {
|
|
197
|
+
const clamped = Math.max(0, Math.min(1, rawLastEval));
|
|
198
|
+
if (Number.isFinite(clamped)) {
|
|
199
|
+
lastEvalScore = clamped;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Arrays — ensure always arrays
|
|
204
|
+
const includedTrainRunIds = Array.isArray(s.includedTrainRunIds)
|
|
205
|
+
? s.includedTrainRunIds.filter((id): id is string => typeof id === 'string')
|
|
206
|
+
: [];
|
|
207
|
+
const deployedCheckpointIds = Array.isArray(s.deployedCheckpointIds)
|
|
208
|
+
? s.deployedCheckpointIds.filter((id): id is string => typeof id === 'string')
|
|
209
|
+
: [];
|
|
210
|
+
|
|
211
|
+
// Skip entries where the stored principleId doesn't match the map key.
|
|
212
|
+
// This indicates a corrupted or tampered entry.
|
|
213
|
+
const storedPrincipleId = s.principleId;
|
|
214
|
+
if (typeof storedPrincipleId !== 'string' || storedPrincipleId !== principleId) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
result[principleId] = {
|
|
219
|
+
principleId,
|
|
220
|
+
evaluability,
|
|
221
|
+
applicableOpportunityCount,
|
|
222
|
+
observedViolationCount,
|
|
223
|
+
complianceRate,
|
|
224
|
+
violationTrend,
|
|
225
|
+
generatedSampleCount,
|
|
226
|
+
approvedSampleCount,
|
|
227
|
+
includedTrainRunIds,
|
|
228
|
+
deployedCheckpointIds,
|
|
229
|
+
lastEvalScore,
|
|
230
|
+
internalizationStatus,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Clamp an unknown value to a float range, returning default if invalid */
|
|
238
|
+
function clampFloat(
|
|
239
|
+
value: unknown,
|
|
240
|
+
min: number,
|
|
241
|
+
max: number,
|
|
242
|
+
fallback: number
|
|
243
|
+
): number {
|
|
244
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
|
|
245
|
+
return Math.max(min, Math.min(max, value));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Clamp an unknown value to an integer range, returning default if invalid */
|
|
249
|
+
function clampInt(
|
|
250
|
+
value: unknown,
|
|
251
|
+
min: number,
|
|
252
|
+
max: number,
|
|
253
|
+
fallback: number
|
|
254
|
+
): number {
|
|
255
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
|
|
256
|
+
const rounded = Math.round(value);
|
|
257
|
+
return Math.max(min, Math.min(max, rounded));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
// Synchronous Read/Write
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Loads the full principle training store from disk.
|
|
266
|
+
* Returns an empty store if the file does not exist or is corrupted.
|
|
267
|
+
*/
|
|
268
|
+
export function loadStore(stateDir: string): PrincipleTrainingStore {
|
|
269
|
+
const filePath = getFilePath(stateDir);
|
|
270
|
+
|
|
271
|
+
if (!fs.existsSync(filePath)) {
|
|
272
|
+
return {};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
277
|
+
const parsed = JSON.parse(raw);
|
|
278
|
+
return applyMigrationDefaults(parsed);
|
|
279
|
+
} catch (err) {
|
|
280
|
+
// Corrupted file — fail-safe, return empty store
|
|
281
|
+
console.warn(`[principle-training-state] Failed to load store from "${filePath}": ${err instanceof Error ? err.message : String(err)}. Returning empty store.`);
|
|
282
|
+
return {};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Synchronously saves the full principle training store to disk.
|
|
288
|
+
* Uses file locking to prevent concurrent write corruption.
|
|
289
|
+
*/
|
|
290
|
+
export function saveStore(stateDir: string, store: PrincipleTrainingStore): void {
|
|
291
|
+
const filePath = getFilePath(stateDir);
|
|
292
|
+
const dir = path.dirname(filePath);
|
|
293
|
+
|
|
294
|
+
if (!fs.existsSync(dir)) {
|
|
295
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
withLock(filePath, () => {
|
|
299
|
+
fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
// Async Read/Write (for use in async contexts)
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Asynchronously loads the full principle training store from disk.
|
|
309
|
+
* Returns an empty store if the file does not exist or is corrupted.
|
|
310
|
+
*/
|
|
311
|
+
export async function loadStoreAsync(stateDir: string): Promise<PrincipleTrainingStore> {
|
|
312
|
+
const filePath = getFilePath(stateDir);
|
|
313
|
+
|
|
314
|
+
if (!fs.existsSync(filePath)) {
|
|
315
|
+
return {};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const raw = await fs.promises.readFile(filePath, 'utf-8');
|
|
320
|
+
const parsed = JSON.parse(raw);
|
|
321
|
+
return applyMigrationDefaults(parsed);
|
|
322
|
+
} catch (err) {
|
|
323
|
+
console.warn(`[principle-training-state] Failed to load store asynchronously from "${filePath}": ${err instanceof Error ? err.message : String(err)}. Returning empty store.`);
|
|
324
|
+
return {};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Asynchronously saves the full principle training store to disk.
|
|
330
|
+
* Uses file locking to prevent concurrent write corruption.
|
|
331
|
+
*/
|
|
332
|
+
export async function saveStoreAsync(stateDir: string, store: PrincipleTrainingStore): Promise<void> {
|
|
333
|
+
const filePath = getFilePath(stateDir);
|
|
334
|
+
const dir = path.dirname(filePath);
|
|
335
|
+
|
|
336
|
+
if (!fs.existsSync(dir)) {
|
|
337
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
await withLockAsync(filePath, async () => {
|
|
341
|
+
await fs.promises.writeFile(filePath, JSON.stringify(store, null, 2), 'utf-8');
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
// Single-Principle Accessors
|
|
347
|
+
// ---------------------------------------------------------------------------
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Gets the training state for a single principle.
|
|
351
|
+
* Returns a default state if the principle is not yet tracked.
|
|
352
|
+
*/
|
|
353
|
+
export function getPrincipleState(
|
|
354
|
+
stateDir: string,
|
|
355
|
+
principleId: string
|
|
356
|
+
): PrincipleTrainingState {
|
|
357
|
+
const store = loadStore(stateDir);
|
|
358
|
+
return store[principleId] ?? createDefaultPrincipleState(principleId);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Updates or inserts the training state for a single principle.
|
|
363
|
+
* Persists the full store after the update.
|
|
364
|
+
*
|
|
365
|
+
* Uses file locking around the entire read-modify-write sequence to prevent
|
|
366
|
+
* concurrent updates from causing lost writes.
|
|
367
|
+
*/
|
|
368
|
+
export function setPrincipleState(
|
|
369
|
+
stateDir: string,
|
|
370
|
+
state: PrincipleTrainingState
|
|
371
|
+
): void {
|
|
372
|
+
const filePath = getFilePath(stateDir);
|
|
373
|
+
withLock(filePath, () => {
|
|
374
|
+
// Read current store while holding the lock
|
|
375
|
+
const store = loadStoreUnlocked(filePath);
|
|
376
|
+
store[state.principleId] = state;
|
|
377
|
+
// Write directly — no nested lock needed (we hold the outer lock)
|
|
378
|
+
const dir = path.dirname(filePath);
|
|
379
|
+
if (!fs.existsSync(dir)) {
|
|
380
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
381
|
+
}
|
|
382
|
+
fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Internal: loads store from a specific file path without acquiring a lock.
|
|
388
|
+
* Caller must hold the lock. Use only inside locked sections.
|
|
389
|
+
*/
|
|
390
|
+
function loadStoreUnlocked(filePath: string): PrincipleTrainingStore {
|
|
391
|
+
if (!fs.existsSync(filePath)) {
|
|
392
|
+
return {};
|
|
393
|
+
}
|
|
394
|
+
try {
|
|
395
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
396
|
+
return applyMigrationDefaults(JSON.parse(raw));
|
|
397
|
+
} catch {
|
|
398
|
+
return {};
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Removes a principle from the training store.
|
|
404
|
+
* Does nothing if the principle is not tracked.
|
|
405
|
+
*
|
|
406
|
+
* Uses file locking around the entire read-modify-write sequence.
|
|
407
|
+
*/
|
|
408
|
+
export function removePrincipleState(stateDir: string, principleId: string): void {
|
|
409
|
+
const filePath = getFilePath(stateDir);
|
|
410
|
+
withLock(filePath, () => {
|
|
411
|
+
const store = loadStoreUnlocked(filePath);
|
|
412
|
+
if (Object.prototype.hasOwnProperty.call(store, principleId)) {
|
|
413
|
+
delete store[principleId];
|
|
414
|
+
const dir = path.dirname(filePath);
|
|
415
|
+
if (!fs.existsSync(dir)) {
|
|
416
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
417
|
+
}
|
|
418
|
+
fs.writeFileSync(filePath, JSON.stringify(store, null, 2), 'utf-8');
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Returns all principles currently tracked in the store.
|
|
425
|
+
*/
|
|
426
|
+
export function listPrincipleIds(stateDir: string): string[] {
|
|
427
|
+
return Object.keys(loadStore(stateDir));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Returns all principles matching a given internalization status.
|
|
432
|
+
*/
|
|
433
|
+
export function listPrinciplesByStatus(
|
|
434
|
+
stateDir: string,
|
|
435
|
+
status: InternalizationStatus
|
|
436
|
+
): PrincipleTrainingState[] {
|
|
437
|
+
const store = loadStore(stateDir);
|
|
438
|
+
return Object.values(store).filter((s) => s.internalizationStatus === status);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Returns all principles with 'deterministic' or 'weak_heuristic' evaluability
|
|
443
|
+
* that are eligible for automatic nocturnal targeting.
|
|
444
|
+
*/
|
|
445
|
+
export function listEvaluablePrinciples(stateDir: string): PrincipleTrainingState[] {
|
|
446
|
+
const store = loadStore(stateDir);
|
|
447
|
+
return Object.values(store).filter(
|
|
448
|
+
(s) => s.evaluability !== 'manual_only' && s.internalizationStatus !== 'prompt_only'
|
|
449
|
+
);
|
|
450
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
export const PROFILE_AUDIT_LEVELS = new Set(["low", "medium", "high"]);
|
|
2
|
+
export const PROFILE_EVOLUTION_MODES = new Set(["realtime", "async"]);
|
|
3
|
+
export const PROFILE_TEST_LEVELS = new Set(["smoke", "unit", "full"]);
|
|
4
|
+
|
|
5
|
+
export const PROFILE_DEFAULTS = {
|
|
6
|
+
audit_level: "medium",
|
|
7
|
+
risk_paths: [] as string[],
|
|
8
|
+
evolution_mode: "realtime",
|
|
9
|
+
gate: {
|
|
10
|
+
require_plan_for_risk_paths: true,
|
|
11
|
+
require_audit_before_write: true,
|
|
12
|
+
require_reviewer_after_write: true,
|
|
13
|
+
},
|
|
14
|
+
tests: {
|
|
15
|
+
on_change: "smoke",
|
|
16
|
+
on_risk_change: "unit",
|
|
17
|
+
commands: {} as Record<string, string>,
|
|
18
|
+
},
|
|
19
|
+
pain: {
|
|
20
|
+
soft_capture_threshold: 30,
|
|
21
|
+
adaptive: {
|
|
22
|
+
enabled: true,
|
|
23
|
+
spiral_boost: 20,
|
|
24
|
+
min_threshold: 15,
|
|
25
|
+
max_threshold: 70,
|
|
26
|
+
backlog_trigger: 6,
|
|
27
|
+
hard_failure_trigger: 1,
|
|
28
|
+
low_recent_success_boost: 15,
|
|
29
|
+
high_recent_pain_boost: 10,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
lifecycle: {
|
|
33
|
+
enabled: true,
|
|
34
|
+
heartbeat_stale_hours: 72,
|
|
35
|
+
},
|
|
36
|
+
progressive_gate: {
|
|
37
|
+
enabled: true,
|
|
38
|
+
plan_approvals: {
|
|
39
|
+
enabled: false,
|
|
40
|
+
max_lines_override: -1,
|
|
41
|
+
allowed_patterns: [] as string[],
|
|
42
|
+
allowed_operations: [] as string[],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
edit_verification: {
|
|
46
|
+
enabled: true,
|
|
47
|
+
max_file_size_bytes: 10 * 1024 * 1024, // 10MB
|
|
48
|
+
fuzzy_match_enabled: true,
|
|
49
|
+
fuzzy_match_threshold: 0.8,
|
|
50
|
+
skip_large_file_action: "warn" as "warn" | "block", // "warn" or "block"
|
|
51
|
+
},
|
|
52
|
+
thinking_checkpoint: {
|
|
53
|
+
enabled: false, // Default OFF to avoid blocking new users
|
|
54
|
+
window_ms: 5 * 60 * 1000, // 5 minute window
|
|
55
|
+
high_risk_tools: ['run_shell_command', 'delete_file', 'move_file'],
|
|
56
|
+
},
|
|
57
|
+
custom_guards: [] as Array<{ pattern: string; message: string; severity: string }>,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export function normalizeProfile(rawProfile: any): any {
|
|
61
|
+
const defaults = JSON.parse(JSON.stringify(PROFILE_DEFAULTS));
|
|
62
|
+
const warnings: string[] = [];
|
|
63
|
+
const normalized = { ...defaults };
|
|
64
|
+
let invalid = false;
|
|
65
|
+
|
|
66
|
+
if (!rawProfile || typeof rawProfile !== "object" || Array.isArray(rawProfile)) {
|
|
67
|
+
warnings.push("PROFILE root must be an object; defaults applied.");
|
|
68
|
+
invalid = true;
|
|
69
|
+
} else {
|
|
70
|
+
// Merge known fields (Support both snake_case and camelCase)
|
|
71
|
+
const auditLevel = rawProfile.audit_level ?? rawProfile.auditLevel;
|
|
72
|
+
if (PROFILE_AUDIT_LEVELS.has(auditLevel)) {
|
|
73
|
+
normalized.audit_level = auditLevel;
|
|
74
|
+
} else if (auditLevel !== undefined) {
|
|
75
|
+
warnings.push(`Invalid audit_level '${auditLevel}'`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const evolutionMode = rawProfile.evolution_mode ?? rawProfile.evolutionMode;
|
|
79
|
+
if (PROFILE_EVOLUTION_MODES.has(evolutionMode)) {
|
|
80
|
+
normalized.evolution_mode = evolutionMode;
|
|
81
|
+
} else if (evolutionMode !== undefined) {
|
|
82
|
+
warnings.push(`Invalid evolution_mode '${evolutionMode}'`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const riskPaths = rawProfile.risk_paths ?? rawProfile.riskPaths;
|
|
86
|
+
if (Array.isArray(riskPaths)) {
|
|
87
|
+
normalized.risk_paths = riskPaths.filter((p: any) => typeof p === 'string');
|
|
88
|
+
} else if (typeof riskPaths === 'string') {
|
|
89
|
+
normalized.risk_paths = [riskPaths];
|
|
90
|
+
} else if (riskPaths !== undefined) {
|
|
91
|
+
warnings.push("risk_paths must be an array of strings");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Gate settings
|
|
95
|
+
if (rawProfile.gate && typeof rawProfile.gate === 'object') {
|
|
96
|
+
const g = rawProfile.gate;
|
|
97
|
+
normalized.gate.require_plan_for_risk_paths = g.require_plan_for_risk_paths ?? g.requirePlanForRiskPaths ?? defaults.gate.require_plan_for_risk_paths;
|
|
98
|
+
normalized.gate.require_audit_before_write = g.require_audit_before_write ?? g.requireAuditBeforeWrite ?? defaults.gate.require_audit_before_write;
|
|
99
|
+
normalized.gate.require_reviewer_after_write = g.require_reviewer_after_write ?? g.requireReviewerAfterWrite ?? defaults.gate.require_reviewer_after_write;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Progressive Gate
|
|
103
|
+
if (rawProfile.progressive_gate && typeof rawProfile.progressive_gate === 'object') {
|
|
104
|
+
const pg = rawProfile.progressive_gate;
|
|
105
|
+
normalized.progressive_gate.enabled = pg.enabled ?? pg.enabled ?? defaults.progressive_gate.enabled;
|
|
106
|
+
|
|
107
|
+
// Plan approvals configuration
|
|
108
|
+
if (pg.plan_approvals && typeof pg.plan_approvals === 'object') {
|
|
109
|
+
const pa = pg.plan_approvals;
|
|
110
|
+
normalized.progressive_gate.plan_approvals.enabled = pa.enabled ?? pa.planApprovals ?? defaults.progressive_gate.plan_approvals.enabled;
|
|
111
|
+
|
|
112
|
+
const maxLines = pa.max_lines_override ?? pa.maxLinesOverride;
|
|
113
|
+
if (typeof maxLines === 'number' && maxLines >= -1) {
|
|
114
|
+
normalized.progressive_gate.plan_approvals.max_lines_override = maxLines;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (Array.isArray(pa.allowed_patterns)) {
|
|
118
|
+
normalized.progressive_gate.plan_approvals.allowed_patterns = pa.allowed_patterns.filter((p: any) => typeof p === 'string');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (Array.isArray(pa.allowed_operations)) {
|
|
122
|
+
normalized.progressive_gate.plan_approvals.allowed_operations = pa.allowed_operations.filter((o: any) => typeof o === 'string');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} else if (rawProfile.progressiveGate && typeof rawProfile.progressiveGate === 'object') {
|
|
126
|
+
const pg = rawProfile.progressiveGate;
|
|
127
|
+
normalized.progressive_gate.enabled = pg.enabled ?? defaults.progressive_gate.enabled;
|
|
128
|
+
|
|
129
|
+
// Plan approvals configuration (camelCase)
|
|
130
|
+
if (pg.planApprovals && typeof pg.planApprovals === 'object') {
|
|
131
|
+
const pa = pg.planApprovals;
|
|
132
|
+
normalized.progressive_gate.plan_approvals.enabled = pa.enabled ?? defaults.progressive_gate.plan_approvals.enabled;
|
|
133
|
+
|
|
134
|
+
const maxLines = pa.maxLinesOverride;
|
|
135
|
+
if (typeof maxLines === 'number' && maxLines >= -1) {
|
|
136
|
+
normalized.progressive_gate.plan_approvals.max_lines_override = maxLines;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (Array.isArray(pa.allowedPatterns)) {
|
|
140
|
+
normalized.progressive_gate.plan_approvals.allowed_patterns = pa.allowedPatterns.filter((p: any) => typeof p === 'string');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (Array.isArray(pa.allowedOperations)) {
|
|
144
|
+
normalized.progressive_gate.plan_approvals.allowed_operations = pa.allowedOperations.filter((o: any) => typeof o === 'string');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Edit verification settings (P-03)
|
|
150
|
+
const evRaw = rawProfile.edit_verification ?? rawProfile.editVerification;
|
|
151
|
+
if (evRaw && typeof evRaw === 'object') {
|
|
152
|
+
normalized.edit_verification.enabled = evRaw.enabled ?? defaults.edit_verification.enabled;
|
|
153
|
+
const maxSize = evRaw.max_file_size_bytes ?? evRaw.maxFileSizeBytes;
|
|
154
|
+
if (typeof maxSize === 'number' && maxSize >= 0) {
|
|
155
|
+
normalized.edit_verification.max_file_size_bytes = maxSize;
|
|
156
|
+
}
|
|
157
|
+
normalized.edit_verification.fuzzy_match_enabled = evRaw.fuzzy_match_enabled ?? evRaw.fuzzyMatchEnabled ?? defaults.edit_verification.fuzzy_match_enabled;
|
|
158
|
+
const threshold = evRaw.fuzzy_match_threshold ?? evRaw.fuzzyMatchThreshold;
|
|
159
|
+
if (typeof threshold === 'number' && threshold > 0 && threshold <= 1) {
|
|
160
|
+
normalized.edit_verification.fuzzy_match_threshold = threshold;
|
|
161
|
+
}
|
|
162
|
+
const action = evRaw.skip_large_file_action ?? evRaw.skipLargeFileAction;
|
|
163
|
+
if (typeof action === 'string' && ['warn', 'block'].includes(action)) {
|
|
164
|
+
normalized.edit_verification.skip_large_file_action = action as "warn" | "block";
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Test settings
|
|
169
|
+
if (rawProfile.tests && typeof rawProfile.tests === 'object') {
|
|
170
|
+
const t = rawProfile.tests;
|
|
171
|
+
const onChange = t.on_change ?? t.onChange;
|
|
172
|
+
if (PROFILE_TEST_LEVELS.has(onChange)) {
|
|
173
|
+
normalized.tests.on_change = onChange;
|
|
174
|
+
}
|
|
175
|
+
const onRiskChange = t.on_risk_change ?? t.onRiskChange;
|
|
176
|
+
if (PROFILE_TEST_LEVELS.has(onRiskChange)) {
|
|
177
|
+
normalized.tests.on_risk_change = onRiskChange;
|
|
178
|
+
}
|
|
179
|
+
if (t.commands && typeof t.commands === 'object') {
|
|
180
|
+
normalized.tests.commands = { ...defaults.tests.commands, ...t.commands };
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Pain settings
|
|
185
|
+
if (rawProfile.pain && typeof rawProfile.pain === 'object') {
|
|
186
|
+
const p = rawProfile.pain;
|
|
187
|
+
normalized.pain.soft_capture_threshold = p.soft_capture_threshold ?? p.softCaptureThreshold ?? defaults.pain.soft_capture_threshold;
|
|
188
|
+
if (p.adaptive && typeof p.adaptive === 'object') {
|
|
189
|
+
normalized.pain.adaptive = { ...defaults.pain.adaptive, ...p.adaptive };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Thinking OS Checkpoint settings (P-10)
|
|
194
|
+
const tcRaw = rawProfile.thinking_checkpoint ?? rawProfile.thinkingCheckpoint;
|
|
195
|
+
if (tcRaw && typeof tcRaw === 'object') {
|
|
196
|
+
normalized.thinking_checkpoint.enabled = tcRaw.enabled ?? defaults.thinking_checkpoint.enabled;
|
|
197
|
+
const windowMs = tcRaw.window_ms ?? tcRaw.windowMs;
|
|
198
|
+
if (typeof windowMs === 'number' && windowMs > 0) {
|
|
199
|
+
normalized.thinking_checkpoint.window_ms = windowMs;
|
|
200
|
+
}
|
|
201
|
+
if (Array.isArray(tcRaw.high_risk_tools ?? tcRaw.highRiskTools)) {
|
|
202
|
+
normalized.thinking_checkpoint.high_risk_tools = (tcRaw.high_risk_tools ?? tcRaw.highRiskTools).filter((t: any) => typeof t === 'string');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (Array.isArray(rawProfile.custom_guards)) {
|
|
207
|
+
normalized.custom_guards = rawProfile.custom_guards.map((item: any) => {
|
|
208
|
+
let severity = "error";
|
|
209
|
+
const itemSeverity = item.severity;
|
|
210
|
+
if (itemSeverity && ["info", "warning", "error", "fatal"].includes(String(itemSeverity).toLowerCase())) {
|
|
211
|
+
severity = String(itemSeverity).toLowerCase();
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
pattern: String(item.pattern || ""),
|
|
215
|
+
message: String(item.message || "Custom guard triggered"),
|
|
216
|
+
severity,
|
|
217
|
+
};
|
|
218
|
+
}).filter((item: any) => item.pattern);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
normalized._profile_invalid = invalid;
|
|
223
|
+
normalized._profile_warnings = warnings;
|
|
224
|
+
|
|
225
|
+
return normalized;
|
|
226
|
+
}
|