principles-disciple 1.127.0 → 1.129.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 -96
- 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,199 +1,124 @@
|
|
|
1
|
-
|
|
2
1
|
import * as path from 'path';
|
|
3
2
|
import * as fs from 'fs';
|
|
4
3
|
import { atomicWriteFileSync } from '../utils/io.js';
|
|
5
|
-
import type { PainConfig } from './config.js';
|
|
6
4
|
import { SystemLogger } from './system-logger.js';
|
|
7
5
|
import { TWO_HOURS_MS } from '../config/defaults/runtime.js';
|
|
8
|
-
import {
|
|
9
|
-
applyFriction as coreApplyFriction,
|
|
10
|
-
applyDecay as coreApplyDecay,
|
|
11
|
-
applyRelief as coreApplyRelief,
|
|
12
|
-
classifyGfiStage,
|
|
13
|
-
DEFAULT_GFI_POLICY,
|
|
14
|
-
} from '@principles/core/runtime-v2';
|
|
15
|
-
import type { GfiState, GfiEvent, GfiSource } from '@principles/core/runtime-v2';
|
|
16
|
-
|
|
17
|
-
export interface TokenUsage {
|
|
18
|
-
input?: number;
|
|
19
|
-
output?: number;
|
|
20
|
-
cacheRead?: number;
|
|
21
|
-
cacheWrite?: number;
|
|
22
|
-
total?: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
6
|
+
import { applyFriction as coreApplyFriction, applyDecay as coreApplyDecay, applyRelief as coreApplyRelief, classifyGfiStage, DEFAULT_GFI_POLICY, } from '@principles/core/runtime-v2';
|
|
25
7
|
// ── GFI Core Kernel Adapter ──────────────────────────────────────────────────
|
|
26
|
-
|
|
27
8
|
/** Convert SessionState GFI fields to GfiState for core kernel */
|
|
28
|
-
function toGfiState(state
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
9
|
+
function toGfiState(state) {
|
|
10
|
+
return {
|
|
11
|
+
currentGfi: state.currentGfi ?? 0,
|
|
12
|
+
gfiBySource: (state.gfiBySource ?? {}),
|
|
13
|
+
lastErrorHash: state.lastErrorHash === '' ? undefined : state.lastErrorHash,
|
|
14
|
+
lastErrorSource: state.lastErrorSource || undefined,
|
|
15
|
+
consecutiveErrors: state.consecutiveErrors ?? 0,
|
|
16
|
+
lastGfiDecayAt: state.lastGfiDecayAt,
|
|
17
|
+
dailyGfiPeak: state.dailyGfiPeak,
|
|
18
|
+
};
|
|
38
19
|
}
|
|
39
|
-
|
|
40
20
|
/** Apply GfiState result back onto SessionState */
|
|
41
|
-
function applyGfiResult(state
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface SessionState {
|
|
52
|
-
sessionId: string;
|
|
53
|
-
sessionKey?: string; // Structured session key from OpenClaw (e.g., agent:main:cron:job-1:run:xxx)
|
|
54
|
-
trigger?: string; // Trigger source: "user" | "cron" | "heartbeat" | "memory" | "subagent"
|
|
55
|
-
workspaceDir?: string;
|
|
56
|
-
toolReadsByFile: Record<string, number>;
|
|
57
|
-
llmTurns: number;
|
|
58
|
-
blockedAttempts: number;
|
|
59
|
-
lastActivityAt: number;
|
|
60
|
-
lastControlActivityAt: number;
|
|
61
|
-
totalInputTokens: number;
|
|
62
|
-
totalOutputTokens: number;
|
|
63
|
-
cacheHits: number;
|
|
64
|
-
// Track consecutive loops of similar lengths/ratios (paralysis)
|
|
65
|
-
stuckLoops: number;
|
|
66
|
-
|
|
67
|
-
// GFI - Track A: Empirical Friction
|
|
68
|
-
currentGfi: number;
|
|
69
|
-
gfiBySource?: Record<string, number>;
|
|
70
|
-
lastErrorSource?: string;
|
|
71
|
-
lastErrorHash: string;
|
|
72
|
-
consecutiveErrors: number;
|
|
73
|
-
lastGfiDecayAt?: number; // Timestamp of last GFI decay (for time-based decay)
|
|
74
|
-
|
|
75
|
-
// Daily statistics (persisted)
|
|
76
|
-
dailyToolCalls: number;
|
|
77
|
-
dailyToolFailures: number;
|
|
78
|
-
dailyPainSignals: number;
|
|
79
|
-
dailyGfiPeak: number;
|
|
80
|
-
|
|
81
|
-
// Thinking OS checkpoint - tracks last deep thinking timestamp
|
|
82
|
-
lastThinkingTimestamp: number;
|
|
83
|
-
|
|
84
|
-
// Evolution loop feedback attribution
|
|
85
|
-
injectedProbationIds?: string[];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const sessions = new Map<string, SessionState>();
|
|
90
|
-
|
|
21
|
+
function applyGfiResult(state, result) {
|
|
22
|
+
state.currentGfi = result.currentGfi;
|
|
23
|
+
state.gfiBySource = { ...result.gfiBySource };
|
|
24
|
+
state.lastErrorHash = result.lastErrorHash ?? '';
|
|
25
|
+
state.lastErrorSource = result.lastErrorSource ?? '';
|
|
26
|
+
state.consecutiveErrors = result.consecutiveErrors;
|
|
27
|
+
state.lastGfiDecayAt = result.lastGfiDecayAt;
|
|
28
|
+
state.dailyGfiPeak = result.dailyGfiPeak ?? state.dailyGfiPeak;
|
|
29
|
+
}
|
|
30
|
+
const sessions = new Map();
|
|
91
31
|
/** Directory for persisting session state */
|
|
92
|
-
let persistDir
|
|
93
|
-
|
|
32
|
+
let persistDir = null;
|
|
94
33
|
/** Debounce timers for persistence, one per session */
|
|
95
|
-
const persistTimers = new Map
|
|
96
|
-
|
|
97
|
-
function logSessionTrackerWarning(message: string, error?: unknown): void {
|
|
34
|
+
const persistTimers = new Map();
|
|
35
|
+
function logSessionTrackerWarning(message, error) {
|
|
98
36
|
const detail = error instanceof Error ? error.message : error ? String(error) : '';
|
|
99
37
|
const suffix = detail ? `: ${detail}` : '';
|
|
100
|
-
|
|
101
38
|
console.warn(`[PD:SessionTracker] ${message}${suffix}`);
|
|
102
39
|
}
|
|
103
|
-
|
|
104
|
-
function touchActivity(state: SessionState, kind: 'general' | 'control' = 'general'): void {
|
|
40
|
+
function touchActivity(state, kind = 'general') {
|
|
105
41
|
const now = Date.now();
|
|
106
42
|
state.lastActivityAt = now;
|
|
107
43
|
if (kind === 'control') {
|
|
108
44
|
state.lastControlActivityAt = now;
|
|
109
45
|
}
|
|
110
46
|
}
|
|
111
|
-
|
|
112
47
|
/**
|
|
113
48
|
* Initialize persistence for session state.
|
|
114
49
|
* Call this once during plugin startup.
|
|
115
50
|
*/
|
|
116
|
-
export function initPersistence(stateDir
|
|
51
|
+
export function initPersistence(stateDir) {
|
|
117
52
|
persistDir = path.join(stateDir, 'sessions');
|
|
118
53
|
if (!fs.existsSync(persistDir)) {
|
|
119
54
|
fs.mkdirSync(persistDir, { recursive: true });
|
|
120
55
|
}
|
|
121
|
-
|
|
122
56
|
// Load all existing sessions
|
|
123
|
-
|
|
124
|
-
|
|
125
57
|
loadAllSessions();
|
|
126
58
|
}
|
|
127
|
-
|
|
128
59
|
/**
|
|
129
60
|
* Get the file path for a session's persisted state.
|
|
130
61
|
*/
|
|
131
|
-
function getSessionPath(sessionId
|
|
132
|
-
if (!persistDir)
|
|
62
|
+
function getSessionPath(sessionId) {
|
|
63
|
+
if (!persistDir)
|
|
64
|
+
return '';
|
|
133
65
|
// Sanitize sessionId for filesystem
|
|
134
66
|
const safeId = sessionId.replace(/[/\\:]/g, '_');
|
|
135
67
|
return path.join(persistDir, `${safeId}.json`);
|
|
136
68
|
}
|
|
137
|
-
|
|
138
69
|
/**
|
|
139
70
|
* Load all persisted sessions from disk.
|
|
140
71
|
*/
|
|
141
|
-
function loadAllSessions()
|
|
142
|
-
if (!persistDir || !fs.existsSync(persistDir))
|
|
143
|
-
|
|
72
|
+
function loadAllSessions() {
|
|
73
|
+
if (!persistDir || !fs.existsSync(persistDir))
|
|
74
|
+
return;
|
|
144
75
|
try {
|
|
145
76
|
const files = fs.readdirSync(persistDir).filter(f => f.endsWith('.json'));
|
|
146
77
|
const now = Date.now();
|
|
147
78
|
const twoHoursAgo = now - TWO_HOURS_MS;
|
|
148
|
-
|
|
149
79
|
for (const file of files) {
|
|
150
80
|
try {
|
|
151
81
|
const content = fs.readFileSync(path.join(persistDir, file), 'utf-8');
|
|
152
|
-
const state = JSON.parse(content)
|
|
153
|
-
|
|
82
|
+
const state = JSON.parse(content);
|
|
154
83
|
// Skip abandoned sessions
|
|
155
84
|
if (state.lastActivityAt < twoHoursAgo) {
|
|
156
85
|
continue;
|
|
157
86
|
}
|
|
158
|
-
|
|
159
87
|
sessions.set(state.sessionId, state);
|
|
160
|
-
}
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
161
90
|
logSessionTrackerWarning(`Failed to load session snapshot ${file}`, error);
|
|
162
91
|
}
|
|
163
92
|
}
|
|
164
|
-
}
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
165
95
|
logSessionTrackerWarning('Failed to load persisted sessions', err);
|
|
166
96
|
}
|
|
167
97
|
}
|
|
168
|
-
|
|
169
98
|
/**
|
|
170
99
|
* Persist a single session to disk.
|
|
171
100
|
*/
|
|
172
|
-
function persistSession(state
|
|
173
|
-
if (!persistDir)
|
|
174
|
-
|
|
101
|
+
function persistSession(state) {
|
|
102
|
+
if (!persistDir)
|
|
103
|
+
return;
|
|
175
104
|
const sessionPath = getSessionPath(state.sessionId);
|
|
176
|
-
if (!sessionPath)
|
|
177
|
-
|
|
105
|
+
if (!sessionPath)
|
|
106
|
+
return;
|
|
178
107
|
try {
|
|
179
108
|
atomicWriteFileSync(sessionPath, JSON.stringify(state, null, 2));
|
|
180
109
|
// Log successful persistence with GFI snapshot for debugging
|
|
181
110
|
if (state.currentGfi > 0) {
|
|
182
|
-
SystemLogger.log(
|
|
183
|
-
state.workspaceDir,
|
|
184
|
-
'GFI_PERSIST',
|
|
185
|
-
`Session ${state.sessionId.slice(0, 8)} persisted: GFI=${state.currentGfi.toFixed(1)}, sources=${JSON.stringify(state.gfiBySource)}`
|
|
186
|
-
);
|
|
111
|
+
SystemLogger.log(state.workspaceDir, 'GFI_PERSIST', `Session ${state.sessionId.slice(0, 8)} persisted: GFI=${state.currentGfi.toFixed(1)}, sources=${JSON.stringify(state.gfiBySource)}`);
|
|
187
112
|
}
|
|
188
|
-
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
189
115
|
logSessionTrackerWarning(`Failed to persist session ${state.sessionId}`, error);
|
|
190
116
|
}
|
|
191
117
|
}
|
|
192
|
-
|
|
193
118
|
/**
|
|
194
119
|
* Schedule persistence with debounce.
|
|
195
120
|
*/
|
|
196
|
-
function schedulePersistence(state
|
|
121
|
+
function schedulePersistence(state) {
|
|
197
122
|
const existing = persistTimers.get(state.sessionId);
|
|
198
123
|
if (existing) {
|
|
199
124
|
clearTimeout(existing);
|
|
@@ -201,15 +126,14 @@ function schedulePersistence(state: SessionState): void {
|
|
|
201
126
|
const timer = setTimeout(() => {
|
|
202
127
|
persistSession(state);
|
|
203
128
|
persistTimers.delete(state.sessionId);
|
|
204
|
-
}, 1000);
|
|
129
|
+
}, 1000); // 1 second debounce
|
|
205
130
|
timer.unref(); // Don't keep process alive for persistence
|
|
206
131
|
persistTimers.set(state.sessionId, timer);
|
|
207
132
|
}
|
|
208
|
-
|
|
209
133
|
/**
|
|
210
134
|
* Force persist all sessions immediately.
|
|
211
135
|
*/
|
|
212
|
-
export function flushAllSessions()
|
|
136
|
+
export function flushAllSessions() {
|
|
213
137
|
for (const timer of persistTimers.values()) {
|
|
214
138
|
clearTimeout(timer);
|
|
215
139
|
}
|
|
@@ -218,10 +142,7 @@ export function flushAllSessions(): void {
|
|
|
218
142
|
persistSession(state);
|
|
219
143
|
}
|
|
220
144
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
function getOrCreateSession(sessionId: string, workspaceDir?: string, sessionKey?: string, trigger?: string): SessionState {
|
|
145
|
+
function getOrCreateSession(sessionId, workspaceDir, sessionKey, trigger) {
|
|
225
146
|
let state = sessions.get(sessionId);
|
|
226
147
|
if (!state) {
|
|
227
148
|
state = {
|
|
@@ -253,7 +174,6 @@ function getOrCreateSession(sessionId: string, workspaceDir?: string, sessionKey
|
|
|
253
174
|
};
|
|
254
175
|
sessions.set(sessionId, state);
|
|
255
176
|
}
|
|
256
|
-
|
|
257
177
|
if (workspaceDir && !state.workspaceDir) {
|
|
258
178
|
state.workspaceDir = workspaceDir;
|
|
259
179
|
}
|
|
@@ -266,32 +186,25 @@ function getOrCreateSession(sessionId: string, workspaceDir?: string, sessionKey
|
|
|
266
186
|
}
|
|
267
187
|
return state;
|
|
268
188
|
}
|
|
269
|
-
|
|
270
|
-
export function trackToolRead(sessionId: string, filePath: string, workspaceDir?: string): SessionState {
|
|
189
|
+
export function trackToolRead(sessionId, filePath, workspaceDir) {
|
|
271
190
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
272
191
|
const normalizedPath = path.posix.normalize(filePath.replace(/\\/g, '/'));
|
|
273
192
|
state.toolReadsByFile[normalizedPath] = (state.toolReadsByFile[normalizedPath] || 0) + 1;
|
|
274
193
|
touchActivity(state);
|
|
275
194
|
return state;
|
|
276
195
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined, config?: PainConfig, workspaceDir?: string, sessionKey?: string, trigger?: string): SessionState {
|
|
196
|
+
export function trackLlmOutput(sessionId, usage, config, workspaceDir, sessionKey, trigger) {
|
|
281
197
|
const state = getOrCreateSession(sessionId, workspaceDir, sessionKey, trigger);
|
|
282
198
|
state.llmTurns += 1;
|
|
283
199
|
touchActivity(state);
|
|
284
|
-
|
|
285
200
|
if (usage) {
|
|
286
201
|
state.totalInputTokens += usage.input || 0;
|
|
287
202
|
state.totalOutputTokens += usage.output || 0;
|
|
288
203
|
state.cacheHits += usage.cacheRead || 0;
|
|
289
|
-
|
|
290
204
|
// Use thresholds from config or defaults
|
|
291
205
|
const minTurns = 5; // Increased from 3 to 5 to prevent false positives on short tasks
|
|
292
206
|
const outputThreshold = 30; // Decreased from 50. Only penalize truly stunted outputs.
|
|
293
207
|
const inputThreshold = config ? config.get('thresholds.cognitive_paralysis_input') : 8000; // Increased base to 8k
|
|
294
|
-
|
|
295
208
|
// Very rough heuristic for empty/paralysis loops: high input context, tiny output, multiple turns
|
|
296
209
|
if (state.llmTurns > minTurns) {
|
|
297
210
|
const isTinyOutput = (usage.output || 0) < outputThreshold;
|
|
@@ -299,7 +212,8 @@ export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined,
|
|
|
299
212
|
if (isTinyOutput && isLargeInput) {
|
|
300
213
|
state.stuckLoops += 1;
|
|
301
214
|
SystemLogger.log(state.workspaceDir, 'EFFICIENCY_ALARM', `Stuck loop detected (Turn ${state.llmTurns}). Input: ${usage.input}, Output: ${usage.output}. Consecutive: ${state.stuckLoops}`);
|
|
302
|
-
}
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
303
217
|
// Reset if we broke out of the tiny output loop
|
|
304
218
|
if (state.stuckLoops > 0) {
|
|
305
219
|
SystemLogger.log(state.workspaceDir, 'EFFICIENCY_OK', `Broke out of stuck loop after ${state.stuckLoops} turns.`);
|
|
@@ -308,107 +222,76 @@ export function trackLlmOutput(sessionId: string, usage: TokenUsage | undefined,
|
|
|
308
222
|
}
|
|
309
223
|
}
|
|
310
224
|
}
|
|
311
|
-
|
|
312
225
|
return state;
|
|
313
226
|
}
|
|
314
|
-
|
|
315
227
|
/**
|
|
316
228
|
* Tracks physical friction based on tool execution failures.
|
|
317
229
|
* Delegates to core GFI kernel for scoring.
|
|
318
230
|
*/
|
|
319
|
-
export function trackFriction(
|
|
320
|
-
sessionId: string,
|
|
321
|
-
deltaF: number,
|
|
322
|
-
hash: string,
|
|
323
|
-
workspaceDir?: string,
|
|
324
|
-
options?: { source?: string }
|
|
325
|
-
): SessionState {
|
|
231
|
+
export function trackFriction(sessionId, deltaF, hash, workspaceDir, options) {
|
|
326
232
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
327
|
-
|
|
328
|
-
const
|
|
329
|
-
const event: GfiEvent = {
|
|
233
|
+
const source = options?.source ?? 'unknown';
|
|
234
|
+
const event = {
|
|
330
235
|
source,
|
|
331
236
|
baseScore: deltaF,
|
|
332
237
|
hash: hash || undefined,
|
|
333
238
|
};
|
|
334
|
-
|
|
335
239
|
const coreState = toGfiState(state);
|
|
336
240
|
const nextCore = coreApplyFriction(coreState, event, DEFAULT_GFI_POLICY);
|
|
337
|
-
|
|
338
241
|
// Preserve composite source key for unattributed sources
|
|
339
242
|
if (!options?.source && hash) {
|
|
340
243
|
const val = nextCore.gfiBySource['unknown'];
|
|
341
244
|
if (val !== undefined) {
|
|
342
|
-
const s = nextCore.gfiBySource
|
|
245
|
+
const s = nextCore.gfiBySource;
|
|
343
246
|
delete s['unknown'];
|
|
344
247
|
const key = `unattributed:${hash}`;
|
|
345
248
|
s[key] = (s[key] ?? 0) + val;
|
|
346
249
|
}
|
|
347
250
|
}
|
|
348
|
-
|
|
349
251
|
applyGfiResult(state, nextCore);
|
|
350
|
-
|
|
351
252
|
touchActivity(state, 'control');
|
|
352
|
-
|
|
353
253
|
// Update daily stats
|
|
354
254
|
state.dailyToolFailures++;
|
|
355
255
|
state.dailyGfiPeak = Math.max(state.dailyGfiPeak, state.currentGfi);
|
|
356
|
-
|
|
357
256
|
// Schedule persistence
|
|
358
257
|
state.lastGfiDecayAt = Date.now();
|
|
359
258
|
schedulePersistence(state);
|
|
360
|
-
|
|
361
259
|
return state;
|
|
362
260
|
}
|
|
363
|
-
|
|
364
261
|
/**
|
|
365
262
|
* Resets the friction index upon successful action.
|
|
366
263
|
* Delegates to core GFI kernel for relief computation.
|
|
367
264
|
*/
|
|
368
|
-
export function resetFriction(
|
|
369
|
-
sessionId: string,
|
|
370
|
-
workspaceDir?: string,
|
|
371
|
-
options?: { source?: string; amount?: number }
|
|
372
|
-
): SessionState {
|
|
265
|
+
export function resetFriction(sessionId, workspaceDir, options) {
|
|
373
266
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
374
|
-
|
|
375
267
|
if (options?.source) {
|
|
376
268
|
const coreState = toGfiState(state);
|
|
377
269
|
const nextCore = coreApplyRelief(coreState, { source: options.source, amount: options.amount ?? 0 }, Date.now(), DEFAULT_GFI_POLICY);
|
|
378
270
|
applyGfiResult(state, nextCore);
|
|
379
|
-
|
|
380
271
|
if (state.currentGfi > 0) {
|
|
381
|
-
SystemLogger.log(
|
|
382
|
-
state.workspaceDir,
|
|
383
|
-
'GFI_SLICE_RESET',
|
|
384
|
-
`Friction slice reset for ${options.source}: remaining GFI=${state.currentGfi.toFixed(1)}`
|
|
385
|
-
);
|
|
272
|
+
SystemLogger.log(state.workspaceDir, 'GFI_SLICE_RESET', `Friction slice reset for ${options.source}: remaining GFI=${state.currentGfi.toFixed(1)}`);
|
|
386
273
|
}
|
|
387
274
|
touchActivity(state, 'control');
|
|
388
275
|
schedulePersistence(state);
|
|
389
276
|
return state;
|
|
390
277
|
}
|
|
391
|
-
|
|
392
278
|
// Full reset via core kernel
|
|
393
279
|
const previousGfi = state.currentGfi;
|
|
394
280
|
const coreState = toGfiState(state);
|
|
395
281
|
const nextCore = coreApplyRelief(coreState, { source: 'all', amount: 100 }, Date.now(), DEFAULT_GFI_POLICY);
|
|
396
282
|
applyGfiResult(state, nextCore);
|
|
397
|
-
|
|
398
283
|
if (previousGfi > 0) {
|
|
399
284
|
SystemLogger.log(state.workspaceDir, 'GFI_RESET', `Friction reset to 0 (Was: ${previousGfi.toFixed(1)}). Action successful.`);
|
|
400
285
|
}
|
|
401
286
|
touchActivity(state, 'control');
|
|
402
|
-
|
|
403
287
|
schedulePersistence(state);
|
|
404
288
|
return state;
|
|
405
289
|
}
|
|
406
|
-
|
|
407
290
|
/**
|
|
408
291
|
* Records that deep thinking (Thinking OS) was performed in this session.
|
|
409
292
|
* Used by the Thinking OS checkpoint to allow high-risk operations.
|
|
410
293
|
*/
|
|
411
|
-
export function recordThinkingCheckpoint(sessionId
|
|
294
|
+
export function recordThinkingCheckpoint(sessionId, workspaceDir) {
|
|
412
295
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
413
296
|
state.lastThinkingTimestamp = Date.now();
|
|
414
297
|
touchActivity(state, 'control');
|
|
@@ -416,61 +299,53 @@ export function recordThinkingCheckpoint(sessionId: string, workspaceDir?: strin
|
|
|
416
299
|
schedulePersistence(state);
|
|
417
300
|
return state;
|
|
418
301
|
}
|
|
419
|
-
|
|
420
302
|
/**
|
|
421
303
|
* Checks if deep thinking was performed recently (within the given window).
|
|
422
304
|
* @param sessionId - The session to check
|
|
423
305
|
* @param windowMs - How recent the thinking must be (default: 5 minutes)
|
|
424
306
|
* @returns true if thinking was recorded within the window
|
|
425
307
|
*/
|
|
426
|
-
export function hasRecentThinking(sessionId
|
|
308
|
+
export function hasRecentThinking(sessionId, windowMs = 5 * 60 * 1000) {
|
|
427
309
|
const state = sessions.get(sessionId);
|
|
428
|
-
if (!state || !state.lastThinkingTimestamp)
|
|
310
|
+
if (!state || !state.lastThinkingTimestamp)
|
|
311
|
+
return false;
|
|
429
312
|
return (Date.now() - state.lastThinkingTimestamp) < windowMs;
|
|
430
313
|
}
|
|
431
|
-
|
|
432
|
-
export function trackBlock(sessionId: string): SessionState {
|
|
314
|
+
export function trackBlock(sessionId) {
|
|
433
315
|
const state = getOrCreateSession(sessionId);
|
|
434
316
|
state.blockedAttempts += 1;
|
|
435
317
|
touchActivity(state, 'control');
|
|
436
318
|
schedulePersistence(state);
|
|
437
319
|
return state;
|
|
438
320
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
export function setInjectedProbationIds(sessionId: string, ids: string[], workspaceDir?: string): SessionState {
|
|
321
|
+
export function setInjectedProbationIds(sessionId, ids, workspaceDir) {
|
|
442
322
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
443
323
|
state.injectedProbationIds = [...ids];
|
|
444
324
|
touchActivity(state, 'control');
|
|
445
325
|
schedulePersistence(state);
|
|
446
326
|
return state;
|
|
447
327
|
}
|
|
448
|
-
|
|
449
|
-
export function getInjectedProbationIds(sessionId: string, workspaceDir?: string): string[] {
|
|
328
|
+
export function getInjectedProbationIds(sessionId, workspaceDir) {
|
|
450
329
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
451
330
|
return [...(state.injectedProbationIds || [])];
|
|
452
331
|
}
|
|
453
|
-
|
|
454
|
-
export function clearInjectedProbationIds(sessionId: string, workspaceDir?: string): SessionState {
|
|
332
|
+
export function clearInjectedProbationIds(sessionId, workspaceDir) {
|
|
455
333
|
return setInjectedProbationIds(sessionId, [], workspaceDir);
|
|
456
334
|
}
|
|
457
|
-
|
|
458
|
-
export function getSession(sessionId: string): SessionState | undefined {
|
|
335
|
+
export function getSession(sessionId) {
|
|
459
336
|
return sessions.get(sessionId);
|
|
460
337
|
}
|
|
461
|
-
|
|
462
|
-
export function listSessions(workspaceDir?: string): SessionState[] {
|
|
338
|
+
export function listSessions(workspaceDir) {
|
|
463
339
|
return [...sessions.values()]
|
|
464
340
|
.filter((state) => !workspaceDir || !state.workspaceDir || state.workspaceDir === workspaceDir)
|
|
465
341
|
.map((state) => ({
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
342
|
+
...state,
|
|
343
|
+
toolReadsByFile: { ...state.toolReadsByFile },
|
|
344
|
+
gfiBySource: state.gfiBySource ? { ...state.gfiBySource } : undefined,
|
|
345
|
+
injectedProbationIds: state.injectedProbationIds ? [...state.injectedProbationIds] : undefined,
|
|
346
|
+
}));
|
|
471
347
|
}
|
|
472
|
-
|
|
473
|
-
export function clearSession(sessionId: string): void {
|
|
348
|
+
export function clearSession(sessionId) {
|
|
474
349
|
const timer = persistTimers.get(sessionId);
|
|
475
350
|
if (timer) {
|
|
476
351
|
clearTimeout(timer);
|
|
@@ -478,7 +353,6 @@ export function clearSession(sessionId: string): void {
|
|
|
478
353
|
}
|
|
479
354
|
sessions.delete(sessionId);
|
|
480
355
|
}
|
|
481
|
-
|
|
482
356
|
/**
|
|
483
357
|
* Seed a session directly into SessionTracker.sessions for testing.
|
|
484
358
|
* This bypasses the normal tool-call flow to set up test data for
|
|
@@ -488,14 +362,13 @@ export function clearSession(sessionId: string): void {
|
|
|
488
362
|
* @param workspaceDir - Workspace directory (optional, for filtering)
|
|
489
363
|
* @param lastActivityAt - Unix timestamp in ms (default: now)
|
|
490
364
|
*/
|
|
491
|
-
export function seedSessionForTest(sessionId
|
|
365
|
+
export function seedSessionForTest(sessionId, workspaceDir, lastActivityAt) {
|
|
492
366
|
const state = getOrCreateSession(sessionId, workspaceDir);
|
|
493
367
|
state.lastActivityAt = lastActivityAt ?? Date.now();
|
|
494
368
|
state.lastControlActivityAt = state.lastActivityAt;
|
|
495
369
|
}
|
|
496
|
-
|
|
497
370
|
// Memory cleanup for abandoned sessions (older than 2 hours)
|
|
498
|
-
export function garbageCollectSessions()
|
|
371
|
+
export function garbageCollectSessions() {
|
|
499
372
|
const twoHoursAgo = Date.now() - 2 * 60 * 60 * 1000;
|
|
500
373
|
for (const [id, state] of sessions.entries()) {
|
|
501
374
|
if (state.lastActivityAt < twoHoursAgo) {
|
|
@@ -505,14 +378,14 @@ export function garbageCollectSessions(): void {
|
|
|
505
378
|
persistTimers.delete(id);
|
|
506
379
|
}
|
|
507
380
|
sessions.delete(id);
|
|
508
|
-
|
|
509
381
|
// Also delete persisted file
|
|
510
382
|
if (persistDir) {
|
|
511
383
|
const sessionPath = getSessionPath(id);
|
|
512
384
|
if (sessionPath && fs.existsSync(sessionPath)) {
|
|
513
385
|
try {
|
|
514
386
|
fs.unlinkSync(sessionPath);
|
|
515
|
-
}
|
|
387
|
+
}
|
|
388
|
+
catch (error) {
|
|
516
389
|
logSessionTrackerWarning(`Failed to delete session snapshot for ${id}`, error);
|
|
517
390
|
}
|
|
518
391
|
}
|
|
@@ -520,19 +393,13 @@ export function garbageCollectSessions(): void {
|
|
|
520
393
|
}
|
|
521
394
|
}
|
|
522
395
|
}
|
|
523
|
-
|
|
524
396
|
/**
|
|
525
397
|
* Get daily statistics summary for a session.
|
|
526
398
|
*/
|
|
527
|
-
export function getDailySummary(sessionId
|
|
528
|
-
toolCalls: number;
|
|
529
|
-
toolFailures: number;
|
|
530
|
-
painSignals: number;
|
|
531
|
-
gfiPeak: number;
|
|
532
|
-
} | null {
|
|
399
|
+
export function getDailySummary(sessionId) {
|
|
533
400
|
const state = sessions.get(sessionId);
|
|
534
|
-
if (!state)
|
|
535
|
-
|
|
401
|
+
if (!state)
|
|
402
|
+
return null;
|
|
536
403
|
return {
|
|
537
404
|
toolCalls: state.dailyToolCalls,
|
|
538
405
|
toolFailures: state.dailyToolFailures,
|
|
@@ -540,11 +407,10 @@ export function getDailySummary(sessionId: string): {
|
|
|
540
407
|
gfiPeak: state.dailyGfiPeak,
|
|
541
408
|
};
|
|
542
409
|
}
|
|
543
|
-
|
|
544
410
|
/**
|
|
545
411
|
* Reset daily statistics (call at midnight or on new day).
|
|
546
412
|
*/
|
|
547
|
-
export function resetDailyStats(sessionId
|
|
413
|
+
export function resetDailyStats(sessionId) {
|
|
548
414
|
const state = sessions.get(sessionId);
|
|
549
415
|
if (state) {
|
|
550
416
|
state.dailyToolCalls = 0;
|
|
@@ -554,7 +420,6 @@ export function resetDailyStats(sessionId: string): void {
|
|
|
554
420
|
schedulePersistence(state);
|
|
555
421
|
}
|
|
556
422
|
}
|
|
557
|
-
|
|
558
423
|
/**
|
|
559
424
|
* Apply time-based decay to GFI using stage-aware linear decay.
|
|
560
425
|
* Delegates to core GFI kernel.
|
|
@@ -563,43 +428,35 @@ export function resetDailyStats(sessionId: string): void {
|
|
|
563
428
|
* @param elapsedMinutes - Minutes since last decay
|
|
564
429
|
* @returns Updated session state, or undefined if session not found or GFI is 0
|
|
565
430
|
*/
|
|
566
|
-
export function decayGfi(sessionId
|
|
431
|
+
export function decayGfi(sessionId, elapsedMinutes) {
|
|
567
432
|
const state = sessions.get(sessionId);
|
|
568
|
-
if (!state || state.currentGfi <= 0 || elapsedMinutes <= 0)
|
|
569
|
-
|
|
433
|
+
if (!state || state.currentGfi <= 0 || elapsedMinutes <= 0)
|
|
434
|
+
return undefined;
|
|
570
435
|
const coreState = toGfiState(state);
|
|
571
436
|
const stage = classifyGfiStage(state.currentGfi, DEFAULT_GFI_POLICY);
|
|
572
437
|
const nextCore = coreApplyDecay(coreState, elapsedMinutes, DEFAULT_GFI_POLICY, stage, Date.now());
|
|
573
438
|
const previousGfi = state.currentGfi;
|
|
574
439
|
applyGfiResult(state, nextCore);
|
|
575
|
-
|
|
576
440
|
// Log if significant decay
|
|
577
441
|
const decayedAmount = previousGfi - state.currentGfi;
|
|
578
442
|
if (decayedAmount >= 1) {
|
|
579
|
-
|
|
580
|
-
state.workspaceDir,
|
|
581
|
-
'GFI_DECAY',
|
|
582
|
-
`GFI decayed by ${decayedAmount.toFixed(1)} (${elapsedMinutes}min). ${previousGfi.toFixed(1)} → ${state.currentGfi.toFixed(1)}`
|
|
583
|
-
);
|
|
443
|
+
SystemLogger.log(state.workspaceDir, 'GFI_DECAY', `GFI decayed by ${decayedAmount.toFixed(1)} (${elapsedMinutes}min). ${previousGfi.toFixed(1)} → ${state.currentGfi.toFixed(1)}`);
|
|
584
444
|
}
|
|
585
|
-
|
|
586
445
|
schedulePersistence(state);
|
|
587
446
|
return state;
|
|
588
447
|
}
|
|
589
|
-
|
|
590
448
|
/**
|
|
591
449
|
* Check if GFI decay should be applied and return elapsed minutes since last decay.
|
|
592
450
|
* @param sessionId - The session to check
|
|
593
451
|
* @returns Elapsed minutes since last decay, or 0 if no decay needed
|
|
594
452
|
*/
|
|
595
|
-
export function getGfiDecayElapsed(sessionId
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
return Math.floor(elapsedMs / 60000);
|
|
453
|
+
export function getGfiDecayElapsed(sessionId) {
|
|
454
|
+
const state = sessions.get(sessionId);
|
|
455
|
+
if (!state || state.currentGfi <= 0)
|
|
456
|
+
return 0;
|
|
457
|
+
const now = Date.now();
|
|
458
|
+
const lastDecay = state.lastGfiDecayAt || state.lastControlActivityAt || state.lastActivityAt || now;
|
|
459
|
+
const elapsedMs = now - lastDecay;
|
|
460
|
+
// Return elapsed minutes (floor to whole minutes)
|
|
461
|
+
return Math.floor(elapsedMs / 60000);
|
|
605
462
|
}
|