principles-disciple 1.126.0 → 1.128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/archive-impl.d.ts +18 -0
- package/dist/commands/archive-impl.js +105 -0
- package/dist/commands/capabilities.d.ts +3 -0
- package/dist/commands/capabilities.js +76 -0
- package/dist/commands/context.d.ts +5 -0
- package/{src/commands/context.ts → dist/commands/context.js} +34 -83
- package/dist/commands/disable-impl.d.ts +22 -0
- package/dist/commands/disable-impl.js +118 -0
- package/dist/commands/evolution-status.d.ts +4 -0
- package/dist/commands/evolution-status.js +187 -0
- package/dist/commands/export.d.ts +2 -0
- package/dist/commands/export.js +53 -0
- package/dist/commands/focus.d.ts +14 -0
- package/dist/commands/focus.js +443 -0
- package/dist/commands/pain.d.ts +6 -0
- package/{src/commands/pain.ts → dist/commands/pain.js} +137 -188
- package/dist/commands/principle-rollback.d.ts +4 -0
- package/dist/commands/principle-rollback.js +26 -0
- package/dist/commands/promote-impl.d.ts +22 -0
- package/dist/commands/promote-impl.js +194 -0
- package/dist/commands/rollback-impl.d.ts +32 -0
- package/dist/commands/rollback-impl.js +180 -0
- package/dist/commands/rollback.d.ts +19 -0
- package/{src/commands/rollback.ts → dist/commands/rollback.js} +10 -53
- package/dist/commands/samples.d.ts +2 -0
- package/dist/commands/samples.js +58 -0
- package/dist/commands/strategy.d.ts +2 -0
- package/dist/commands/strategy.js +16 -0
- package/dist/commands/thinking-os.d.ts +2 -0
- package/{src/commands/thinking-os.ts → dist/commands/thinking-os.js} +35 -58
- package/dist/commands/workflow-debug.d.ts +6 -0
- package/{src/commands/workflow-debug.ts → dist/commands/workflow-debug.js} +13 -33
- package/dist/config/defaults/runtime.d.ts +58 -0
- package/{src/config/defaults/runtime.ts → dist/config/defaults/runtime.js} +4 -41
- package/dist/config/errors.d.ts +86 -0
- package/dist/config/errors.js +107 -0
- package/{src/config/index.ts → dist/config/index.d.ts} +1 -2
- package/dist/config/index.js +7 -0
- package/dist/constants/diagnostician.d.ts +12 -0
- package/{src/constants/diagnostician.ts → dist/constants/diagnostician.js} +0 -1
- package/dist/constants/tools.d.ts +17 -0
- package/dist/constants/tools.js +53 -0
- package/dist/core/__tests__/focus-history.test.d.ts +1 -0
- package/dist/core/__tests__/focus-history.test.js +160 -0
- package/dist/core/bootstrap-rules.d.ts +50 -0
- package/dist/core/bootstrap-rules.js +187 -0
- package/dist/core/code-implementation-storage.d.ts +71 -0
- package/dist/core/code-implementation-storage.js +139 -0
- package/dist/core/config-health.d.ts +27 -0
- package/dist/core/config-health.js +60 -0
- package/dist/core/config-service.d.ts +15 -0
- package/{src/core/config-service.ts → dist/core/config-service.js} +4 -7
- package/dist/core/config.d.ts +111 -0
- package/{src/core/config.ts → dist/core/config.js} +46 -146
- package/dist/core/control-ui-db.d.ts +106 -0
- package/dist/core/control-ui-db.js +309 -0
- package/dist/core/correction-cue-learner.d.ts +33 -0
- package/dist/core/correction-cue-learner.js +184 -0
- package/dist/core/correction-types.d.ts +3 -0
- package/dist/core/correction-types.js +1 -0
- package/dist/core/detection-funnel.d.ts +33 -0
- package/{src/core/detection-funnel.ts → dist/core/detection-funnel.js} +17 -37
- package/dist/core/detection-service.d.ts +15 -0
- package/{src/core/detection-service.ts → dist/core/detection-service.js} +4 -7
- package/dist/core/dictionary-service.d.ts +15 -0
- package/{src/core/dictionary-service.ts → dist/core/dictionary-service.js} +4 -7
- package/dist/core/dictionary.d.ts +38 -0
- package/{src/core/dictionary.ts → dist/core/dictionary.js} +33 -59
- package/dist/core/empathy-keyword-matcher.d.ts +5 -0
- package/dist/core/empathy-keyword-matcher.js +40 -0
- package/dist/core/empathy-types.d.ts +2 -0
- package/dist/core/empathy-types.js +1 -0
- package/dist/core/event-log.d.ts +90 -0
- package/dist/core/event-log.js +702 -0
- package/dist/core/evolution-engine.d.ts +119 -0
- package/dist/core/evolution-engine.js +460 -0
- package/dist/core/evolution-logger.d.ts +137 -0
- package/dist/core/evolution-logger.js +261 -0
- package/dist/core/evolution-migration.d.ts +5 -0
- package/dist/core/evolution-migration.js +65 -0
- package/dist/core/evolution-reducer.d.ts +124 -0
- package/dist/core/evolution-reducer.js +730 -0
- package/dist/core/evolution-types.d.ts +50 -0
- package/dist/core/evolution-types.js +11 -0
- package/dist/core/external-training-contract.d.ts +276 -0
- package/dist/core/external-training-contract.js +269 -0
- package/dist/core/file-store.d.ts +41 -0
- package/dist/core/file-store.js +46 -0
- package/dist/core/focus-history.d.ts +50 -0
- package/dist/core/focus-history.js +574 -0
- package/dist/core/hygiene/tracker.d.ts +22 -0
- package/dist/core/hygiene/tracker.js +110 -0
- package/dist/core/init.d.ts +30 -0
- package/{src/core/init.ts → dist/core/init.js} +87 -118
- package/dist/core/local-worker-routing.d.ts +124 -0
- package/dist/core/local-worker-routing.js +216 -0
- package/dist/core/migration.d.ts +6 -0
- package/{src/core/migration.ts → dist/core/migration.js} +10 -18
- package/dist/core/model-deployment-registry.d.ts +218 -0
- package/dist/core/model-deployment-registry.js +502 -0
- package/dist/core/model-training-registry.d.ts +295 -0
- package/dist/core/model-training-registry.js +474 -0
- package/dist/core/observability.d.ts +40 -0
- package/dist/core/observability.js +164 -0
- package/dist/core/pain-diagnostic-gate.d.ts +36 -0
- package/dist/core/pain-diagnostic-gate.js +105 -0
- package/dist/core/pain.d.ts +87 -0
- package/dist/core/pain.js +223 -0
- package/dist/core/path-resolver.d.ts +60 -0
- package/{src/core/path-resolver.ts → dist/core/path-resolver.js} +41 -131
- package/dist/core/paths.d.ts +60 -0
- package/{src/core/paths.ts → dist/core/paths.js} +4 -13
- package/dist/core/pd-config-loader.d.ts +96 -0
- package/dist/core/pd-config-loader.js +307 -0
- package/dist/core/pd-task-reconciler.d.ts +89 -0
- package/dist/core/pd-task-reconciler.js +262 -0
- package/dist/core/pd-task-service.d.ts +2 -0
- package/dist/core/pd-task-service.js +32 -0
- package/dist/core/pd-task-store.d.ts +5 -0
- package/dist/core/pd-task-store.js +62 -0
- package/dist/core/pd-task-types.d.ts +8 -0
- package/dist/core/pd-task-types.js +2 -0
- package/dist/core/principle-compiler/__tests__/compiler-replay-gate.test.d.ts +1 -0
- package/dist/core/principle-compiler/__tests__/compiler-replay-gate.test.js +132 -0
- package/dist/core/principle-compiler/code-validator.d.ts +14 -0
- package/dist/core/principle-compiler/code-validator.js +86 -0
- package/dist/core/principle-compiler/compiler.d.ts +45 -0
- package/dist/core/principle-compiler/compiler.js +287 -0
- package/{src/core/principle-compiler/index.ts → dist/core/principle-compiler/index.d.ts} +0 -1
- package/dist/core/principle-compiler/index.js +10 -0
- package/dist/core/principle-compiler/ledger-registrar.d.ts +28 -0
- package/dist/core/principle-compiler/ledger-registrar.js +95 -0
- package/{src/core/principle-compiler/template-generator.ts → dist/core/principle-compiler/template-generator.d.ts} +0 -1
- package/dist/core/principle-compiler/template-generator.js +7 -0
- package/{src/core/principle-injection.ts → dist/core/principle-injection.d.ts} +1 -7
- package/dist/core/principle-injection.js +10 -0
- package/dist/core/principle-internalization/filesystem-lifecycle-datasource.d.ts +15 -0
- package/dist/core/principle-internalization/filesystem-lifecycle-datasource.js +34 -0
- package/dist/core/principle-internalization/lifecycle-read-model.d.ts +17 -0
- package/{src/core/principle-internalization/lifecycle-read-model.ts → dist/core/principle-internalization/lifecycle-read-model.js} +2 -21
- package/dist/core/principle-internalization/lifecycle-refresh.d.ts +2 -0
- package/dist/core/principle-internalization/lifecycle-refresh.js +4 -0
- package/dist/core/principle-internalization/principle-lifecycle-service.d.ts +28 -0
- package/dist/core/principle-internalization/principle-lifecycle-service.js +89 -0
- package/dist/core/principle-training-state.d.ts +47 -0
- package/dist/core/principle-training-state.js +113 -0
- package/dist/core/principle-tree-ledger-adapter.d.ts +32 -0
- package/dist/core/principle-tree-ledger-adapter.js +125 -0
- package/dist/core/principle-tree-ledger.d.ts +82 -0
- package/dist/core/principle-tree-ledger.js +527 -0
- package/dist/core/profile.d.ts +62 -0
- package/dist/core/profile.js +211 -0
- package/dist/core/promotion-gate.d.ts +243 -0
- package/dist/core/promotion-gate.js +554 -0
- package/dist/core/reflection/reflection-context.d.ts +31 -0
- package/dist/core/reflection/reflection-context.js +91 -0
- package/dist/core/replay-engine.d.ts +12 -0
- package/dist/core/replay-engine.js +82 -0
- package/dist/core/risk-calculator.d.ts +22 -0
- package/{src/core/risk-calculator.ts → dist/core/risk-calculator.js} +19 -49
- package/{src/core/rule-host-helpers.ts → dist/core/rule-host-helpers.d.ts} +0 -1
- package/dist/core/rule-host-helpers.js +7 -0
- package/{src/core/rule-host-types.ts → dist/core/rule-host-types.d.ts} +1 -8
- package/dist/core/rule-host-types.js +7 -0
- package/dist/core/rule-host.d.ts +86 -0
- package/dist/core/rule-host.js +311 -0
- package/dist/core/rule-implementation-runtime.d.ts +18 -0
- package/dist/core/rule-implementation-runtime.js +112 -0
- package/dist/core/runtime-v2-prompt-activation-reader.d.ts +22 -0
- package/dist/core/runtime-v2-prompt-activation-reader.js +99 -0
- package/{src/core/schema/db-types.ts → dist/core/schema/db-types.d.ts} +4 -9
- package/dist/core/schema/db-types.js +5 -0
- package/{src/core/schema/index.ts → dist/core/schema/index.d.ts} +1 -10
- package/dist/core/schema/index.js +15 -0
- package/dist/core/schema/migration-runner.d.ts +53 -0
- package/dist/core/schema/migration-runner.js +170 -0
- package/dist/core/schema/migrations/001-init-trajectory.d.ts +6 -0
- package/{src/core/schema/migrations/001-init-trajectory.ts → dist/core/schema/migrations/001-init-trajectory.js} +38 -56
- package/dist/core/schema/migrations/002-init-central.d.ts +5 -0
- package/{src/core/schema/migrations/002-init-central.ts → dist/core/schema/migrations/002-init-central.js} +27 -41
- package/dist/core/schema/migrations/003-init-workflow.d.ts +5 -0
- package/{src/core/schema/migrations/003-init-workflow.ts → dist/core/schema/migrations/003-init-workflow.js} +16 -21
- package/dist/core/schema/migrations/004-add-thinking-and-gfi.d.ts +8 -0
- package/{src/core/schema/migrations/004-add-thinking-and-gfi.ts → dist/core/schema/migrations/004-add-thinking-and-gfi.js} +19 -27
- package/{src/core/schema/migrations/index.ts → dist/core/schema/migrations/index.d.ts} +1 -16
- package/dist/core/schema/migrations/index.js +27 -0
- package/dist/core/schema/schema-definitions.d.ts +46 -0
- package/{src/core/schema/schema-definitions.ts → dist/core/schema/schema-definitions.js} +242 -291
- package/dist/core/session-tracker.d.ts +119 -0
- package/{src/core/session-tracker.ts → dist/core/session-tracker.js} +96 -239
- package/dist/core/shadow-observation-registry.d.ts +217 -0
- package/dist/core/shadow-observation-registry.js +280 -0
- package/dist/core/surface-guard.d.ts +31 -0
- package/dist/core/surface-guard.js +131 -0
- package/dist/core/system-logger.d.ts +8 -0
- package/{src/core/system-logger.ts → dist/core/system-logger.js} +20 -34
- package/dist/core/thinking-models.d.ts +70 -0
- package/dist/core/thinking-models.js +300 -0
- package/dist/core/thinking-os-parser.d.ts +35 -0
- package/dist/core/thinking-os-parser.js +123 -0
- package/dist/core/trajectory-types.d.ts +220 -0
- package/dist/core/trajectory-types.js +8 -0
- package/dist/core/trajectory.d.ts +242 -0
- package/dist/core/trajectory.js +1500 -0
- package/dist/core/workflow-funnel-loader.d.ts +72 -0
- package/dist/core/workflow-funnel-loader.js +135 -0
- package/dist/core/workspace-context.d.ts +111 -0
- package/{src/core/workspace-context.ts → dist/core/workspace-context.js} +50 -105
- package/dist/core/workspace-dir-validation.d.ts +11 -0
- package/dist/core/workspace-dir-validation.js +37 -0
- package/dist/core/workspace-guidance-migrator.d.ts +12 -0
- package/{src/core/workspace-guidance-migrator.ts → dist/core/workspace-guidance-migrator.js} +21 -59
- package/dist/hooks/after-tool-call-helpers.d.ts +89 -0
- package/dist/hooks/after-tool-call-helpers.js +475 -0
- package/dist/hooks/after-tool-call-types.d.ts +86 -0
- package/dist/hooks/after-tool-call-types.js +13 -0
- package/dist/hooks/gate-block-helper.d.ts +44 -0
- package/dist/hooks/gate-block-helper.js +209 -0
- package/dist/hooks/gate.d.ts +16 -0
- package/dist/hooks/gate.js +381 -0
- package/dist/hooks/lifecycle.d.ts +5 -0
- package/dist/hooks/lifecycle.js +287 -0
- package/dist/hooks/llm.d.ts +13 -0
- package/{src/hooks/llm.ts → dist/hooks/llm.js} +63 -117
- package/dist/hooks/message-sanitize.d.ts +24 -0
- package/dist/hooks/message-sanitize.js +77 -0
- package/dist/hooks/pain.d.ts +33 -0
- package/dist/hooks/pain.js +294 -0
- package/dist/hooks/prompt.d.ts +52 -0
- package/dist/hooks/prompt.js +930 -0
- package/dist/hooks/raw-observation-adapter.d.ts +57 -0
- package/dist/hooks/raw-observation-adapter.js +170 -0
- package/dist/hooks/raw-observation-types.d.ts +62 -0
- package/dist/hooks/raw-observation-types.js +15 -0
- package/dist/hooks/subagent.d.ts +9 -0
- package/{src/hooks/subagent.ts → dist/hooks/subagent.js} +20 -60
- package/dist/hooks/trajectory-collector.d.ts +25 -0
- package/dist/hooks/trajectory-collector.js +225 -0
- package/dist/hooks/trajectory-evidence.d.ts +11 -0
- package/dist/hooks/trajectory-evidence.js +88 -0
- package/dist/hooks/triage-adapter.d.ts +58 -0
- package/{src/hooks/triage-adapter.ts → dist/hooks/triage-adapter.js} +36 -68
- package/dist/hooks/trigger-cooldown-tracker.d.ts +30 -0
- package/dist/hooks/trigger-cooldown-tracker.js +55 -0
- package/dist/i18n/commands.d.ts +26 -0
- package/dist/i18n/commands.js +96 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.js +829 -0
- package/dist/openclaw-sdk.d.ts +293 -0
- package/dist/openclaw-sdk.js +4 -0
- package/dist/service/central-database.d.ts +138 -0
- package/dist/service/central-database.js +731 -0
- package/dist/service/central-sync-service.d.ts +8 -0
- package/dist/service/central-sync-service.js +71 -0
- package/dist/service/correction-observer-service.d.ts +19 -0
- package/{src/service/correction-observer-service.ts → dist/service/correction-observer-service.js} +36 -76
- package/dist/service/evolution-dedup.d.ts +27 -0
- package/{src/service/evolution-dedup.ts → dist/service/evolution-dedup.js} +11 -31
- package/{src/service/evolution-queue-migration.ts → dist/service/evolution-queue-migration.d.ts} +15 -62
- package/dist/service/evolution-queue-migration.js +53 -0
- package/dist/service/evolution-worker.d.ts +103 -0
- package/{src/service/evolution-worker.ts → dist/service/evolution-worker.js} +169 -331
- package/dist/service/internalization-auto-consumer-service.d.ts +8 -0
- package/dist/service/internalization-auto-consumer-service.js +322 -0
- package/dist/service/keyword-optimization-service.d.ts +44 -0
- package/dist/service/keyword-optimization-service.js +137 -0
- package/dist/service/phase3-input-filter.d.ts +73 -0
- package/dist/service/phase3-input-filter.js +172 -0
- package/dist/service/queue-io.d.ts +30 -0
- package/dist/service/queue-io.js +79 -0
- package/{src/service/queue-migration.ts → dist/service/queue-migration.d.ts} +6 -45
- package/dist/service/queue-migration.js +56 -0
- package/dist/service/runtime-summary-service.d.ts +158 -0
- package/dist/service/runtime-summary-service.js +636 -0
- package/dist/service/subagent-workflow/subagent-error-utils.d.ts +8 -0
- package/{src/service/subagent-workflow/subagent-error-utils.ts → dist/service/subagent-workflow/subagent-error-utils.js} +3 -6
- package/{src/service/subagent-workflow/types.ts → dist/service/subagent-workflow/types.d.ts} +17 -80
- package/dist/service/subagent-workflow/types.js +11 -0
- package/dist/service/subagent-workflow/workflow-store.d.ts +30 -0
- package/{src/service/subagent-workflow/workflow-store.ts → dist/service/subagent-workflow/workflow-store.js} +43 -108
- package/dist/service/trajectory-service.d.ts +2 -0
- package/dist/service/trajectory-service.js +16 -0
- package/dist/service/workflow-watchdog.d.ts +23 -0
- package/dist/service/workflow-watchdog.js +103 -0
- package/dist/types/event-types.d.ts +2 -0
- package/dist/types/event-types.js +1 -0
- package/dist/types/hygiene-types.d.ts +2 -0
- package/dist/types/hygiene-types.js +1 -0
- package/{src/types/principle-tree-schema.ts → dist/types/principle-tree-schema.d.ts} +2 -25
- package/dist/types/principle-tree-schema.js +24 -0
- package/dist/types/queue.d.ts +2 -0
- package/dist/types/queue.js +1 -0
- package/dist/types/runtime-summary.d.ts +1 -0
- package/dist/types/runtime-summary.js +1 -0
- package/dist/types.d.ts +33 -0
- package/dist/types.js +16 -0
- package/dist/utils/file-lock.d.ts +68 -0
- package/dist/utils/file-lock.js +310 -0
- package/dist/utils/hashing.d.ts +9 -0
- package/{src/utils/hashing.ts → dist/utils/hashing.js} +4 -6
- package/dist/utils/io.d.ts +11 -0
- package/dist/utils/io.js +174 -0
- package/dist/utils/node-vm-polyfill.d.ts +9 -0
- package/{src/utils/node-vm-polyfill.ts → dist/utils/node-vm-polyfill.js} +0 -2
- package/dist/utils/retry.d.ts +210 -0
- package/dist/utils/retry.js +375 -0
- package/dist/utils/session-key.d.ts +10 -0
- package/{src/utils/session-key.ts → dist/utils/session-key.js} +5 -4
- package/dist/utils/shadow-fingerprint.d.ts +16 -0
- package/dist/utils/shadow-fingerprint.js +34 -0
- package/dist/utils/workspace-resolver.d.ts +82 -0
- package/dist/utils/workspace-resolver.js +288 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +8 -2
- package/templates/workspace/.principles/DECISION_POLICY.json +44 -0
- package/templates/workspace/.principles/PRINCIPLES.md +20 -0
- package/templates/workspace/.principles/PROFILE.json +54 -0
- package/templates/workspace/.principles/PROFILE.schema.json +56 -0
- package/templates/workspace/.principles/THINKING_OS.md +65 -0
- package/templates/workspace/.principles/THINKING_OS_ARCHIVE.md +7 -0
- package/templates/workspace/.principles/THINKING_OS_CANDIDATES.md +9 -0
- package/templates/workspace/.principles/models/_INDEX.md +27 -0
- package/templates/workspace/.principles/models/first_principles.md +62 -0
- package/templates/workspace/.principles/models/marketing_4p.md +52 -0
- package/templates/workspace/.principles/models/porter_five.md +63 -0
- package/templates/workspace/.principles/models/swot.md +60 -0
- package/templates/workspace/.principles/models/user_story_map.md +63 -0
- package/templates/workspace/.state/WORKBOARD.json +4 -0
- package/.dependency-cruiser.json +0 -19
- package/ADVANCED_CONFIG_ZH.md +0 -93
- package/AGENT_INSTALL.md +0 -173
- package/AGENT_INSTALL_EN.md +0 -173
- package/CHANGELOG.md +0 -26
- package/INSTALL.md +0 -254
- package/SKILL.md +0 -63
- package/esbuild.config.js +0 -104
- package/src/commands/archive-impl.ts +0 -147
- package/src/commands/capabilities.ts +0 -89
- package/src/commands/disable-impl.ts +0 -159
- package/src/commands/evolution-status.ts +0 -247
- package/src/commands/export.ts +0 -59
- package/src/commands/focus.ts +0 -523
- package/src/commands/principle-rollback.ts +0 -32
- package/src/commands/promote-impl.ts +0 -254
- package/src/commands/rollback-impl.ts +0 -246
- package/src/commands/samples.ts +0 -65
- package/src/commands/strategy.ts +0 -21
- package/src/config/errors.ts +0 -180
- package/src/constants/tools.ts +0 -62
- package/src/core/AGENTS.md +0 -34
- package/src/core/__tests__/focus-history.test.ts +0 -210
- package/src/core/bootstrap-rules.ts +0 -216
- package/src/core/code-implementation-storage.ts +0 -213
- package/src/core/config-health.ts +0 -72
- package/src/core/control-ui-db.ts +0 -454
- package/src/core/correction-cue-learner.ts +0 -239
- package/src/core/correction-types.ts +0 -16
- package/src/core/empathy-keyword-matcher.ts +0 -64
- package/src/core/empathy-types.ts +0 -18
- package/src/core/event-log.ts +0 -787
- package/src/core/evolution-engine.ts +0 -613
- package/src/core/evolution-logger.ts +0 -357
- package/src/core/evolution-migration.ts +0 -77
- package/src/core/evolution-reducer.ts +0 -891
- package/src/core/evolution-types.ts +0 -110
- package/src/core/external-training-contract.ts +0 -530
- package/src/core/file-store.ts +0 -80
- package/src/core/focus-history.ts +0 -763
- package/src/core/hygiene/tracker.ts +0 -122
- package/src/core/local-worker-routing.ts +0 -337
- package/src/core/model-deployment-registry.ts +0 -724
- package/src/core/model-training-registry.ts +0 -815
- package/src/core/observability.ts +0 -242
- package/src/core/pain-diagnostic-gate.ts +0 -169
- package/src/core/pain.ts +0 -309
- package/src/core/pd-config-loader.ts +0 -400
- package/src/core/pd-task-reconciler.ts +0 -380
- package/src/core/pd-task-service.ts +0 -43
- package/src/core/pd-task-store.ts +0 -78
- package/src/core/pd-task-types.ts +0 -24
- package/src/core/principle-compiler/__tests__/compiler-replay-gate.test.ts +0 -174
- package/src/core/principle-compiler/code-validator.ts +0 -93
- package/src/core/principle-compiler/compiler.ts +0 -327
- package/src/core/principle-compiler/ledger-registrar.ts +0 -116
- package/src/core/principle-internalization/filesystem-lifecycle-datasource.ts +0 -42
- package/src/core/principle-internalization/lifecycle-refresh.ts +0 -11
- package/src/core/principle-internalization/principle-lifecycle-service.ts +0 -170
- package/src/core/principle-training-state.ts +0 -177
- package/src/core/principle-tree-ledger-adapter.ts +0 -145
- package/src/core/principle-tree-ledger.ts +0 -725
- package/src/core/profile.ts +0 -228
- package/src/core/promotion-gate.ts +0 -854
- package/src/core/reflection/reflection-context.ts +0 -133
- package/src/core/replay-engine.ts +0 -106
- package/src/core/rule-host.ts +0 -386
- package/src/core/rule-implementation-runtime.ts +0 -145
- package/src/core/runtime-v2-prompt-activation-reader.ts +0 -114
- package/src/core/schema/migration-runner.ts +0 -207
- package/src/core/shadow-observation-registry.ts +0 -508
- package/src/core/surface-guard.ts +0 -188
- package/src/core/thinking-models.ts +0 -377
- package/src/core/thinking-os-parser.ts +0 -165
- package/src/core/trajectory-types.ts +0 -247
- package/src/core/trajectory.ts +0 -1831
- package/src/core/workflow-funnel-loader.ts +0 -195
- package/src/core/workspace-dir-validation.ts +0 -52
- package/src/hooks/AGENTS.md +0 -31
- package/src/hooks/after-tool-call-helpers.ts +0 -601
- package/src/hooks/after-tool-call-types.ts +0 -99
- package/src/hooks/gate-block-helper.ts +0 -265
- package/src/hooks/gate.ts +0 -394
- package/src/hooks/lifecycle.ts +0 -334
- package/src/hooks/message-sanitize.ts +0 -102
- package/src/hooks/pain.ts +0 -358
- package/src/hooks/prompt.ts +0 -1102
- package/src/hooks/raw-observation-adapter.ts +0 -215
- package/src/hooks/raw-observation-types.ts +0 -77
- package/src/hooks/trajectory-collector.ts +0 -253
- package/src/hooks/trajectory-evidence.ts +0 -97
- package/src/hooks/trigger-cooldown-tracker.ts +0 -82
- package/src/i18n/commands.ts +0 -101
- package/src/index.ts +0 -939
- package/src/openclaw-sdk.ts +0 -312
- package/src/service/central-database.ts +0 -936
- package/src/service/central-sync-service.ts +0 -85
- package/src/service/internalization-auto-consumer-service.ts +0 -397
- package/src/service/keyword-optimization-service.ts +0 -169
- package/src/service/phase3-input-filter.ts +0 -237
- package/src/service/queue-io.ts +0 -108
- package/src/service/runtime-summary-service.ts +0 -990
- package/src/service/trajectory-service.ts +0 -16
- package/src/service/workflow-watchdog.ts +0 -125
- package/src/types/event-types.ts +0 -39
- package/src/types/hygiene-types.ts +0 -8
- package/src/types/queue.ts +0 -15
- package/src/types/runtime-summary.ts +0 -5
- package/src/types.ts +0 -53
- package/src/utils/file-lock.ts +0 -394
- package/src/utils/io.ts +0 -176
- package/src/utils/retry.ts +0 -573
- package/src/utils/shadow-fingerprint.ts +0 -42
- package/src/utils/workspace-resolver.ts +0 -393
- package/tests/README.md +0 -120
- package/tests/build-artifacts.test.ts +0 -55
- package/tests/commands/evolution-status.test.ts +0 -511
- package/tests/commands/export.test.ts +0 -78
- package/tests/commands/pain.test.ts +0 -287
- package/tests/commands/samples.test.ts +0 -65
- package/tests/commands/strategy.test.ts +0 -19
- package/tests/commands/thinking-os.test.ts +0 -88
- package/tests/core/bootstrap-rules.test.ts +0 -596
- package/tests/core/code-implementation-storage.test.ts +0 -300
- package/tests/core/code-validator.test.ts +0 -197
- package/tests/core/config-service.test.ts +0 -89
- package/tests/core/config.test.ts +0 -90
- package/tests/core/control-ui-db.test.ts +0 -75
- package/tests/core/core-principle-registry-drift.test.ts +0 -39
- package/tests/core/core-template-guidance.test.ts +0 -21
- package/tests/core/correction-cue-learner.test.ts +0 -345
- package/tests/core/detection-service.test.ts +0 -50
- package/tests/core/dictionary-service.test.ts +0 -116
- package/tests/core/dictionary.test.ts +0 -171
- package/tests/core/empathy-keyword-matcher.test.ts +0 -209
- package/tests/core/event-log.test.ts +0 -484
- package/tests/core/evolution-engine.test.ts +0 -610
- package/tests/core/evolution-logger.test.ts +0 -148
- package/tests/core/evolution-migration.test.ts +0 -374
- package/tests/core/evolution-paths.test.ts +0 -21
- package/tests/core/evolution-reducer.compilation-retry.test.ts +0 -189
- package/tests/core/evolution-reducer.detector-metadata.test.ts +0 -602
- package/tests/core/evolution-types-loop.test.ts +0 -48
- package/tests/core/external-training-contract.test.ts +0 -463
- package/tests/core/file-store.test.ts +0 -102
- package/tests/core/focus-history.test.ts +0 -874
- package/tests/core/init-flatten.test.ts +0 -69
- package/tests/core/init-refactor.test.ts +0 -87
- package/tests/core/init-v1.3.test.ts +0 -46
- package/tests/core/init.test.ts +0 -190
- package/tests/core/ledger-registrar.test.ts +0 -235
- package/tests/core/migration.test.ts +0 -84
- package/tests/core/model-deployment-registry.test.ts +0 -858
- package/tests/core/model-training-registry.test.ts +0 -908
- package/tests/core/observability.test.ts +0 -382
- package/tests/core/pain-diagnostic-gate.test.ts +0 -614
- package/tests/core/pain-score.property.test.ts +0 -19
- package/tests/core/pain.test.ts +0 -132
- package/tests/core/path-resolver.test.ts +0 -57
- package/tests/core/paths-refactor.test.ts +0 -20
- package/tests/core/pd-config-loader.test.ts +0 -407
- package/tests/core/pd-task-store.test.ts +0 -126
- package/tests/core/phase7-rollout-integration.test.ts +0 -477
- package/tests/core/principle-compiler.test.ts +0 -350
- package/tests/core/principle-injection.test.ts +0 -223
- package/tests/core/principle-internalization/deprecated-readiness.test.ts +0 -193
- package/tests/core/principle-internalization/lifecycle-metrics.test.ts +0 -350
- package/tests/core/principle-internalization/lifecycle-routing-policy.test.ts +0 -212
- package/tests/core/principle-internalization/lineage-source-retired.test.ts +0 -56
- package/tests/core/principle-internalization/principle-lifecycle-service.test.ts +0 -189
- package/tests/core/principle-training-state.test.ts +0 -939
- package/tests/core/principle-tree-ledger-adapter.test.ts +0 -253
- package/tests/core/principle-tree-ledger.test.ts +0 -423
- package/tests/core/profile.test.ts +0 -56
- package/tests/core/promotion-gate.test.ts +0 -561
- package/tests/core/queue-purge.test.ts +0 -337
- package/tests/core/reflection-context.test.ts +0 -342
- package/tests/core/regression-v1-9-1.test.ts +0 -266
- package/tests/core/replay-engine.test.ts +0 -165
- package/tests/core/risk-calculator.test.ts +0 -168
- package/tests/core/rule-host-adversarial-output.test.ts +0 -242
- package/tests/core/rule-host-autocorrect-vm.test.ts +0 -163
- package/tests/core/rule-host-helpers.test.ts +0 -120
- package/tests/core/rule-host-resource-bounds.test.ts +0 -231
- package/tests/core/rule-host-sqlite-source.test.ts +0 -720
- package/tests/core/rule-host-unhealthy-visibility.test.ts +0 -261
- package/tests/core/rule-host-validation.test.ts +0 -315
- package/tests/core/rule-implementation-runtime.test.ts +0 -49
- package/tests/core/session-tracker.test.ts +0 -191
- package/tests/core/surface-guard.test.ts +0 -338
- package/tests/core/template-generator.test.ts +0 -101
- package/tests/core/trajectory.test.ts +0 -427
- package/tests/core/workflow-funnel-loader.test.ts +0 -1028
- package/tests/core/workspace-context-factory.test.ts +0 -18
- package/tests/core/workspace-context.test.ts +0 -187
- package/tests/core/workspace-guidance-migrator.test.ts +0 -248
- package/tests/core-anti-growth.test.ts +0 -182
- package/tests/evolution-worker-quarantine.test.ts +0 -400
- package/tests/evolution-worker-slimming.test.ts +0 -380
- package/tests/fixtures/legacy-queue-v1.json +0 -74
- package/tests/fixtures/production-compatibility.test.ts +0 -147
- package/tests/fixtures/production-mock-generator.ts +0 -282
- package/tests/globalSetup.ts +0 -38
- package/tests/hook-workspace-nextaction-contract.test.ts +0 -50
- package/tests/hooks/confirm-first-removal.test.ts +0 -188
- package/tests/hooks/gate-auto-correct-shadow.test.ts +0 -309
- package/tests/hooks/gate-auto-correct.test.ts +0 -664
- package/tests/hooks/gate-block-helper-profile.test.ts +0 -186
- package/tests/hooks/gate-no-path-write-tool.test.ts +0 -171
- package/tests/hooks/gate-rule-host-pipeline.test.ts +0 -230
- package/tests/hooks/gate-rule-host-real-pipeline.test.ts +0 -190
- package/tests/hooks/lifecycle.test.ts +0 -248
- package/tests/hooks/message-sanitize.test.ts +0 -244
- package/tests/hooks/pain-emission-characterization.test.ts +0 -420
- package/tests/hooks/pain.test.ts +0 -795
- package/tests/hooks/prompt-characterization.test.ts +0 -476
- package/tests/hooks/prompt-diet.test.ts +0 -335
- package/tests/hooks/prompt-size-guard.test.ts +0 -319
- package/tests/hooks/raw-observation-adapter.test.ts +0 -312
- package/tests/hooks/runtime-v2-prompt-activation.test.ts +0 -895
- package/tests/hooks/single-gate-pain-admission.test.ts +0 -258
- package/tests/hooks/subagent.test.ts +0 -469
- package/tests/hooks/trajectory-collector.test.ts +0 -269
- package/tests/hooks/trajectory-evidence.test.ts +0 -280
- package/tests/hooks/triage-adapter.test.ts +0 -331
- package/tests/hygiene-tracker.test.ts +0 -77
- package/tests/index.test.ts +0 -142
- package/tests/integration/auto-entry-gate.test.ts +0 -256
- package/tests/integration/gate-real-io.e2e.test.ts +0 -248
- package/tests/integration/m8-legacy-paths.test.ts +0 -63
- package/tests/integration/mvp-surface-registry-guard.test.ts +0 -536
- package/tests/integration/pain-id-chain-e2e.test.ts +0 -313
- package/tests/integration/principle-compiler-e2e.test.ts +0 -403
- package/tests/integration/principle-lifecycle.e2e.test.ts +0 -198
- package/tests/integration/runtime-v2-pain-guard.test.ts +0 -125
- package/tests/integration/trajectory-lifecycle.e2e.test.ts +0 -523
- package/tests/internalization-auto-consumer-gate.test.ts +0 -158
- package/tests/internalization-auto-consumer-service.test.ts +0 -219
- package/tests/plugin-config-resolution-cutover.test.ts +0 -359
- package/tests/queue/async-lock.test.ts +0 -200
- package/tests/runtime-v2-discovery-guard.test.ts +0 -153
- package/tests/scripts/validate-live-path.test.ts +0 -286
- package/tests/service/central-database.test.ts +0 -457
- package/tests/service/correction-observer-service.test.ts +0 -505
- package/tests/service/evolution-worker.compilation-backfill.test.ts +0 -203
- package/tests/service/evolution-worker.correction-observer.test.ts +0 -50
- package/tests/service/evolution-worker.queue.test.ts +0 -296
- package/tests/service/evolution-worker.timeout.test.ts +0 -233
- package/tests/service/keyword-optimization-service.test.ts +0 -121
- package/tests/service/phase3-input-filter.test.ts +0 -289
- package/tests/service/queue-io.test.ts +0 -168
- package/tests/service/queue-migration.test.ts +0 -147
- package/tests/service/runtime-summary-service.test.ts +0 -1100
- package/tests/service/workflow-watchdog.test.ts +0 -281
- package/tests/task-compliance.test.ts +0 -166
- package/tests/test-utils.ts +0 -48
- package/tests/utils/file-lock.test.ts +0 -409
- package/tests/utils/hashing.test.ts +0 -32
- package/tests/utils/hook-workspace-resolver.test.ts +0 -524
- package/tests/utils/io.test.ts +0 -39
- package/tests/utils/retry.test.ts +0 -327
- package/tests/utils/session-key.test.ts +0 -52
- package/tsconfig.json +0 -16
- package/vitest.config.ts +0 -61
- package/vitest.unit.config.ts +0 -12
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Regression tests for bug fixes in v1.9.1
|
|
3
|
-
*
|
|
4
|
-
* Validates fixes for:
|
|
5
|
-
* - #208/#209: isExpectedSubagentError expanded + terminal_error classification
|
|
6
|
-
* - #212: evaluability defaults to weak_heuristic, principles are evaluable
|
|
7
|
-
* - #213: fire-and-forget Promise has .catch()
|
|
8
|
-
* - #214: sleep_reflection timeout expires nocturnal workflow
|
|
9
|
-
* - #207/#210: stateDir properly passed through WorkspaceContext
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import * as fs from 'fs';
|
|
13
|
-
import * as os from 'os';
|
|
14
|
-
import * as path from 'path';
|
|
15
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
16
|
-
import { EvolutionReducerImpl } from '../../src/core/evolution-reducer.js';
|
|
17
|
-
import {
|
|
18
|
-
listEvaluablePrinciples,
|
|
19
|
-
transitionInternalizationStatus,
|
|
20
|
-
getPrincipleState,
|
|
21
|
-
} from '../../src/core/principle-training-state.js';
|
|
22
|
-
import { isExpectedSubagentError } from '../../src/service/subagent-workflow/subagent-error-utils.js';
|
|
23
|
-
import { WorkspaceContext } from '../../src/core/workspace-context.js';
|
|
24
|
-
import { safeRmDir } from '../test-utils.js';
|
|
25
|
-
|
|
26
|
-
const tempDirs: string[] = [];
|
|
27
|
-
|
|
28
|
-
function makeTempDir(): string {
|
|
29
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-regression-'));
|
|
30
|
-
tempDirs.push(dir);
|
|
31
|
-
return dir;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
for (const dir of tempDirs.splice(0)) {
|
|
36
|
-
safeRmDir(dir);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// ── #208/#209: isExpectedSubagentError covers daemon-mode errors ──
|
|
41
|
-
|
|
42
|
-
describe('#208/#209: isExpectedSubagentError daemon-mode coverage', () => {
|
|
43
|
-
it('matches original gateway request errors', () => {
|
|
44
|
-
expect(isExpectedSubagentError('Plugin runtime subagent methods are only available during a gateway request')).toBe(true);
|
|
45
|
-
expect(isExpectedSubagentError('cannot start workflow for boot session')).toBe(true);
|
|
46
|
-
expect(isExpectedSubagentError('subagent runtime unavailable')).toBe(true);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('matches NocturnalWorkflowManager specific error', () => {
|
|
50
|
-
expect(isExpectedSubagentError('NocturnalWorkflowManager: subagent runtime unavailable')).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('matches daemon-mode connection errors', () => {
|
|
54
|
-
expect(isExpectedSubagentError('subagent is not available')).toBe(true);
|
|
55
|
-
expect(isExpectedSubagentError('gateway is not running')).toBe(true);
|
|
56
|
-
expect(isExpectedSubagentError('process isolation error: ECONNREFUSED')).toBe(true);
|
|
57
|
-
// #3 review fix: connection errors now require 'subagent' in message to reduce false positives
|
|
58
|
-
expect(isExpectedSubagentError('subagent connection refused')).toBe(true);
|
|
59
|
-
expect(isExpectedSubagentError('subagent connection reset by peer')).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('does not match unrelated errors', () => {
|
|
63
|
-
expect(isExpectedSubagentError('file not found')).toBe(false);
|
|
64
|
-
expect(isExpectedSubagentError('syntax error in config')).toBe(false);
|
|
65
|
-
expect(isExpectedSubagentError('network timeout to external API')).toBe(false);
|
|
66
|
-
// #3 review fix: generic connection errors without 'subagent' should NOT match
|
|
67
|
-
expect(isExpectedSubagentError('connection refused')).toBe(false);
|
|
68
|
-
expect(isExpectedSubagentError('connection reset by peer')).toBe(false);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// ── #212: evaluability defaults to weak_heuristic ──
|
|
73
|
-
|
|
74
|
-
describe('#212: principle evaluability and internalization status', () => {
|
|
75
|
-
it('new principle without explicit evaluability defaults to weak_heuristic', () => {
|
|
76
|
-
const workspace = makeTempDir();
|
|
77
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
78
|
-
|
|
79
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
80
|
-
painId: 'regression-212-1',
|
|
81
|
-
painType: 'tool_failure',
|
|
82
|
-
triggerPattern: 'api call times out after 30s',
|
|
83
|
-
action: 'implement retry with exponential backoff',
|
|
84
|
-
source: 'test',
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
expect(id).not.toBeNull();
|
|
88
|
-
const principle = reducer.getPrincipleById(id!);
|
|
89
|
-
expect(principle).not.toBeNull();
|
|
90
|
-
expect(principle!.evaluability).toBe('weak_heuristic');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('new principle with weak_heuristic evaluability gets needs_training status', () => {
|
|
94
|
-
const workspace = makeTempDir();
|
|
95
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
96
|
-
|
|
97
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
98
|
-
painId: 'regression-212-2',
|
|
99
|
-
painType: 'tool_failure',
|
|
100
|
-
triggerPattern: 'database connection pool exhausted',
|
|
101
|
-
action: 'queue requests and retry with timeout',
|
|
102
|
-
source: 'test',
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
expect(id).not.toBeNull();
|
|
106
|
-
const trainingState = getPrincipleState(workspace, id!);
|
|
107
|
-
expect(trainingState.internalizationStatus).toBe('needs_training');
|
|
108
|
-
expect(trainingState.evaluability).toBe('weak_heuristic');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('new principle with manual_only evaluability gets prompt_only status', () => {
|
|
112
|
-
const workspace = makeTempDir();
|
|
113
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
114
|
-
|
|
115
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
116
|
-
painId: 'regression-212-3',
|
|
117
|
-
painType: 'user_frustration',
|
|
118
|
-
triggerPattern: 'ambiguous user intent',
|
|
119
|
-
action: 'ask clarifying questions before acting',
|
|
120
|
-
source: 'test',
|
|
121
|
-
evaluability: 'manual_only',
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
expect(id).not.toBeNull();
|
|
125
|
-
const trainingState = getPrincipleState(workspace, id!);
|
|
126
|
-
expect(trainingState.internalizationStatus).toBe('prompt_only');
|
|
127
|
-
expect(trainingState.evaluability).toBe('manual_only');
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('listEvaluablePrinciples includes weak_heuristic principles', () => {
|
|
131
|
-
const workspace = makeTempDir();
|
|
132
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
133
|
-
|
|
134
|
-
// Create a weak_heuristic principle (should be evaluable)
|
|
135
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
136
|
-
painId: 'regression-212-eval-1',
|
|
137
|
-
painType: 'tool_failure',
|
|
138
|
-
triggerPattern: 'regex parse error on empty input',
|
|
139
|
-
action: 'validate input before regex processing',
|
|
140
|
-
source: 'test',
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
expect(id).not.toBeNull();
|
|
144
|
-
const evaluable = listEvaluablePrinciples(workspace);
|
|
145
|
-
expect(evaluable.length).toBeGreaterThan(0);
|
|
146
|
-
// Principle IDs are auto-generated (P_001, P_002...), check by the returned ID
|
|
147
|
-
expect(evaluable.some(p => p.principleId === id)).toBe(true);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('listEvaluablePrinciples excludes manual_only + prompt_only principles', () => {
|
|
151
|
-
const workspace = makeTempDir();
|
|
152
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
153
|
-
|
|
154
|
-
// Create a manual_only principle (should NOT be evaluable)
|
|
155
|
-
reducer.createPrincipleFromDiagnosis({
|
|
156
|
-
painId: 'regression-212-noeval-1',
|
|
157
|
-
painType: 'user_frustration',
|
|
158
|
-
triggerPattern: 'user confused about feature',
|
|
159
|
-
action: 'provide contextual help',
|
|
160
|
-
source: 'test',
|
|
161
|
-
evaluability: 'manual_only',
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
const evaluable = listEvaluablePrinciples(workspace);
|
|
165
|
-
expect(evaluable.some(p => p.principleId.includes('regression-212-noeval'))).toBe(false);
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// ── #212: internalization status transition mechanism ──
|
|
170
|
-
|
|
171
|
-
describe('#212: internalization status transitions', () => {
|
|
172
|
-
it('transitions prompt_only → needs_training', () => {
|
|
173
|
-
const workspace = makeTempDir();
|
|
174
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
175
|
-
|
|
176
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
177
|
-
painId: 'regression-212-transition-1',
|
|
178
|
-
painType: 'user_frustration',
|
|
179
|
-
triggerPattern: 'user error on complex form',
|
|
180
|
-
action: 'simplify form with progressive disclosure',
|
|
181
|
-
source: 'test',
|
|
182
|
-
evaluability: 'manual_only',
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
expect(id).not.toBeNull();
|
|
186
|
-
const before = getPrincipleState(workspace, id!);
|
|
187
|
-
expect(before.internalizationStatus).toBe('prompt_only');
|
|
188
|
-
|
|
189
|
-
transitionInternalizationStatus(workspace, id!, 'needs_training');
|
|
190
|
-
const after = getPrincipleState(workspace, id!);
|
|
191
|
-
expect(after.internalizationStatus).toBe('needs_training');
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('rejects invalid transition prompt_only → in_training', () => {
|
|
195
|
-
const workspace = makeTempDir();
|
|
196
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
197
|
-
|
|
198
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
199
|
-
painId: 'regression-212-invalid-transition',
|
|
200
|
-
painType: 'user_frustration',
|
|
201
|
-
triggerPattern: 'user error on complex form',
|
|
202
|
-
action: 'simplify form',
|
|
203
|
-
source: 'test',
|
|
204
|
-
evaluability: 'manual_only',
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
expect(() => transitionInternalizationStatus(workspace, id!, 'in_training')).toThrow(
|
|
208
|
-
'Invalid transition: prompt_only → in_training'
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('transitions regressed → needs_training', () => {
|
|
213
|
-
const workspace = makeTempDir();
|
|
214
|
-
const reducer = new EvolutionReducerImpl({ workspaceDir: workspace, stateDir: workspace });
|
|
215
|
-
|
|
216
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
217
|
-
painId: 'regression-212-regress',
|
|
218
|
-
painType: 'tool_failure',
|
|
219
|
-
triggerPattern: 'timeout on slow endpoint',
|
|
220
|
-
action: 'add pagination and caching',
|
|
221
|
-
source: 'test',
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// Transition chain: needs_training → in_training → deployed_pending_eval → regressed → needs_training
|
|
225
|
-
transitionInternalizationStatus(workspace, id!, 'in_training');
|
|
226
|
-
transitionInternalizationStatus(workspace, id!, 'deployed_pending_eval');
|
|
227
|
-
|
|
228
|
-
const before = getPrincipleState(workspace, id!);
|
|
229
|
-
expect(before.internalizationStatus).toBe('deployed_pending_eval');
|
|
230
|
-
|
|
231
|
-
// Can transition to regressed from deployed_pending_eval
|
|
232
|
-
transitionInternalizationStatus(workspace, id!, 'regressed');
|
|
233
|
-
const regressed = getPrincipleState(workspace, id!);
|
|
234
|
-
expect(regressed.internalizationStatus).toBe('regressed');
|
|
235
|
-
|
|
236
|
-
// Can transition back to needs_training from regressed
|
|
237
|
-
transitionInternalizationStatus(workspace, id!, 'needs_training');
|
|
238
|
-
const after = getPrincipleState(workspace, id!);
|
|
239
|
-
expect(after.internalizationStatus).toBe('needs_training');
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
// ── #207/#210: stateDir via WorkspaceContext ──
|
|
244
|
-
|
|
245
|
-
describe('#207/#210: WorkspaceContext provides stateDir to evolutionReducer', () => {
|
|
246
|
-
it('evolutionReducer from WorkspaceContext has stateDir', () => {
|
|
247
|
-
const workspace = makeTempDir();
|
|
248
|
-
const wctx = WorkspaceContext.fromHookContext({ workspaceDir: workspace });
|
|
249
|
-
|
|
250
|
-
// The reducer should have stateDir set via WorkspaceContext
|
|
251
|
-
// We can verify by creating a principle and checking training store
|
|
252
|
-
const reducer = wctx.evolutionReducer;
|
|
253
|
-
const id = reducer.createPrincipleFromDiagnosis({
|
|
254
|
-
painId: 'regression-207-1',
|
|
255
|
-
painType: 'tool_failure',
|
|
256
|
-
triggerPattern: 'null pointer on empty list',
|
|
257
|
-
action: 'check for empty list before iteration',
|
|
258
|
-
source: 'test',
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
expect(id).not.toBeNull();
|
|
262
|
-
// If stateDir was properly passed, training store should have been written
|
|
263
|
-
const trainingState = getPrincipleState(workspace, id!);
|
|
264
|
-
expect(trainingState.principleId).toBe(id);
|
|
265
|
-
});
|
|
266
|
-
});
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
-
import { ReplayEngine } from '../../src/core/replay-engine.js';
|
|
6
|
-
import { createImplementationAssetDir, getImplementationAssetRoot } from '../../src/core/code-implementation-storage.js';
|
|
7
|
-
import { safeRmDir } from '../test-utils.js';
|
|
8
|
-
|
|
9
|
-
describe('ReplayEngine', () => {
|
|
10
|
-
let tempDir: string;
|
|
11
|
-
let workspaceDir: string;
|
|
12
|
-
let stateDir: string;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pd-replay-engine-'));
|
|
16
|
-
workspaceDir = path.join(tempDir, 'workspace');
|
|
17
|
-
stateDir = path.join(tempDir, '.state');
|
|
18
|
-
fs.mkdirSync(workspaceDir, { recursive: true });
|
|
19
|
-
fs.mkdirSync(stateDir, { recursive: true });
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
safeRmDir(tempDir);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('listReports returns empty array when no replays exist', () => {
|
|
27
|
-
const engine = new ReplayEngine(workspaceDir, stateDir);
|
|
28
|
-
expect(engine.listReports('IMPL-1')).toEqual([]);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('listReports returns persisted replay reports sorted by name descending', () => {
|
|
32
|
-
createImplementationAssetDir(stateDir, 'IMPL-1', '1.0.0');
|
|
33
|
-
const replayDir = path.join(getImplementationAssetRoot(stateDir, 'IMPL-1'), 'replays');
|
|
34
|
-
fs.mkdirSync(replayDir, { recursive: true });
|
|
35
|
-
|
|
36
|
-
const report1 = {
|
|
37
|
-
implementationId: 'IMPL-1',
|
|
38
|
-
generatedAt: '2026-04-08T00:00:00.000Z',
|
|
39
|
-
overallDecision: 'needs-review',
|
|
40
|
-
blockers: [],
|
|
41
|
-
sampleFingerprints: [],
|
|
42
|
-
replayResults: {
|
|
43
|
-
painNegative: { total: 0, passed: 0, failed: 0, details: [] },
|
|
44
|
-
successPositive: { total: 0, passed: 0, failed: 0, details: [] },
|
|
45
|
-
principleAnchor: { total: 0, passed: 0, failed: 0, details: [] },
|
|
46
|
-
},
|
|
47
|
-
evidenceSummary: {
|
|
48
|
-
evidenceStatus: 'empty',
|
|
49
|
-
totalSamples: 0,
|
|
50
|
-
classifiedCounts: { painNegative: 0, successPositive: 0, principleAnchor: 0 },
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const report2 = {
|
|
55
|
-
...report1,
|
|
56
|
-
generatedAt: '2026-04-09T00:00:00.000Z',
|
|
57
|
-
overallDecision: 'pass',
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
fs.writeFileSync(path.join(replayDir, '2026-04-08T00-00-00-000Z.json'), JSON.stringify(report1, null, 2), 'utf-8');
|
|
61
|
-
fs.writeFileSync(path.join(replayDir, '2026-04-09T00-00-00-000Z.json'), JSON.stringify(report2, null, 2), 'utf-8');
|
|
62
|
-
|
|
63
|
-
const engine = new ReplayEngine(workspaceDir, stateDir);
|
|
64
|
-
const reports = engine.listReports('IMPL-1');
|
|
65
|
-
|
|
66
|
-
expect(reports).toHaveLength(2);
|
|
67
|
-
expect(reports[0].overallDecision).toBe('pass');
|
|
68
|
-
expect(reports[1].overallDecision).toBe('needs-review');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('getLatestReport returns the most recent report', () => {
|
|
72
|
-
createImplementationAssetDir(stateDir, 'IMPL-1', '1.0.0');
|
|
73
|
-
const replayDir = path.join(getImplementationAssetRoot(stateDir, 'IMPL-1'), 'replays');
|
|
74
|
-
fs.mkdirSync(replayDir, { recursive: true });
|
|
75
|
-
|
|
76
|
-
const report = {
|
|
77
|
-
implementationId: 'IMPL-1',
|
|
78
|
-
generatedAt: '2026-04-08T00:00:00.000Z',
|
|
79
|
-
overallDecision: 'pass',
|
|
80
|
-
blockers: [],
|
|
81
|
-
sampleFingerprints: [],
|
|
82
|
-
replayResults: {
|
|
83
|
-
painNegative: { total: 1, passed: 1, failed: 0, details: [] },
|
|
84
|
-
successPositive: { total: 0, passed: 0, failed: 0, details: [] },
|
|
85
|
-
principleAnchor: { total: 0, passed: 0, failed: 0, details: [] },
|
|
86
|
-
},
|
|
87
|
-
evidenceSummary: {
|
|
88
|
-
evidenceStatus: 'observed',
|
|
89
|
-
totalSamples: 1,
|
|
90
|
-
classifiedCounts: { painNegative: 1, successPositive: 0, principleAnchor: 0 },
|
|
91
|
-
},
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
fs.writeFileSync(path.join(replayDir, '2026-04-08T00-00-00-000Z.json'), JSON.stringify(report, null, 2), 'utf-8');
|
|
95
|
-
|
|
96
|
-
const engine = new ReplayEngine(workspaceDir, stateDir);
|
|
97
|
-
const latest = engine.getLatestReport('IMPL-1');
|
|
98
|
-
|
|
99
|
-
expect(latest).not.toBeNull();
|
|
100
|
-
expect(latest!.overallDecision).toBe('pass');
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('getLatestReport returns null when no reports exist', () => {
|
|
104
|
-
const engine = new ReplayEngine(workspaceDir, stateDir);
|
|
105
|
-
expect(engine.getLatestReport('IMPL-1')).toBeNull();
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('hasPassingReport returns true when a passing report exists', () => {
|
|
109
|
-
createImplementationAssetDir(stateDir, 'IMPL-1', '1.0.0');
|
|
110
|
-
const replayDir = path.join(getImplementationAssetRoot(stateDir, 'IMPL-1'), 'replays');
|
|
111
|
-
fs.mkdirSync(replayDir, { recursive: true });
|
|
112
|
-
|
|
113
|
-
const report = {
|
|
114
|
-
implementationId: 'IMPL-1',
|
|
115
|
-
generatedAt: '2026-04-08T00:00:00.000Z',
|
|
116
|
-
overallDecision: 'pass',
|
|
117
|
-
blockers: [],
|
|
118
|
-
sampleFingerprints: [],
|
|
119
|
-
replayResults: {
|
|
120
|
-
painNegative: { total: 1, passed: 1, failed: 0, details: [] },
|
|
121
|
-
successPositive: { total: 0, passed: 0, failed: 0, details: [] },
|
|
122
|
-
principleAnchor: { total: 0, passed: 0, failed: 0, details: [] },
|
|
123
|
-
},
|
|
124
|
-
evidenceSummary: {
|
|
125
|
-
evidenceStatus: 'observed',
|
|
126
|
-
totalSamples: 1,
|
|
127
|
-
classifiedCounts: { painNegative: 1, successPositive: 0, principleAnchor: 0 },
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
fs.writeFileSync(path.join(replayDir, '2026-04-08T00-00-00-000Z.json'), JSON.stringify(report, null, 2), 'utf-8');
|
|
132
|
-
|
|
133
|
-
const engine = new ReplayEngine(workspaceDir, stateDir);
|
|
134
|
-
expect(engine.hasPassingReport('IMPL-1')).toBe(true);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('hasPassingReport returns false when no passing report exists', () => {
|
|
138
|
-
createImplementationAssetDir(stateDir, 'IMPL-1', '1.0.0');
|
|
139
|
-
const replayDir = path.join(getImplementationAssetRoot(stateDir, 'IMPL-1'), 'replays');
|
|
140
|
-
fs.mkdirSync(replayDir, { recursive: true });
|
|
141
|
-
|
|
142
|
-
const report = {
|
|
143
|
-
implementationId: 'IMPL-1',
|
|
144
|
-
generatedAt: '2026-04-08T00:00:00.000Z',
|
|
145
|
-
overallDecision: 'needs-review',
|
|
146
|
-
blockers: ['NO REPLAY EVIDENCE'],
|
|
147
|
-
sampleFingerprints: [],
|
|
148
|
-
replayResults: {
|
|
149
|
-
painNegative: { total: 0, passed: 0, failed: 0, details: [] },
|
|
150
|
-
successPositive: { total: 0, passed: 0, failed: 0, details: [] },
|
|
151
|
-
principleAnchor: { total: 0, passed: 0, failed: 0, details: [] },
|
|
152
|
-
},
|
|
153
|
-
evidenceSummary: {
|
|
154
|
-
evidenceStatus: 'empty',
|
|
155
|
-
totalSamples: 0,
|
|
156
|
-
classifiedCounts: { painNegative: 0, successPositive: 0, principleAnchor: 0 },
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
fs.writeFileSync(path.join(replayDir, '2026-04-08T00-00-00-000Z.json'), JSON.stringify(report, null, 2), 'utf-8');
|
|
161
|
-
|
|
162
|
-
const engine = new ReplayEngine(workspaceDir, stateDir);
|
|
163
|
-
expect(engine.hasPassingReport('IMPL-1')).toBe(false);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { estimateLineChanges, assessRiskLevel, getTargetFileLineCount, calculatePercentageThreshold } from '../../src/core/risk-calculator.js';
|
|
3
|
-
import * as ioUtils from '../../src/utils/io.js';
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
|
|
6
|
-
vi.mock('../../src/utils/io.js');
|
|
7
|
-
vi.mock('fs');
|
|
8
|
-
|
|
9
|
-
describe('Risk Calculator', () => {
|
|
10
|
-
it('should estimate line changes correctly for write_file', () => {
|
|
11
|
-
const lines = estimateLineChanges({
|
|
12
|
-
toolName: 'write_file',
|
|
13
|
-
params: { content: 'line1\nline2\nline3' }
|
|
14
|
-
});
|
|
15
|
-
expect(lines).toBe(3);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should estimate line changes correctly for replace', () => {
|
|
19
|
-
const lines = estimateLineChanges({
|
|
20
|
-
toolName: 'replace',
|
|
21
|
-
params: { new_string: 'a\nb\nc\nd\ne' }
|
|
22
|
-
});
|
|
23
|
-
expect(lines).toBe(5);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should estimate 50 for delete_file', () => {
|
|
27
|
-
const lines = estimateLineChanges({
|
|
28
|
-
toolName: 'delete_file',
|
|
29
|
-
params: {}
|
|
30
|
-
});
|
|
31
|
-
expect(lines).toBe(50);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should assess risk level correctly', () => {
|
|
35
|
-
// High risk path, large change
|
|
36
|
-
vi.mocked(ioUtils.isRisky).mockReturnValueOnce(true);
|
|
37
|
-
let level = assessRiskLevel('src/core.ts', { toolName: 'write', params: { content: Array(105).fill('a').join('\n') } }, ['src/']);
|
|
38
|
-
expect(level).toBe('CRITICAL');
|
|
39
|
-
|
|
40
|
-
// High risk path, small change
|
|
41
|
-
vi.mocked(ioUtils.isRisky).mockReturnValueOnce(true);
|
|
42
|
-
level = assessRiskLevel('src/core.ts', { toolName: 'write', params: { content: 'a\nb' } }, ['src/']);
|
|
43
|
-
expect(level).toBe('HIGH');
|
|
44
|
-
|
|
45
|
-
// Low risk path, large change
|
|
46
|
-
vi.mocked(ioUtils.isRisky).mockReturnValueOnce(false);
|
|
47
|
-
level = assessRiskLevel('docs/readme.md', { toolName: 'write', params: { content: Array(105).fill('a').join('\n') } }, ['src/']);
|
|
48
|
-
expect(level).toBe('HIGH');
|
|
49
|
-
|
|
50
|
-
// Low risk path, medium change
|
|
51
|
-
vi.mocked(ioUtils.isRisky).mockReturnValueOnce(false);
|
|
52
|
-
level = assessRiskLevel('docs/readme.md', { toolName: 'write', params: { content: Array(15).fill('a').join('\n') } }, ['src/']);
|
|
53
|
-
expect(level).toBe('MEDIUM');
|
|
54
|
-
|
|
55
|
-
// Low risk path, small change
|
|
56
|
-
vi.mocked(ioUtils.isRisky).mockReturnValueOnce(false);
|
|
57
|
-
level = assessRiskLevel('docs/readme.md', { toolName: 'write', params: { content: 'a\nb' } }, ['src/']);
|
|
58
|
-
expect(level).toBe('LOW');
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe('getTargetFileLineCount', () => {
|
|
63
|
-
it('should return line count when file exists and is readable', () => {
|
|
64
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
65
|
-
vi.mocked(fs.statSync).mockReturnValue({ isFile: () => true } as any);
|
|
66
|
-
vi.mocked(fs.readFileSync).mockReturnValue('line1\nline2\nline3\n');
|
|
67
|
-
|
|
68
|
-
const count = getTargetFileLineCount('/some/file.txt');
|
|
69
|
-
expect(count).toBe(4);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should return null when file does not exist', () => {
|
|
73
|
-
vi.mocked(fs.existsSync).mockReturnValue(false);
|
|
74
|
-
|
|
75
|
-
const count = getTargetFileLineCount('/nonexistent/file.txt');
|
|
76
|
-
expect(count).toBeNull();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should return null when path is not a regular file', () => {
|
|
80
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
81
|
-
vi.mocked(fs.statSync).mockReturnValue({ isFile: () => false } as any);
|
|
82
|
-
|
|
83
|
-
const count = getTargetFileLineCount('/some/directory');
|
|
84
|
-
expect(count).toBeNull();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should return null and log error when file cannot be read', () => {
|
|
88
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
89
|
-
vi.mocked(fs.statSync).mockReturnValue({ isFile: () => true } as any);
|
|
90
|
-
vi.mocked(fs.readFileSync).mockImplementation(() => {
|
|
91
|
-
const err = new Error('Permission denied');
|
|
92
|
-
(err as any).code = 'EACCES';
|
|
93
|
-
throw err;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
97
|
-
|
|
98
|
-
const count = getTargetFileLineCount('/some/file.txt');
|
|
99
|
-
expect(count).toBeNull();
|
|
100
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
101
|
-
expect.stringContaining('[PD:RISK_CALC] Failed to read file'),
|
|
102
|
-
expect.objectContaining({ code: 'EACCES' })
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
consoleSpy.mockRestore();
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('should return 1 for file with no newlines', () => {
|
|
109
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
110
|
-
vi.mocked(fs.statSync).mockReturnValue({ isFile: () => true } as any);
|
|
111
|
-
vi.mocked(fs.readFileSync).mockReturnValue('single line content');
|
|
112
|
-
|
|
113
|
-
const count = getTargetFileLineCount('/some/file.txt');
|
|
114
|
-
expect(count).toBe(1);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
describe('calculatePercentageThreshold', () => {
|
|
119
|
-
it('should calculate percentage correctly', () => {
|
|
120
|
-
// 10% of 100 lines = 10 lines
|
|
121
|
-
const limit = calculatePercentageThreshold(100, 10, 5);
|
|
122
|
-
expect(limit).toBe(10);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should enforce minimum floor', () => {
|
|
126
|
-
// 5% of 100 lines = 5 lines, but min is 20, so result is 20
|
|
127
|
-
const limit = calculatePercentageThreshold(100, 5, 20);
|
|
128
|
-
expect(limit).toBe(20);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('should round correctly', () => {
|
|
132
|
-
// 10% of 99 lines = 9.9, rounds to 10
|
|
133
|
-
const limit = calculatePercentageThreshold(99, 10, 5);
|
|
134
|
-
expect(limit).toBe(10);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should handle zero percentage', () => {
|
|
138
|
-
const limit = calculatePercentageThreshold(100, 0, 20);
|
|
139
|
-
expect(limit).toBe(20); // minLines is the floor
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should handle 100 percentage', () => {
|
|
143
|
-
const limit = calculatePercentageThreshold(100, 100, 20);
|
|
144
|
-
expect(limit).toBe(100);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('should clamp negative percentage to 0', () => {
|
|
148
|
-
const limit = calculatePercentageThreshold(100, -10, 20);
|
|
149
|
-
expect(limit).toBe(20); // minLines is the floor
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('should clamp percentage over 100 to 100', () => {
|
|
153
|
-
const limit = calculatePercentageThreshold(100, 150, 20);
|
|
154
|
-
expect(limit).toBe(100);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should respect maxLines upper bound', () => {
|
|
158
|
-
// 15% of 1000 lines = 150, but max is 100
|
|
159
|
-
const limit = calculatePercentageThreshold(1000, 15, 20, 100);
|
|
160
|
-
expect(limit).toBe(100);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
it('should use minLines when both floor and ceiling apply', () => {
|
|
164
|
-
// 1% of 100 lines = 1, but min is 20, ceiling doesn't apply
|
|
165
|
-
const limit = calculatePercentageThreshold(100, 1, 20, 50);
|
|
166
|
-
expect(limit).toBe(20);
|
|
167
|
-
});
|
|
168
|
-
});
|