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,265 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { TrajectoryDatabase } from '../../src/core/trajectory.js';
|
|
6
|
+
|
|
7
|
+
describe('TrajectoryDatabase', () => {
|
|
8
|
+
let workspaceDir: string | null = null;
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
if (workspaceDir) {
|
|
12
|
+
fs.rmSync(workspaceDir, { recursive: true, force: true });
|
|
13
|
+
workspaceDir = null;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('bootstraps trajectory.db and blob/export directories', () => {
|
|
18
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
19
|
+
const db = new TrajectoryDatabase({ workspaceDir });
|
|
20
|
+
|
|
21
|
+
expect(fs.existsSync(path.join(workspaceDir, '.state', 'trajectory.db'))).toBe(true);
|
|
22
|
+
expect(fs.existsSync(path.join(workspaceDir, '.state', 'blobs'))).toBe(true);
|
|
23
|
+
expect(fs.existsSync(path.join(workspaceDir, '.state', 'exports'))).toBe(true);
|
|
24
|
+
|
|
25
|
+
const stats = db.getDataStats();
|
|
26
|
+
expect(stats.assistantTurns).toBe(0);
|
|
27
|
+
expect(stats.userTurns).toBe(0);
|
|
28
|
+
expect(stats.pendingSamples).toBe(0);
|
|
29
|
+
db.dispose();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('stores oversized assistant raw text in blob storage and preserves sanitized text inline', () => {
|
|
33
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
34
|
+
const db = new TrajectoryDatabase({ workspaceDir, blobInlineThresholdBytes: 128 });
|
|
35
|
+
|
|
36
|
+
const raw = `${'A'.repeat(256)}\n<empathy signal="damage" severity="mild"/>`;
|
|
37
|
+
db.recordAssistantTurn({
|
|
38
|
+
sessionId: 's1',
|
|
39
|
+
runId: 'run-1',
|
|
40
|
+
provider: 'test',
|
|
41
|
+
model: 'model',
|
|
42
|
+
rawText: raw,
|
|
43
|
+
sanitizedText: 'clean text',
|
|
44
|
+
usageJson: { input: 10, output: 20 },
|
|
45
|
+
empathySignalJson: { detected: true, severity: 'mild' },
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const turns = db.listAssistantTurns('s1');
|
|
49
|
+
expect(turns).toHaveLength(1);
|
|
50
|
+
expect(turns[0].sanitizedText).toBe('clean text');
|
|
51
|
+
expect(turns[0].rawText).toBe(raw);
|
|
52
|
+
expect(turns[0].blobRef).toBeTruthy();
|
|
53
|
+
db.dispose();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('creates a pending correction sample after a user correction followed by successful recovery', () => {
|
|
57
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
58
|
+
const db = new TrajectoryDatabase({ workspaceDir });
|
|
59
|
+
|
|
60
|
+
const assistantTurnId = db.recordAssistantTurn({
|
|
61
|
+
sessionId: 's1',
|
|
62
|
+
runId: 'run-1',
|
|
63
|
+
provider: 'test',
|
|
64
|
+
model: 'model',
|
|
65
|
+
rawText: 'I changed the wrong file.',
|
|
66
|
+
sanitizedText: 'I changed the wrong file.',
|
|
67
|
+
usageJson: {},
|
|
68
|
+
empathySignalJson: { detected: false },
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
db.recordToolCall({
|
|
72
|
+
sessionId: 's1',
|
|
73
|
+
toolName: 'edit',
|
|
74
|
+
outcome: 'failure',
|
|
75
|
+
errorType: 'EACCES',
|
|
76
|
+
errorMessage: 'permission denied',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
db.recordUserTurn({
|
|
80
|
+
sessionId: 's1',
|
|
81
|
+
turnIndex: 1,
|
|
82
|
+
rawText: '你错了,不是这个文件,重新来。',
|
|
83
|
+
correctionDetected: true,
|
|
84
|
+
correctionCue: '你错了',
|
|
85
|
+
referencesAssistantTurnId: assistantTurnId,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
db.recordToolCall({
|
|
89
|
+
sessionId: 's1',
|
|
90
|
+
toolName: 'edit',
|
|
91
|
+
outcome: 'success',
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const samples = db.listCorrectionSamples('pending');
|
|
95
|
+
expect(samples).toHaveLength(1);
|
|
96
|
+
expect(samples[0].sessionId).toBe('s1');
|
|
97
|
+
expect(samples[0].badAssistantTurnId).toBe(assistantTurnId);
|
|
98
|
+
expect(samples[0].reviewStatus).toBe('pending');
|
|
99
|
+
expect(samples[0].qualityScore).toBeGreaterThan(0);
|
|
100
|
+
db.dispose();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('does not create a correction sample when prerequisites are missing', () => {
|
|
104
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
105
|
+
const db = new TrajectoryDatabase({ workspaceDir });
|
|
106
|
+
|
|
107
|
+
db.recordToolCall({
|
|
108
|
+
sessionId: 's1',
|
|
109
|
+
toolName: 'edit',
|
|
110
|
+
outcome: 'failure',
|
|
111
|
+
errorType: 'EACCES',
|
|
112
|
+
});
|
|
113
|
+
db.recordUserTurn({
|
|
114
|
+
sessionId: 's1',
|
|
115
|
+
turnIndex: 1,
|
|
116
|
+
rawText: 'redo',
|
|
117
|
+
correctionDetected: false,
|
|
118
|
+
referencesAssistantTurnId: null,
|
|
119
|
+
});
|
|
120
|
+
db.recordToolCall({
|
|
121
|
+
sessionId: 's1',
|
|
122
|
+
toolName: 'edit',
|
|
123
|
+
outcome: 'success',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(db.listCorrectionSamples('pending')).toHaveLength(0);
|
|
127
|
+
db.dispose();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('raises when reviewing a missing correction sample', () => {
|
|
131
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
132
|
+
const db = new TrajectoryDatabase({ workspaceDir });
|
|
133
|
+
|
|
134
|
+
expect(() => db.reviewCorrectionSample('missing', 'approved')).toThrow('Correction sample not found');
|
|
135
|
+
db.dispose();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('aggregates daily metrics without multiplying user corrections', () => {
|
|
139
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
140
|
+
const db = new TrajectoryDatabase({ workspaceDir });
|
|
141
|
+
|
|
142
|
+
db.recordToolCall({
|
|
143
|
+
sessionId: 's1',
|
|
144
|
+
toolName: 'edit',
|
|
145
|
+
outcome: 'failure',
|
|
146
|
+
createdAt: '2026-03-19T10:00:00.000Z',
|
|
147
|
+
});
|
|
148
|
+
db.recordToolCall({
|
|
149
|
+
sessionId: 's1',
|
|
150
|
+
toolName: 'write',
|
|
151
|
+
outcome: 'success',
|
|
152
|
+
createdAt: '2026-03-19T11:00:00.000Z',
|
|
153
|
+
});
|
|
154
|
+
db.recordUserTurn({
|
|
155
|
+
sessionId: 's1',
|
|
156
|
+
turnIndex: 1,
|
|
157
|
+
rawText: 'redo',
|
|
158
|
+
correctionDetected: true,
|
|
159
|
+
correctionCue: 'redo',
|
|
160
|
+
createdAt: '2026-03-19T12:00:00.000Z',
|
|
161
|
+
});
|
|
162
|
+
db.recordUserTurn({
|
|
163
|
+
sessionId: 's1',
|
|
164
|
+
turnIndex: 2,
|
|
165
|
+
rawText: 'again',
|
|
166
|
+
correctionDetected: true,
|
|
167
|
+
correctionCue: 'again',
|
|
168
|
+
createdAt: '2026-03-19T13:00:00.000Z',
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const result = db.exportAnalytics();
|
|
172
|
+
const payload = JSON.parse(fs.readFileSync(result.filePath, 'utf8')) as {
|
|
173
|
+
dailyMetrics: Array<{ day: string; tool_calls: number; failures: number; user_corrections: number }>;
|
|
174
|
+
};
|
|
175
|
+
expect(payload.dailyMetrics).toEqual([
|
|
176
|
+
{ day: '2026-03-19', tool_calls: 2, failures: 1, user_corrections: 2 },
|
|
177
|
+
]);
|
|
178
|
+
db.dispose();
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('applies busy_timeout and prunes orphaned blobs on startup', () => {
|
|
182
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
183
|
+
const blobDir = path.join(workspaceDir, '.state', 'blobs');
|
|
184
|
+
fs.mkdirSync(blobDir, { recursive: true });
|
|
185
|
+
const orphanBlob = path.join(blobDir, 'assistant-orphan.txt');
|
|
186
|
+
fs.writeFileSync(orphanBlob, 'stale blob', 'utf8');
|
|
187
|
+
const oldTime = new Date('2026-01-01T00:00:00.000Z');
|
|
188
|
+
fs.utimesSync(orphanBlob, oldTime, oldTime);
|
|
189
|
+
|
|
190
|
+
const db = new TrajectoryDatabase({
|
|
191
|
+
workspaceDir,
|
|
192
|
+
busyTimeoutMs: 2500,
|
|
193
|
+
orphanBlobGraceDays: 0,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect((db as any).db.pragma('busy_timeout', { simple: true })).toBe(2500);
|
|
197
|
+
expect(fs.existsSync(orphanBlob)).toBe(false);
|
|
198
|
+
db.dispose();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('imports legacy sessions, events, and evolution artifacts idempotently', () => {
|
|
202
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-trajectory-'));
|
|
203
|
+
const sessionDir = path.join(workspaceDir, '.state', 'sessions');
|
|
204
|
+
const logsDir = path.join(workspaceDir, '.state', 'logs');
|
|
205
|
+
const memoryDir = path.join(workspaceDir, 'memory');
|
|
206
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
207
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
208
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
209
|
+
|
|
210
|
+
fs.writeFileSync(
|
|
211
|
+
path.join(sessionDir, 'session-a.json'),
|
|
212
|
+
JSON.stringify({ sessionId: 'legacy-session', lastActivityAt: Date.parse('2026-03-18T10:00:00.000Z') }),
|
|
213
|
+
'utf8',
|
|
214
|
+
);
|
|
215
|
+
fs.writeFileSync(
|
|
216
|
+
path.join(logsDir, 'events.jsonl'),
|
|
217
|
+
[
|
|
218
|
+
JSON.stringify({
|
|
219
|
+
type: 'pain_signal',
|
|
220
|
+
sessionId: 'legacy-session',
|
|
221
|
+
ts: '2026-03-18T10:01:00.000Z',
|
|
222
|
+
data: { source: 'legacy_pain', score: 12, reason: 'legacy reason' },
|
|
223
|
+
}),
|
|
224
|
+
JSON.stringify({
|
|
225
|
+
type: 'trust_change',
|
|
226
|
+
sessionId: 'legacy-session',
|
|
227
|
+
ts: '2026-03-18T10:02:00.000Z',
|
|
228
|
+
data: { previousScore: 80, newScore: 82, delta: 2, reason: 'legacy trust' },
|
|
229
|
+
}),
|
|
230
|
+
].join('\n'),
|
|
231
|
+
'utf8',
|
|
232
|
+
);
|
|
233
|
+
fs.writeFileSync(
|
|
234
|
+
path.join(memoryDir, 'evolution.jsonl'),
|
|
235
|
+
`${JSON.stringify({
|
|
236
|
+
type: 'principle_promoted',
|
|
237
|
+
ts: '2026-03-18T10:03:00.000Z',
|
|
238
|
+
data: { principleId: 'p-1', summary: 'legacy principle' },
|
|
239
|
+
})}\n`,
|
|
240
|
+
'utf8',
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const db = new TrajectoryDatabase({ workspaceDir });
|
|
244
|
+
const firstStats = db.getDataStats();
|
|
245
|
+
expect(firstStats.painEvents).toBe(1);
|
|
246
|
+
expect(firstStats.assistantTurns).toBe(0);
|
|
247
|
+
|
|
248
|
+
const analytics = JSON.parse(fs.readFileSync(db.exportAnalytics().filePath, 'utf8')) as {
|
|
249
|
+
stats: { painEvents: number };
|
|
250
|
+
principleEffectiveness: Array<{ event_type: string; total: number }>;
|
|
251
|
+
};
|
|
252
|
+
expect(analytics.stats.painEvents).toBe(1);
|
|
253
|
+
expect(analytics.principleEffectiveness).toEqual(
|
|
254
|
+
expect.arrayContaining([
|
|
255
|
+
expect.objectContaining({ event_type: 'principle_promoted', total: 1 }),
|
|
256
|
+
]),
|
|
257
|
+
);
|
|
258
|
+
db.dispose();
|
|
259
|
+
|
|
260
|
+
const reopened = new TrajectoryDatabase({ workspaceDir });
|
|
261
|
+
const secondStats = reopened.getDataStats();
|
|
262
|
+
expect(secondStats.painEvents).toBe(1);
|
|
263
|
+
reopened.dispose();
|
|
264
|
+
});
|
|
265
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { createTestContext } from '../test-utils.js';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
describe('WorkspaceContext Factory (Test Utils)', () => {
|
|
6
|
+
it('should create a test context with a temporary directory', () => {
|
|
7
|
+
const wctx = createTestContext();
|
|
8
|
+
|
|
9
|
+
expect(wctx.workspaceDir).toContain('pd-test-');
|
|
10
|
+
expect(wctx.stateDir).toContain('.state');
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should allow overriding workspaceDir', () => {
|
|
14
|
+
const customDir = path.resolve('/custom/test');
|
|
15
|
+
const wctx = createTestContext({ workspaceDir: customDir });
|
|
16
|
+
expect(wctx.workspaceDir).toBe(customDir);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { WorkspaceContext } from '../../src/core/workspace-context.js';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
|
|
6
|
+
vi.mock('fs');
|
|
7
|
+
vi.mock('../../src/core/trajectory.js', () => ({
|
|
8
|
+
TrajectoryRegistry: {
|
|
9
|
+
get: vi.fn(() => ({
|
|
10
|
+
dispose: vi.fn(),
|
|
11
|
+
})),
|
|
12
|
+
use: vi.fn(),
|
|
13
|
+
dispose: vi.fn(),
|
|
14
|
+
clear: vi.fn(),
|
|
15
|
+
}
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
describe('WorkspaceContext', () => {
|
|
19
|
+
// Use path.resolve for cross-platform compatibility on Windows
|
|
20
|
+
const workspaceDir = path.resolve('/mock/workspace');
|
|
21
|
+
const stateDir = path.resolve('/mock/state');
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.clearAllMocks();
|
|
25
|
+
WorkspaceContext.clearCache();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
vi.resetAllMocks();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should create an instance from hook context', () => {
|
|
33
|
+
const mockCtx = { workspaceDir, stateDir };
|
|
34
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
35
|
+
|
|
36
|
+
expect(wctx.workspaceDir).toBe(workspaceDir);
|
|
37
|
+
expect(wctx.stateDir).toBe(stateDir);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should cache instances based on workspaceDir', () => {
|
|
41
|
+
const mockCtx1 = { workspaceDir, stateDir: path.resolve('/state1') };
|
|
42
|
+
const mockCtx2 = { workspaceDir, stateDir: path.resolve('/state2') };
|
|
43
|
+
|
|
44
|
+
const wctx1 = WorkspaceContext.fromHookContext(mockCtx1);
|
|
45
|
+
const wctx2 = WorkspaceContext.fromHookContext(mockCtx2);
|
|
46
|
+
|
|
47
|
+
expect(wctx1).toBe(wctx2);
|
|
48
|
+
expect(wctx1.stateDir).toBe(path.resolve('/state1'));
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should use fallback workspace when workspaceDir is missing', () => {
|
|
52
|
+
const mockCtx = { stateDir };
|
|
53
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
54
|
+
expect(wctx).toBeDefined();
|
|
55
|
+
expect(wctx.workspaceDir).toBeDefined();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should resolve paths using PD_FILES keys', () => {
|
|
59
|
+
const mockCtx = { workspaceDir };
|
|
60
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
61
|
+
|
|
62
|
+
// PROFILE is at .principles/PROFILE.json
|
|
63
|
+
expect(wctx.resolve('PROFILE')).toBe(path.join(workspaceDir, '.principles', 'PROFILE.json'));
|
|
64
|
+
// PLAN is at root
|
|
65
|
+
expect(wctx.resolve('PLAN')).toBe(path.join(workspaceDir, 'PLAN.md'));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should support explicit disposal from cache', () => {
|
|
69
|
+
const mockCtx = { workspaceDir };
|
|
70
|
+
const wctx1 = WorkspaceContext.fromHookContext(mockCtx);
|
|
71
|
+
|
|
72
|
+
WorkspaceContext.dispose(workspaceDir);
|
|
73
|
+
|
|
74
|
+
const wctx2 = WorkspaceContext.fromHookContext(mockCtx);
|
|
75
|
+
expect(wctx1).not.toBe(wctx2);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should allow invalidation of internal state', () => {
|
|
79
|
+
const mockCtx = { workspaceDir };
|
|
80
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
81
|
+
|
|
82
|
+
expect(() => wctx.invalidate()).not.toThrow();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should lazy load ConfigService', () => {
|
|
86
|
+
const mockCtx = { workspaceDir };
|
|
87
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
88
|
+
|
|
89
|
+
const config = wctx.config;
|
|
90
|
+
expect(config).toBeDefined();
|
|
91
|
+
expect(wctx.config).toBe(config); // Should be cached
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should lazy load EventLog', () => {
|
|
95
|
+
const mockCtx = { workspaceDir };
|
|
96
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
97
|
+
|
|
98
|
+
const eventLog = wctx.eventLog;
|
|
99
|
+
expect(eventLog).toBeDefined();
|
|
100
|
+
expect(wctx.eventLog).toBe(eventLog); // Should be cached
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should pass trajectory settings from config into the registry', async () => {
|
|
104
|
+
const { TrajectoryRegistry } = await import('../../src/core/trajectory.js');
|
|
105
|
+
const mockCtx = { workspaceDir };
|
|
106
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
107
|
+
|
|
108
|
+
(wctx as any)._config = {
|
|
109
|
+
get: vi.fn((key: string) => {
|
|
110
|
+
if (key === 'trajectory.blob_inline_threshold_bytes') return 2048;
|
|
111
|
+
if (key === 'trajectory.busy_timeout_ms') return 1500;
|
|
112
|
+
if (key === 'trajectory.orphan_blob_grace_days') return 2;
|
|
113
|
+
return undefined;
|
|
114
|
+
}),
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const trajectory = wctx.trajectory;
|
|
118
|
+
expect(trajectory).toBeDefined();
|
|
119
|
+
expect(TrajectoryRegistry.get).toHaveBeenCalledWith(workspaceDir, {
|
|
120
|
+
blobInlineThresholdBytes: 2048,
|
|
121
|
+
busyTimeoutMs: 1500,
|
|
122
|
+
orphanBlobGraceDays: 2,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should lazy load Dictionary service', () => {
|
|
127
|
+
const mockCtx = { workspaceDir };
|
|
128
|
+
const wctx = WorkspaceContext.fromHookContext(mockCtx);
|
|
129
|
+
|
|
130
|
+
const dictionary = wctx.dictionary;
|
|
131
|
+
expect(dictionary).toBeDefined();
|
|
132
|
+
expect(wctx.dictionary).toBe(dictionary);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "nocturnal-reviewed-subset-v1",
|
|
3
|
+
"description": "Reviewed subset fixture for comparing single-reflector vs Trinity quality",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"createdAt": "2026-03-28T00:00:00.000Z",
|
|
6
|
+
"testCases": [
|
|
7
|
+
{
|
|
8
|
+
"caseId": "case-001",
|
|
9
|
+
"principleId": "T-01",
|
|
10
|
+
"principleDescription": "Map Before Territory: Always survey the existing structure before making changes",
|
|
11
|
+
"sessionId": "session-case-001",
|
|
12
|
+
"signalType": "failure",
|
|
13
|
+
"signalContext": "Agent edited src/main.ts without reading it first, causing a merge conflict",
|
|
14
|
+
"singleReflectorOutput": {
|
|
15
|
+
"artifactId": "single-001-artifact",
|
|
16
|
+
"sessionId": "session-case-001",
|
|
17
|
+
"principleId": "T-01",
|
|
18
|
+
"sourceSnapshotRef": "snapshot-case-001",
|
|
19
|
+
"badDecision": "Edited src/main.ts without first reading its contents, leading to a merge conflict",
|
|
20
|
+
"betterDecision": "Read src/main.ts to understand its current structure before making edits",
|
|
21
|
+
"rationale": "Surveying the existing territory prevents conflicts and ensures edits integrate properly",
|
|
22
|
+
"createdAt": "2026-03-28T00:01:00.000Z"
|
|
23
|
+
},
|
|
24
|
+
"trinityOutput": {
|
|
25
|
+
"selectedCandidateIndex": 0,
|
|
26
|
+
"badDecision": "Edited src/main.ts without first reading its contents, leading to a merge conflict with parallel changes",
|
|
27
|
+
"betterDecision": "Before editing, read src/main.ts to understand its current structure and identify any conflicting sections",
|
|
28
|
+
"rationale": "Surveying the existing territory before making changes prevents conflicts and ensures the edit integrates properly with the current implementation",
|
|
29
|
+
"sessionId": "session-case-001",
|
|
30
|
+
"principleId": "T-01",
|
|
31
|
+
"sourceSnapshotRef": "snapshot-case-001",
|
|
32
|
+
"telemetry": {
|
|
33
|
+
"chainMode": "trinity",
|
|
34
|
+
"dreamerPassed": true,
|
|
35
|
+
"philosopherPassed": true,
|
|
36
|
+
"scribePassed": true,
|
|
37
|
+
"candidateCount": 3,
|
|
38
|
+
"selectedCandidateIndex": 0,
|
|
39
|
+
"stageFailures": []
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"qualityScores": {
|
|
43
|
+
"singleReflector": {
|
|
44
|
+
"specificity": 0.85,
|
|
45
|
+
"principleAlignment": 0.90,
|
|
46
|
+
"actionability": 0.88,
|
|
47
|
+
"rationaleQuality": 0.85,
|
|
48
|
+
"overall": 0.87
|
|
49
|
+
},
|
|
50
|
+
"trinity": {
|
|
51
|
+
"specificity": 0.95,
|
|
52
|
+
"principleAlignment": 0.95,
|
|
53
|
+
"actionability": 0.92,
|
|
54
|
+
"rationaleQuality": 0.95,
|
|
55
|
+
"overall": 0.94
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"trinityWins": true,
|
|
59
|
+
"notes": "Trinity produces more specific badDecision and betterDecision with better rationale"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"caseId": "case-002",
|
|
63
|
+
"principleId": "T-08",
|
|
64
|
+
"principleDescription": "Pain as Signal: Treat failures and errors as signals to pause and reflect",
|
|
65
|
+
"sessionId": "session-case-002",
|
|
66
|
+
"signalType": "pain",
|
|
67
|
+
"signalContext": "Agent retries failing bash command 3 times without any diagnosis",
|
|
68
|
+
"singleReflectorOutput": {
|
|
69
|
+
"artifactId": "single-002-artifact",
|
|
70
|
+
"sessionId": "session-case-002",
|
|
71
|
+
"principleId": "T-08",
|
|
72
|
+
"sourceSnapshotRef": "snapshot-case-002",
|
|
73
|
+
"badDecision": "Retried failing operation without diagnosing",
|
|
74
|
+
"betterDecision": "Diagnose before retrying",
|
|
75
|
+
"rationale": "Treating failures as signals prevents repeated failures",
|
|
76
|
+
"createdAt": "2026-03-28T00:02:00.000Z"
|
|
77
|
+
},
|
|
78
|
+
"trinityOutput": {
|
|
79
|
+
"selectedCandidateIndex": 0,
|
|
80
|
+
"badDecision": "After bash command failed with 'command not found', immediately retried the exact same command without pausing to diagnose the root cause",
|
|
81
|
+
"betterDecision": "When the bash command fails, pause to check if the tool is installed, verify the path, or consult documentation before retrying",
|
|
82
|
+
"rationale": "Treating each failure as a signal to diagnose rather than blindly retry prevents repeated failures and respects the cost of each action attempt",
|
|
83
|
+
"sessionId": "session-case-002",
|
|
84
|
+
"principleId": "T-08",
|
|
85
|
+
"sourceSnapshotRef": "snapshot-case-002",
|
|
86
|
+
"telemetry": {
|
|
87
|
+
"chainMode": "trinity",
|
|
88
|
+
"dreamerPassed": true,
|
|
89
|
+
"philosopherPassed": true,
|
|
90
|
+
"scribePassed": true,
|
|
91
|
+
"candidateCount": 2,
|
|
92
|
+
"selectedCandidateIndex": 0,
|
|
93
|
+
"stageFailures": []
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"qualityScores": {
|
|
97
|
+
"singleReflector": {
|
|
98
|
+
"specificity": 0.70,
|
|
99
|
+
"principleAlignment": 0.85,
|
|
100
|
+
"actionability": 0.75,
|
|
101
|
+
"rationaleQuality": 0.80,
|
|
102
|
+
"overall": 0.77
|
|
103
|
+
},
|
|
104
|
+
"trinity": {
|
|
105
|
+
"specificity": 0.95,
|
|
106
|
+
"principleAlignment": 0.95,
|
|
107
|
+
"actionability": 0.90,
|
|
108
|
+
"rationaleQuality": 0.95,
|
|
109
|
+
"overall": 0.94
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"trinityWins": true,
|
|
113
|
+
"notes": "Single-reflector is generic; Trinity provides specific diagnosis steps"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"caseId": "case-003",
|
|
117
|
+
"principleId": "T-03",
|
|
118
|
+
"principleDescription": "Evidence Over Intuition: Ground decisions in observable evidence",
|
|
119
|
+
"sessionId": "session-case-003",
|
|
120
|
+
"signalType": "gate_block",
|
|
121
|
+
"signalContext": "Agent proceeded with a tool call despite receiving a gate block",
|
|
122
|
+
"singleReflectorOutput": {
|
|
123
|
+
"artifactId": "single-003-artifact",
|
|
124
|
+
"sessionId": "session-case-003",
|
|
125
|
+
"principleId": "T-03",
|
|
126
|
+
"sourceSnapshotRef": "snapshot-case-003",
|
|
127
|
+
"badDecision": "Proceeded despite gate block",
|
|
128
|
+
"betterDecision": "Respect gate blocks",
|
|
129
|
+
"rationale": "Gate blocks are safety mechanisms",
|
|
130
|
+
"createdAt": "2026-03-28T00:03:00.000Z"
|
|
131
|
+
},
|
|
132
|
+
"trinityOutput": {
|
|
133
|
+
"selectedCandidateIndex": 0,
|
|
134
|
+
"badDecision": "Proceeded with a tool call despite receiving a gate block, bypassing the safety check",
|
|
135
|
+
"betterDecision": "Read the blocked operation documentation and obtain proper authorization before retrying the operation",
|
|
136
|
+
"rationale": "Respecting gate blocks prevents unintended system modifications and ensures alignment with operational constraints",
|
|
137
|
+
"sessionId": "session-case-003",
|
|
138
|
+
"principleId": "T-03",
|
|
139
|
+
"sourceSnapshotRef": "snapshot-case-003",
|
|
140
|
+
"telemetry": {
|
|
141
|
+
"chainMode": "trinity",
|
|
142
|
+
"dreamerPassed": true,
|
|
143
|
+
"philosopherPassed": true,
|
|
144
|
+
"scribePassed": true,
|
|
145
|
+
"candidateCount": 3,
|
|
146
|
+
"selectedCandidateIndex": 0,
|
|
147
|
+
"stageFailures": []
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"qualityScores": {
|
|
151
|
+
"singleReflector": {
|
|
152
|
+
"specificity": 0.60,
|
|
153
|
+
"principleAlignment": 0.75,
|
|
154
|
+
"actionability": 0.65,
|
|
155
|
+
"rationaleQuality": 0.70,
|
|
156
|
+
"overall": 0.68
|
|
157
|
+
},
|
|
158
|
+
"trinity": {
|
|
159
|
+
"specificity": 0.90,
|
|
160
|
+
"principleAlignment": 0.95,
|
|
161
|
+
"actionability": 0.88,
|
|
162
|
+
"rationaleQuality": 0.92,
|
|
163
|
+
"overall": 0.91
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"trinityWins": true,
|
|
167
|
+
"notes": "Single-reflector is too generic; Trinity is much more specific"
|
|
168
|
+
}
|
|
169
|
+
],
|
|
170
|
+
"summary": {
|
|
171
|
+
"totalCases": 3,
|
|
172
|
+
"trinityWins": 3,
|
|
173
|
+
"singleReflectorWins": 0,
|
|
174
|
+
"averageDelta": {
|
|
175
|
+
"specificity": 0.23,
|
|
176
|
+
"principleAlignment": 0.10,
|
|
177
|
+
"actionability": 0.17,
|
|
178
|
+
"rationaleQuality": 0.17,
|
|
179
|
+
"overall": 0.19
|
|
180
|
+
},
|
|
181
|
+
"conclusion": "Trinity consistently outperforms single-reflector on reviewed subset"
|
|
182
|
+
}
|
|
183
|
+
}
|