principles-disciple 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ADVANCED_CONFIG_ZH.md +97 -0
- package/AGENT_INSTALL.md +173 -0
- package/AGENT_INSTALL_EN.md +173 -0
- package/INSTALL.md +256 -0
- package/SKILL.md +63 -0
- package/docs/COMMAND_REFERENCE.md +76 -0
- package/docs/COMMAND_REFERENCE_EN.md +79 -0
- package/esbuild.config.js +75 -0
- package/openclaw.plugin.json +6 -1
- package/package.json +13 -15
- package/scripts/build-web.mjs +46 -0
- package/scripts/install-dependencies.cjs +47 -0
- package/scripts/sync-plugin.mjs +802 -0
- package/scripts/verify-build.mjs +109 -0
- package/src/agents/nocturnal-dreamer.md +152 -0
- package/src/agents/nocturnal-philosopher.md +138 -0
- package/src/agents/nocturnal-reflector.md +126 -0
- package/src/agents/nocturnal-scribe.md +164 -0
- package/src/commands/capabilities.ts +85 -0
- package/{dist/commands/context.js → src/commands/context.ts} +78 -38
- package/src/commands/evolution-status.ts +146 -0
- package/src/commands/export.ts +111 -0
- package/src/commands/focus.ts +533 -0
- package/src/commands/nocturnal-review.ts +311 -0
- package/src/commands/nocturnal-rollout.ts +763 -0
- package/src/commands/nocturnal-train.ts +1002 -0
- package/{dist/commands/pain.js → src/commands/pain.ts} +68 -49
- package/src/commands/principle-rollback.ts +27 -0
- package/{dist/commands/rollback.js → src/commands/rollback.ts} +44 -12
- package/src/commands/samples.ts +60 -0
- package/src/commands/strategy.ts +38 -0
- package/{dist/commands/thinking-os.js → src/commands/thinking-os.ts} +59 -36
- package/src/commands/workflow-debug.ts +128 -0
- package/{dist/config/defaults/runtime.js → src/config/defaults/runtime.ts} +12 -5
- package/src/config/errors.ts +163 -0
- package/{dist/config/index.d.ts → src/config/index.ts} +2 -1
- package/src/constants/diagnostician.ts +66 -0
- package/src/constants/tools.ts +62 -0
- package/src/core/adaptive-thresholds.ts +476 -0
- package/{dist/core/config-service.js → src/core/config-service.ts} +7 -4
- package/{dist/core/config.js → src/core/config.ts} +158 -46
- package/src/core/control-ui-db.ts +435 -0
- package/{dist/core/detection-funnel.js → src/core/detection-funnel.ts} +36 -21
- package/{dist/core/detection-service.js → src/core/detection-service.ts} +7 -4
- package/{dist/core/dictionary-service.js → src/core/dictionary-service.ts} +7 -4
- package/{dist/core/dictionary.js → src/core/dictionary.ts} +57 -34
- package/src/core/empathy-keyword-matcher.ts +327 -0
- package/src/core/empathy-types.ts +218 -0
- package/src/core/event-log.ts +544 -0
- package/src/core/evolution-engine.ts +612 -0
- package/src/core/evolution-logger.ts +353 -0
- package/src/core/evolution-migration.ts +77 -0
- package/src/core/evolution-reducer.ts +731 -0
- package/src/core/evolution-types.ts +456 -0
- package/src/core/external-training-contract.ts +527 -0
- package/src/core/focus-history.ts +1458 -0
- package/src/core/hygiene/tracker.ts +117 -0
- package/{dist/core/init.js → src/core/init.ts} +39 -26
- package/src/core/local-worker-routing.ts +617 -0
- package/{dist/core/migration.js → src/core/migration.ts} +18 -11
- package/src/core/model-deployment-registry.ts +722 -0
- package/src/core/model-training-registry.ts +813 -0
- package/src/core/nocturnal-arbiter.ts +706 -0
- package/src/core/nocturnal-candidate-scoring.ts +392 -0
- package/src/core/nocturnal-compliance.ts +1075 -0
- package/src/core/nocturnal-dataset.ts +668 -0
- package/src/core/nocturnal-executability.ts +428 -0
- package/src/core/nocturnal-export.ts +390 -0
- package/{dist/core/nocturnal-paths.js → src/core/nocturnal-paths.ts} +49 -23
- package/src/core/nocturnal-trajectory-extractor.ts +484 -0
- package/src/core/nocturnal-trinity.ts +1384 -0
- package/src/core/pain.ts +122 -0
- package/{dist/core/path-resolver.js → src/core/path-resolver.ts} +157 -36
- package/{dist/core/paths.js → src/core/paths.ts} +13 -4
- package/src/core/principle-training-state.ts +450 -0
- package/src/core/profile.ts +226 -0
- package/src/core/promotion-gate.ts +822 -0
- package/{dist/core/risk-calculator.js → src/core/risk-calculator.ts} +42 -16
- package/{dist/core/session-tracker.js → src/core/session-tracker.ts} +185 -63
- package/src/core/shadow-observation-registry.ts +534 -0
- package/{dist/core/system-logger.js → src/core/system-logger.ts} +9 -5
- package/src/core/thinking-models.ts +217 -0
- package/src/core/training-program.ts +630 -0
- package/src/core/trajectory-types.ts +243 -0
- package/src/core/trajectory.ts +1673 -0
- package/{dist/core/workspace-context.js → src/core/workspace-context.ts} +57 -32
- package/src/hooks/bash-risk.ts +171 -0
- package/src/hooks/edit-verification.ts +295 -0
- package/src/hooks/gate-block-helper.ts +160 -0
- package/src/hooks/gate.ts +210 -0
- package/src/hooks/gfi-gate.ts +177 -0
- package/src/hooks/lifecycle.ts +326 -0
- package/{dist/hooks/llm.js → src/hooks/llm.ts} +166 -139
- package/src/hooks/message-sanitize.ts +45 -0
- package/src/hooks/pain.ts +384 -0
- package/src/hooks/progressive-trust-gate.ts +174 -0
- package/src/hooks/prompt.ts +920 -0
- package/src/hooks/subagent.ts +207 -0
- package/src/hooks/thinking-checkpoint.ts +73 -0
- package/src/hooks/trajectory-collector.ts +290 -0
- package/src/http/principles-console-route.ts +716 -0
- package/src/i18n/commands.ts +117 -0
- package/src/index.ts +694 -0
- package/src/service/central-database.ts +831 -0
- package/src/service/control-ui-query-service.ts +888 -0
- package/src/service/evolution-query-service.ts +405 -0
- package/src/service/evolution-worker.ts +1646 -0
- package/src/service/health-query-service.ts +836 -0
- package/{dist/service/nocturnal-runtime.js → src/service/nocturnal-runtime.ts} +263 -36
- package/src/service/nocturnal-service.ts +1015 -0
- package/src/service/nocturnal-target-selector.ts +532 -0
- package/src/service/phase3-input-filter.ts +237 -0
- package/src/service/runtime-summary-service.ts +757 -0
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +513 -0
- package/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +603 -0
- package/src/service/subagent-workflow/index.ts +51 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +856 -0
- package/src/service/subagent-workflow/runtime-direct-driver.ts +166 -0
- package/src/service/subagent-workflow/types.ts +378 -0
- package/src/service/subagent-workflow/workflow-store.ts +328 -0
- package/src/service/trajectory-service.ts +15 -0
- package/{dist/tools/critique-prompt.js → src/tools/critique-prompt.ts} +25 -8
- package/src/tools/deep-reflect.ts +349 -0
- package/{dist/tools/model-index.js → src/tools/model-index.ts} +33 -17
- package/src/types/event-types.ts +453 -0
- package/src/types/hygiene-types.ts +31 -0
- package/src/types/principle-tree-schema.ts +244 -0
- package/src/types/runtime-summary.ts +49 -0
- package/src/types.ts +74 -0
- package/src/utils/file-lock.ts +391 -0
- package/{dist/utils/glob-match.js → src/utils/glob-match.ts} +21 -20
- package/{dist/utils/hashing.js → src/utils/hashing.ts} +6 -4
- package/src/utils/io.ts +110 -0
- package/{dist/utils/nlp.js → src/utils/nlp.ts} +19 -12
- package/{dist/utils/plugin-logger.js → src/utils/plugin-logger.ts} +33 -8
- package/src/utils/subagent-probe.ts +94 -0
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +70 -1
- package/templates/pain_settings.json +2 -1
- package/tests/README.md +120 -0
- package/tests/build-artifacts.test.ts +111 -0
- package/tests/commands/evolution-status.test.ts +222 -0
- package/tests/commands/evolver.test.ts +22 -0
- package/tests/commands/export.test.ts +78 -0
- package/tests/commands/nocturnal-review.test.ts +448 -0
- package/tests/commands/nocturnal-train.test.ts +97 -0
- package/tests/commands/pain.test.ts +108 -0
- package/tests/commands/samples.test.ts +65 -0
- package/tests/commands/strategy.test.ts +34 -0
- package/tests/commands/thinking-os.test.ts +88 -0
- package/tests/core/adaptive-thresholds.test.ts +261 -0
- package/tests/core/config-service.test.ts +89 -0
- package/tests/core/config.test.ts +90 -0
- package/tests/core/control-ui-db.test.ts +75 -0
- package/tests/core/core-template-guidance.test.ts +21 -0
- package/tests/core/detection-funnel.test.ts +63 -0
- package/tests/core/detection-service.test.ts +50 -0
- package/tests/core/dictionary-service.test.ts +116 -0
- package/tests/core/dictionary.test.ts +168 -0
- package/tests/core/empathy-keyword-matcher.test.ts +209 -0
- package/tests/core/event-log.test.ts +181 -0
- package/tests/core/evolution-e2e.test.ts +58 -0
- package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
- package/tests/core/evolution-engine.test.ts +562 -0
- package/tests/core/evolution-logger.test.ts +148 -0
- package/tests/core/evolution-migration.test.ts +50 -0
- package/tests/core/evolution-paths.test.ts +21 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
- package/tests/core/evolution-reducer.test.ts +180 -0
- package/tests/core/evolution-types-loop.test.ts +48 -0
- package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
- package/tests/core/external-training-contract.test.ts +463 -0
- package/tests/core/focus-history.test.ts +682 -0
- package/tests/core/init-flatten.test.ts +69 -0
- package/tests/core/init-refactor.test.ts +87 -0
- package/tests/core/init-v1.3.test.ts +46 -0
- package/tests/core/init.test.ts +190 -0
- package/tests/core/local-worker-routing.test.ts +757 -0
- package/tests/core/migration.test.ts +84 -0
- package/tests/core/model-deployment-registry.test.ts +845 -0
- package/tests/core/model-training-registry.test.ts +889 -0
- package/tests/core/nocturnal-arbiter.test.ts +494 -0
- package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
- package/tests/core/nocturnal-compliance.test.ts +646 -0
- package/tests/core/nocturnal-dataset.test.ts +892 -0
- package/tests/core/nocturnal-executability.test.ts +357 -0
- package/tests/core/nocturnal-export.test.ts +462 -0
- package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
- package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
- package/tests/core/nocturnal-trinity.test.ts +953 -0
- package/tests/core/pain.test.ts +33 -0
- package/tests/core/path-resolver.test.ts +57 -0
- package/tests/core/paths-refactor.test.ts +42 -0
- package/tests/core/phase7-rollout-integration.test.ts +477 -0
- package/tests/core/principle-training-state.test.ts +712 -0
- package/tests/core/profile.test.ts +56 -0
- package/tests/core/promotion-gate.test.ts +556 -0
- package/tests/core/risk-calculator.test.ts +168 -0
- package/tests/core/session-tracker.test.ts +191 -0
- package/tests/core/training-program.test.ts +472 -0
- package/tests/core/trajectory.test.ts +265 -0
- package/tests/core/workspace-context-factory.test.ts +18 -0
- package/tests/core/workspace-context.test.ts +134 -0
- package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
- package/tests/fixtures/production-compatibility.test.ts +147 -0
- package/tests/fixtures/production-mock-generator.ts +282 -0
- package/tests/hooks/bash-risk-integration.test.ts +137 -0
- package/tests/hooks/bash-risk.test.ts +81 -0
- package/tests/hooks/edit-verification.test.ts +678 -0
- package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
- package/tests/hooks/gate-edit-verification.test.ts +435 -0
- package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
- package/tests/hooks/gate.test.ts +271 -0
- package/tests/hooks/gfi-gate-unit.test.ts +422 -0
- package/tests/hooks/gfi-gate.test.ts +669 -0
- package/tests/hooks/lifecycle.test.ts +248 -0
- package/tests/hooks/llm.test.ts +308 -0
- package/tests/hooks/message-sanitize.test.ts +36 -0
- package/tests/hooks/pain.test.ts +141 -0
- package/tests/hooks/progressive-trust-gate.test.ts +277 -0
- package/tests/hooks/prompt.test.ts +1411 -0
- package/tests/hooks/subagent.test.ts +467 -0
- package/tests/hooks/thinking-gate.test.ts +313 -0
- package/tests/http/principles-console-route.test.ts +140 -0
- package/tests/hygiene-tracker.test.ts +77 -0
- package/tests/index.integration.test.ts +179 -0
- package/tests/index.shadow-routing.integration.test.ts +140 -0
- package/tests/index.test.ts +9 -0
- package/tests/integration/empathy-workflow-integration.test.ts +627 -0
- package/tests/service/control-ui-query-service.test.ts +121 -0
- package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
- package/tests/service/evolution-worker.test.ts +585 -0
- package/tests/service/nocturnal-runtime.test.ts +470 -0
- package/tests/service/nocturnal-service.test.ts +577 -0
- package/tests/service/nocturnal-target-selector.test.ts +615 -0
- package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
- package/tests/service/phase3-input-filter.test.ts +289 -0
- package/tests/service/runtime-summary-service.test.ts +919 -0
- package/tests/task-compliance.test.ts +166 -0
- package/tests/test-utils.ts +48 -0
- package/tests/tools/critique-prompt.test.ts +260 -0
- package/tests/tools/deep-reflect.test.ts +232 -0
- package/tests/tools/model-index.test.ts +246 -0
- package/tests/ui/app.test.tsx +114 -0
- package/tests/utils/file-lock.test.ts +407 -0
- package/tests/utils/hashing.test.ts +32 -0
- package/tests/utils/io.test.ts +39 -0
- package/tests/utils/nlp.test.ts +53 -0
- package/tests/utils/plugin-logger.test.ts +156 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/ui/src/App.tsx +45 -0
- package/ui/src/api.ts +216 -0
- package/ui/src/charts.tsx +586 -0
- package/ui/src/components/ErrorState.tsx +6 -0
- package/ui/src/components/Loading.tsx +13 -0
- package/ui/src/components/ProtectedRoute.tsx +12 -0
- package/ui/src/components/Shell.tsx +91 -0
- package/ui/src/components/WorkspaceConfig.tsx +146 -0
- package/ui/src/components/index.ts +5 -0
- package/ui/src/context/auth.tsx +80 -0
- package/ui/src/context/theme.tsx +66 -0
- package/ui/src/hooks/useAutoRefresh.ts +39 -0
- package/ui/src/i18n/ui.ts +363 -0
- package/ui/src/main.tsx +16 -0
- package/ui/src/pages/EvolutionPage.tsx +352 -0
- package/ui/src/pages/FeedbackPage.tsx +140 -0
- package/ui/src/pages/GateMonitorPage.tsx +136 -0
- package/ui/src/pages/LoginPage.tsx +88 -0
- package/ui/src/pages/OverviewPage.tsx +238 -0
- package/ui/src/pages/SamplesPage.tsx +174 -0
- package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
- package/ui/src/styles.css +1661 -0
- package/ui/src/types.ts +368 -0
- package/ui/src/utils/format.ts +15 -0
- package/vitest.config.ts +23 -0
- package/dist/commands/capabilities.d.ts +0 -3
- package/dist/commands/capabilities.js +0 -73
- package/dist/commands/context.d.ts +0 -5
- package/dist/commands/evolution-status.d.ts +0 -4
- package/dist/commands/evolution-status.js +0 -117
- package/dist/commands/evolver.d.ts +0 -9
- package/dist/commands/evolver.js +0 -26
- package/dist/commands/export.d.ts +0 -2
- package/dist/commands/export.js +0 -98
- package/dist/commands/focus.d.ts +0 -14
- package/dist/commands/focus.js +0 -457
- package/dist/commands/nocturnal-review.d.ts +0 -24
- package/dist/commands/nocturnal-review.js +0 -265
- package/dist/commands/nocturnal-rollout.d.ts +0 -27
- package/dist/commands/nocturnal-rollout.js +0 -671
- package/dist/commands/nocturnal-train.d.ts +0 -25
- package/dist/commands/nocturnal-train.js +0 -919
- package/dist/commands/pain.d.ts +0 -5
- package/dist/commands/principle-rollback.d.ts +0 -4
- package/dist/commands/principle-rollback.js +0 -22
- package/dist/commands/rollback.d.ts +0 -19
- package/dist/commands/samples.d.ts +0 -2
- package/dist/commands/samples.js +0 -55
- package/dist/commands/strategy.d.ts +0 -3
- package/dist/commands/strategy.js +0 -29
- package/dist/commands/thinking-os.d.ts +0 -2
- package/dist/config/defaults/runtime.d.ts +0 -40
- package/dist/config/errors.d.ts +0 -84
- package/dist/config/errors.js +0 -94
- package/dist/config/index.js +0 -7
- package/dist/constants/diagnostician.d.ts +0 -12
- package/dist/constants/diagnostician.js +0 -56
- package/dist/constants/tools.d.ts +0 -17
- package/dist/constants/tools.js +0 -54
- package/dist/core/adaptive-thresholds.d.ts +0 -186
- package/dist/core/adaptive-thresholds.js +0 -300
- package/dist/core/config-service.d.ts +0 -15
- package/dist/core/config.d.ts +0 -127
- package/dist/core/control-ui-db.d.ts +0 -95
- package/dist/core/control-ui-db.js +0 -292
- package/dist/core/detection-funnel.d.ts +0 -33
- package/dist/core/detection-service.d.ts +0 -15
- package/dist/core/dictionary-service.d.ts +0 -15
- package/dist/core/dictionary.d.ts +0 -38
- package/dist/core/event-log.d.ts +0 -82
- package/dist/core/event-log.js +0 -463
- package/dist/core/evolution-engine.d.ts +0 -118
- package/dist/core/evolution-engine.js +0 -464
- package/dist/core/evolution-logger.d.ts +0 -137
- package/dist/core/evolution-logger.js +0 -256
- package/dist/core/evolution-migration.d.ts +0 -5
- package/dist/core/evolution-migration.js +0 -65
- package/dist/core/evolution-reducer.d.ts +0 -98
- package/dist/core/evolution-reducer.js +0 -465
- package/dist/core/evolution-types.d.ts +0 -287
- package/dist/core/evolution-types.js +0 -78
- package/dist/core/external-training-contract.d.ts +0 -276
- package/dist/core/external-training-contract.js +0 -269
- package/dist/core/focus-history.d.ts +0 -210
- package/dist/core/focus-history.js +0 -1185
- package/dist/core/hygiene/tracker.d.ts +0 -22
- package/dist/core/hygiene/tracker.js +0 -106
- package/dist/core/init.d.ts +0 -12
- package/dist/core/local-worker-routing.d.ts +0 -175
- package/dist/core/local-worker-routing.js +0 -525
- package/dist/core/migration.d.ts +0 -6
- package/dist/core/model-deployment-registry.d.ts +0 -218
- package/dist/core/model-deployment-registry.js +0 -503
- package/dist/core/model-training-registry.d.ts +0 -295
- package/dist/core/model-training-registry.js +0 -475
- package/dist/core/nocturnal-arbiter.d.ts +0 -159
- package/dist/core/nocturnal-arbiter.js +0 -534
- package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
- package/dist/core/nocturnal-candidate-scoring.js +0 -266
- package/dist/core/nocturnal-compliance.d.ts +0 -175
- package/dist/core/nocturnal-compliance.js +0 -824
- package/dist/core/nocturnal-dataset.d.ts +0 -224
- package/dist/core/nocturnal-dataset.js +0 -443
- package/dist/core/nocturnal-executability.d.ts +0 -85
- package/dist/core/nocturnal-executability.js +0 -331
- package/dist/core/nocturnal-export.d.ts +0 -124
- package/dist/core/nocturnal-export.js +0 -275
- package/dist/core/nocturnal-paths.d.ts +0 -124
- package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
- package/dist/core/nocturnal-trajectory-extractor.js +0 -307
- package/dist/core/nocturnal-trinity.d.ts +0 -311
- package/dist/core/nocturnal-trinity.js +0 -880
- package/dist/core/pain.d.ts +0 -4
- package/dist/core/pain.js +0 -70
- package/dist/core/path-resolver.d.ts +0 -46
- package/dist/core/paths.d.ts +0 -65
- package/dist/core/principle-training-state.d.ts +0 -121
- package/dist/core/principle-training-state.js +0 -321
- package/dist/core/profile.d.ts +0 -62
- package/dist/core/profile.js +0 -210
- package/dist/core/promotion-gate.d.ts +0 -238
- package/dist/core/promotion-gate.js +0 -529
- package/dist/core/risk-calculator.d.ts +0 -22
- package/dist/core/session-tracker.d.ts +0 -99
- package/dist/core/shadow-observation-registry.d.ts +0 -217
- package/dist/core/shadow-observation-registry.js +0 -308
- package/dist/core/system-logger.d.ts +0 -8
- package/dist/core/thinking-models.d.ts +0 -38
- package/dist/core/thinking-models.js +0 -170
- package/dist/core/training-program.d.ts +0 -233
- package/dist/core/training-program.js +0 -433
- package/dist/core/trajectory.d.ts +0 -411
- package/dist/core/trajectory.js +0 -1307
- package/dist/core/workspace-context.d.ts +0 -71
- package/dist/hooks/bash-risk.d.ts +0 -57
- package/dist/hooks/bash-risk.js +0 -137
- package/dist/hooks/edit-verification.d.ts +0 -62
- package/dist/hooks/edit-verification.js +0 -256
- package/dist/hooks/gate-block-helper.d.ts +0 -44
- package/dist/hooks/gate-block-helper.js +0 -119
- package/dist/hooks/gate.d.ts +0 -24
- package/dist/hooks/gate.js +0 -173
- package/dist/hooks/gfi-gate.d.ts +0 -40
- package/dist/hooks/gfi-gate.js +0 -113
- package/dist/hooks/lifecycle.d.ts +0 -5
- package/dist/hooks/lifecycle.js +0 -284
- package/dist/hooks/llm.d.ts +0 -12
- package/dist/hooks/message-sanitize.d.ts +0 -3
- package/dist/hooks/message-sanitize.js +0 -37
- package/dist/hooks/pain.d.ts +0 -5
- package/dist/hooks/pain.js +0 -301
- package/dist/hooks/progressive-trust-gate.d.ts +0 -51
- package/dist/hooks/progressive-trust-gate.js +0 -89
- package/dist/hooks/prompt.d.ts +0 -47
- package/dist/hooks/prompt.js +0 -884
- package/dist/hooks/subagent.d.ts +0 -10
- package/dist/hooks/subagent.js +0 -387
- package/dist/hooks/thinking-checkpoint.d.ts +0 -37
- package/dist/hooks/thinking-checkpoint.js +0 -51
- package/dist/hooks/trajectory-collector.d.ts +0 -32
- package/dist/hooks/trajectory-collector.js +0 -256
- package/dist/http/principles-console-route.d.ts +0 -9
- package/dist/http/principles-console-route.js +0 -567
- package/dist/i18n/commands.d.ts +0 -26
- package/dist/i18n/commands.js +0 -116
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -581
- package/dist/service/central-database.d.ts +0 -104
- package/dist/service/central-database.js +0 -649
- package/dist/service/control-ui-query-service.d.ts +0 -221
- package/dist/service/control-ui-query-service.js +0 -543
- package/dist/service/empathy-observer-manager.d.ts +0 -52
- package/dist/service/empathy-observer-manager.js +0 -229
- package/dist/service/evolution-query-service.d.ts +0 -155
- package/dist/service/evolution-query-service.js +0 -258
- package/dist/service/evolution-worker.d.ts +0 -101
- package/dist/service/evolution-worker.js +0 -974
- package/dist/service/nocturnal-runtime.d.ts +0 -183
- package/dist/service/nocturnal-service.d.ts +0 -163
- package/dist/service/nocturnal-service.js +0 -787
- package/dist/service/nocturnal-target-selector.d.ts +0 -145
- package/dist/service/nocturnal-target-selector.js +0 -315
- package/dist/service/phase3-input-filter.d.ts +0 -73
- package/dist/service/phase3-input-filter.js +0 -172
- package/dist/service/runtime-summary-service.d.ts +0 -122
- package/dist/service/runtime-summary-service.js +0 -485
- package/dist/service/trajectory-service.d.ts +0 -2
- package/dist/service/trajectory-service.js +0 -15
- package/dist/tools/critique-prompt.d.ts +0 -14
- package/dist/tools/deep-reflect.d.ts +0 -39
- package/dist/tools/deep-reflect.js +0 -350
- package/dist/tools/model-index.d.ts +0 -9
- package/dist/types/event-types.d.ts +0 -306
- package/dist/types/event-types.js +0 -106
- package/dist/types/hygiene-types.d.ts +0 -20
- package/dist/types/hygiene-types.js +0 -12
- package/dist/types/runtime-summary.d.ts +0 -47
- package/dist/types/runtime-summary.js +0 -1
- package/dist/types.d.ts +0 -50
- package/dist/types.js +0 -22
- package/dist/utils/file-lock.d.ts +0 -71
- package/dist/utils/file-lock.js +0 -309
- package/dist/utils/glob-match.d.ts +0 -28
- package/dist/utils/hashing.d.ts +0 -9
- package/dist/utils/io.d.ts +0 -6
- package/dist/utils/io.js +0 -106
- package/dist/utils/nlp.d.ts +0 -9
- package/dist/utils/plugin-logger.d.ts +0 -39
- package/dist/utils/subagent-probe.d.ts +0 -34
- package/dist/utils/subagent-probe.js +0 -81
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate Block Helper - Single Authoritative Block Persistence
|
|
3
|
+
*
|
|
4
|
+
* PURPOSE: Provide ONE authoritative implementation for gate block persistence.
|
|
5
|
+
*
|
|
6
|
+
* All gate modules (progressive-trust-gate, gfi-gate, etc.) must use this
|
|
7
|
+
* helper to ensure consistent block tracking, event logging, and retry behavior.
|
|
8
|
+
*
|
|
9
|
+
* This eliminates the "multi-truth source" problem where different modules
|
|
10
|
+
* had their own block persistence implementations.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { trackBlock } from '../core/session-tracker.js';
|
|
14
|
+
import type { WorkspaceContext } from '../core/workspace-context.js';
|
|
15
|
+
import type { PluginHookBeforeToolCallResult } from '../openclaw-sdk.js';
|
|
16
|
+
import {
|
|
17
|
+
TRAJECTORY_GATE_BLOCK_RETRY_DELAY_MS,
|
|
18
|
+
TRAJECTORY_GATE_BLOCK_MAX_RETRIES
|
|
19
|
+
} from '../config/index.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Block context containing all information needed for block persistence
|
|
23
|
+
*/
|
|
24
|
+
export interface BlockContext {
|
|
25
|
+
filePath: string;
|
|
26
|
+
reason: string;
|
|
27
|
+
toolName: string;
|
|
28
|
+
sessionId?: string;
|
|
29
|
+
/** Source module that triggered the block (for audit trail) */
|
|
30
|
+
blockSource?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Single authoritative block helper.
|
|
35
|
+
*
|
|
36
|
+
* Responsibilities:
|
|
37
|
+
* 1. Call trackBlock() for session-level GFI tracking
|
|
38
|
+
* 2. Record to EventLog for operator visibility
|
|
39
|
+
* 3. Record to trajectory for analytics
|
|
40
|
+
* 4. Handle retry logic for trajectory persistence failures
|
|
41
|
+
* 5. Generate consistent operator-facing block message
|
|
42
|
+
*
|
|
43
|
+
* @param wctx - Workspace context
|
|
44
|
+
* @param blockCtx - Block context with file, reason, tool info
|
|
45
|
+
* @param logger - Logger instance
|
|
46
|
+
* @returns PluginHookBeforeToolCallResult with block=true
|
|
47
|
+
*/
|
|
48
|
+
export function recordGateBlockAndReturn(
|
|
49
|
+
wctx: WorkspaceContext,
|
|
50
|
+
blockCtx: BlockContext,
|
|
51
|
+
logger: { warn?: (message: string) => void; error?: (message: string) => void; info?: (message: string) => void }
|
|
52
|
+
): PluginHookBeforeToolCallResult {
|
|
53
|
+
const { filePath, reason, toolName, sessionId, blockSource } = blockCtx;
|
|
54
|
+
|
|
55
|
+
// Default logger if not provided
|
|
56
|
+
const logWarn = (msg: string) => logger.warn?.(msg);
|
|
57
|
+
const logError = (msg: string) => logger.error?.(msg);
|
|
58
|
+
|
|
59
|
+
// Log the block event
|
|
60
|
+
const sourceTag = blockSource ? `[${blockSource}]` : '';
|
|
61
|
+
logError(`[PD_GATE]${sourceTag} BLOCKED: ${filePath}. Reason: ${reason}`);
|
|
62
|
+
|
|
63
|
+
// 1. Track block for session-level GFI calculation
|
|
64
|
+
if (sessionId) {
|
|
65
|
+
trackBlock(sessionId);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 2. Prepare trajectory payload
|
|
69
|
+
const trajectoryPayload = {
|
|
70
|
+
sessionId: sessionId ?? null,
|
|
71
|
+
toolName,
|
|
72
|
+
filePath,
|
|
73
|
+
reason,
|
|
74
|
+
blockSource: blockSource ?? 'gate',
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// 3. Record to EventLog (primary persistence)
|
|
78
|
+
try {
|
|
79
|
+
wctx.eventLog.recordGateBlock(sessionId, {
|
|
80
|
+
toolName,
|
|
81
|
+
filePath,
|
|
82
|
+
reason,
|
|
83
|
+
blockSource: blockSource ?? 'gate',
|
|
84
|
+
});
|
|
85
|
+
} catch (error: unknown) {
|
|
86
|
+
logWarn(`[PD_GATE] Failed to record gate block event: ${String(error)}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 4. Record to trajectory (secondary persistence with retry)
|
|
90
|
+
try {
|
|
91
|
+
wctx.trajectory?.recordGateBlock?.(trajectoryPayload);
|
|
92
|
+
} catch (error: unknown) {
|
|
93
|
+
logWarn(`[PD_GATE] Failed to record trajectory gate block: ${String(error)}`);
|
|
94
|
+
scheduleTrajectoryGateBlockRetry(wctx, trajectoryPayload, 1, logWarn, logError);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 5. Return consistent block result with operator guidance
|
|
98
|
+
return {
|
|
99
|
+
block: true,
|
|
100
|
+
blockReason: `[Principles Disciple] Security Gate Blocked this action.
|
|
101
|
+
File: ${filePath}
|
|
102
|
+
Reason: ${reason}
|
|
103
|
+
|
|
104
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
105
|
+
📋 How to unblock this operation:
|
|
106
|
+
|
|
107
|
+
1. Use the plan-script skill to create a PLAN.md:
|
|
108
|
+
→ Invoke: skill:plan-script
|
|
109
|
+
|
|
110
|
+
2. Fill in the plan with:
|
|
111
|
+
- Target Files: ${filePath}
|
|
112
|
+
- Steps: What you want to do (be specific)
|
|
113
|
+
- Metrics: How to verify success
|
|
114
|
+
- Active Mental Models: Select 2 relevant models from .principles/THINKING_OS.md
|
|
115
|
+
- Rollback: How to restore if it fails
|
|
116
|
+
|
|
117
|
+
3. After completing the plan, set STATUS: READY in PLAN.md
|
|
118
|
+
|
|
119
|
+
4. Retry the operation
|
|
120
|
+
|
|
121
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
122
|
+
This is a mandatory security gate. The operation was blocked because the modification exceeds the allowed threshold for your current evolution tier.
|
|
123
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Schedule retry for trajectory gate block persistence.
|
|
129
|
+
*
|
|
130
|
+
* Uses exponential backoff with max retries.
|
|
131
|
+
* Failures are logged but do not affect the runtime block decision.
|
|
132
|
+
*/
|
|
133
|
+
function scheduleTrajectoryGateBlockRetry(
|
|
134
|
+
wctx: WorkspaceContext,
|
|
135
|
+
payload: {
|
|
136
|
+
sessionId: string | null;
|
|
137
|
+
toolName: string;
|
|
138
|
+
filePath: string;
|
|
139
|
+
reason: string;
|
|
140
|
+
blockSource?: string;
|
|
141
|
+
},
|
|
142
|
+
attempt: number,
|
|
143
|
+
logWarn: (message: string) => void,
|
|
144
|
+
logError: (message: string) => void
|
|
145
|
+
): void {
|
|
146
|
+
if (attempt > TRAJECTORY_GATE_BLOCK_MAX_RETRIES) {
|
|
147
|
+
logError(`[PD_GATE] Failed to persist trajectory gate block after ${TRAJECTORY_GATE_BLOCK_MAX_RETRIES} retries: ${payload.toolName} ${payload.filePath}`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
try {
|
|
153
|
+
wctx.trajectory?.recordGateBlock?.(payload);
|
|
154
|
+
logWarn(`[PD_GATE] Trajectory gate block persisted on retry ${attempt}`);
|
|
155
|
+
} catch (error: unknown) {
|
|
156
|
+
logWarn(`[PD_GATE] Retrying trajectory gate block persistence (attempt ${attempt + 1}): ${String(error)}`);
|
|
157
|
+
scheduleTrajectoryGateBlockRetry(wctx, payload, attempt + 1, logWarn, logError);
|
|
158
|
+
}
|
|
159
|
+
}, TRAJECTORY_GATE_BLOCK_RETRY_DELAY_MS * attempt);
|
|
160
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Gate Hook - Orchestration Layer
|
|
3
|
+
*
|
|
4
|
+
* HOOK CHAIN PRIORITY (short-circuits on first block):
|
|
5
|
+
*
|
|
6
|
+
* 1. Early Return: Skip if not write/bash/agent tool or no workspace
|
|
7
|
+
* 2. Thinking OS Checkpoint (P-10): Deep reflection enforcement
|
|
8
|
+
* 3. GFI Gate: Fatigue index-based blocking
|
|
9
|
+
* 4. Bash Mutation Detection: Heuristic for bash file modifications
|
|
10
|
+
* 5. Progressive Gate: EP tier-based access control
|
|
11
|
+
* 6. Edit Verification (P-03): Exact/fuzzy match for edit operations
|
|
12
|
+
*
|
|
13
|
+
* IMPORTANT: This is the SINGLE AUTHORITATIVE orchestration path.
|
|
14
|
+
* All policy modules (gfi-gate, progressive-trust-gate) use the shared
|
|
15
|
+
* `recordGateBlockAndReturn` helper to ensure consistent block persistence.
|
|
16
|
+
*
|
|
17
|
+
* Zero-width character detection is handled in bash-risk.ts.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import * as fs from 'fs';
|
|
21
|
+
import * as path from 'path';
|
|
22
|
+
import { isRisky, normalizePath, planStatus as getPlanStatus } from '../utils/io.js';
|
|
23
|
+
import { normalizeProfile } from '../core/profile.js';
|
|
24
|
+
import { estimateLineChanges } from '../core/risk-calculator.js';
|
|
25
|
+
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
26
|
+
import { checkThinkingCheckpoint } from './thinking-checkpoint.js';
|
|
27
|
+
import { handleEditVerification } from './edit-verification.js';
|
|
28
|
+
import { checkGfiGate } from './gfi-gate.js';
|
|
29
|
+
import { checkProgressiveTrustGate } from './progressive-trust-gate.js';
|
|
30
|
+
import { recordGateBlockAndReturn } from './gate-block-helper.js';
|
|
31
|
+
import type { PluginHookBeforeToolCallEvent, PluginHookToolContext, PluginHookBeforeToolCallResult } from '../openclaw-sdk.js';
|
|
32
|
+
import {
|
|
33
|
+
AGENT_TOOLS,
|
|
34
|
+
BASH_TOOLS_SET,
|
|
35
|
+
WRITE_TOOLS,
|
|
36
|
+
} from '../constants/tools.js';
|
|
37
|
+
|
|
38
|
+
export function handleBeforeToolCall(
|
|
39
|
+
event: PluginHookBeforeToolCallEvent,
|
|
40
|
+
ctx: PluginHookToolContext & { workspaceDir?: string; pluginConfig?: Record<string, unknown>; logger?: any }
|
|
41
|
+
): PluginHookBeforeToolCallResult | void {
|
|
42
|
+
const logger = ctx.logger || console;
|
|
43
|
+
|
|
44
|
+
// 1. Identify tool type
|
|
45
|
+
const isBash = BASH_TOOLS_SET.has(event.toolName);
|
|
46
|
+
const isWriteTool = WRITE_TOOLS.has(event.toolName);
|
|
47
|
+
const isAgentTool = AGENT_TOOLS.has(event.toolName);
|
|
48
|
+
|
|
49
|
+
if (!ctx.workspaceDir || (!isWriteTool && !isBash && !isAgentTool)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const wctx = WorkspaceContext.fromHookContext(ctx);
|
|
54
|
+
|
|
55
|
+
// 2. Load Profile
|
|
56
|
+
const profilePath = wctx.resolve('PROFILE');
|
|
57
|
+
let profile = {
|
|
58
|
+
risk_paths: [] as string[],
|
|
59
|
+
gate: { require_plan_for_risk_paths: true },
|
|
60
|
+
progressive_gate: {
|
|
61
|
+
enabled: true,
|
|
62
|
+
plan_approvals: {
|
|
63
|
+
enabled: false,
|
|
64
|
+
max_lines_override: -1,
|
|
65
|
+
allowed_patterns: [] as string[],
|
|
66
|
+
allowed_operations: [] as string[],
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
edit_verification: {
|
|
70
|
+
enabled: true,
|
|
71
|
+
max_file_size_bytes: 10 * 1024 * 1024,
|
|
72
|
+
fuzzy_match_enabled: true,
|
|
73
|
+
fuzzy_match_threshold: 0.8,
|
|
74
|
+
skip_large_file_action: 'warn' as 'warn' | 'block',
|
|
75
|
+
},
|
|
76
|
+
thinking_checkpoint: {
|
|
77
|
+
enabled: false, // Default OFF
|
|
78
|
+
window_ms: 5 * 60 * 1000,
|
|
79
|
+
high_risk_tools: ['run_shell_command', 'delete_file', 'move_file'],
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (fs.existsSync(profilePath)) {
|
|
84
|
+
try {
|
|
85
|
+
const rawProfile = JSON.parse(fs.readFileSync(profilePath, 'utf8'));
|
|
86
|
+
profile = normalizeProfile(rawProfile);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
logger?.error?.(`[PD_GATE] Failed to parse PROFILE.json: ${String(e)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
93
|
+
// POLICY STEP 1: Thinking OS Checkpoint (P-10)
|
|
94
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
95
|
+
// Only enforced when thinking_checkpoint.enabled = true in PROFILE.json
|
|
96
|
+
const thinkingResult = checkThinkingCheckpoint(
|
|
97
|
+
event,
|
|
98
|
+
profile.thinking_checkpoint || {},
|
|
99
|
+
ctx.sessionId,
|
|
100
|
+
logger
|
|
101
|
+
);
|
|
102
|
+
if (thinkingResult) {
|
|
103
|
+
return thinkingResult;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
107
|
+
// POLICY STEP 2: GFI Gate - Hard Intercept
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
109
|
+
// 根据 GFI (疲劳指数) 精细化拦截工具调用
|
|
110
|
+
// 注意:TIER 0 (只读工具) 已在早期过滤中放行,此处不检查
|
|
111
|
+
const gfiGateConfig = wctx.config.get('gfi_gate');
|
|
112
|
+
const gfiResult = checkGfiGate(event, wctx, ctx.sessionId, gfiGateConfig, logger);
|
|
113
|
+
if (gfiResult) {
|
|
114
|
+
return gfiResult;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Merge pluginConfig (OpenClaw UI settings)
|
|
118
|
+
const configRiskPaths = (ctx.pluginConfig?.riskPaths as string[] | undefined) ?? [];
|
|
119
|
+
if (configRiskPaths.length > 0) {
|
|
120
|
+
profile.risk_paths = [...new Set([...profile.risk_paths, ...configRiskPaths])];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 3. Resolve the target file path
|
|
124
|
+
let filePath = event.params.file_path || event.params.path || event.params.file || event.params.target;
|
|
125
|
+
|
|
126
|
+
// Heuristic for bash mutation detection
|
|
127
|
+
if (isBash && !filePath) {
|
|
128
|
+
const command = String(event.params.command || event.params.args || "");
|
|
129
|
+
const mutationMatch = command.match(/(?:>|>>|sed\s+-i|rm|mv|mkdir|touch|cp)\s+(?:-[a-zA-Z]+\s+)*([^\s;&|<>]+)/);
|
|
130
|
+
|
|
131
|
+
if (mutationMatch) {
|
|
132
|
+
filePath = mutationMatch[1];
|
|
133
|
+
} else {
|
|
134
|
+
const hasRiskPath = profile.risk_paths.some(rp => command.includes(rp));
|
|
135
|
+
const isMutation = /(?:>|>>|sed|rm|mv|mkdir|touch|cp|npm|yarn|pnpm|pip|cargo)/.test(command);
|
|
136
|
+
|
|
137
|
+
if (hasRiskPath && isMutation) {
|
|
138
|
+
filePath = command;
|
|
139
|
+
} else {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (typeof filePath !== 'string') return;
|
|
146
|
+
|
|
147
|
+
const relPath = normalizePath(filePath, ctx.workspaceDir);
|
|
148
|
+
const risky = (isBash && filePath.includes(' '))
|
|
149
|
+
? profile.risk_paths.some(rp => filePath.includes(rp))
|
|
150
|
+
: isRisky(relPath, profile.risk_paths);
|
|
151
|
+
|
|
152
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
153
|
+
// POLICY STEP 3: Progressive Trust Gate (Stage 1-4 access control)
|
|
154
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
155
|
+
// IMPORTANT: This step does NOT return early on allow.
|
|
156
|
+
// We must continue to edit verification for ALL allowed operations.
|
|
157
|
+
if (profile.progressive_gate?.enabled) {
|
|
158
|
+
const lineChanges = estimateLineChanges({ toolName: event.toolName, params: event.params });
|
|
159
|
+
const progressiveGateResult = checkProgressiveTrustGate(
|
|
160
|
+
event,
|
|
161
|
+
wctx,
|
|
162
|
+
relPath,
|
|
163
|
+
risky,
|
|
164
|
+
lineChanges,
|
|
165
|
+
logger,
|
|
166
|
+
ctx,
|
|
167
|
+
profile
|
|
168
|
+
);
|
|
169
|
+
if (progressiveGateResult) {
|
|
170
|
+
return progressiveGateResult;
|
|
171
|
+
}
|
|
172
|
+
// NOTE: Do NOT return here! Continue to edit verification.
|
|
173
|
+
// All allowed operations (regardless of EP tier) should still run edit verification.
|
|
174
|
+
} else {
|
|
175
|
+
// FALLBACK: Legacy Gate Logic (when progressive gate is disabled)
|
|
176
|
+
if (risky && profile.gate?.require_plan_for_risk_paths) {
|
|
177
|
+
const planStatus = getPlanStatus(ctx.workspaceDir);
|
|
178
|
+
if (planStatus !== 'READY') {
|
|
179
|
+
return recordGateBlockAndReturn(wctx, {
|
|
180
|
+
filePath: relPath,
|
|
181
|
+
reason: `No READY plan found in PLAN.md.`,
|
|
182
|
+
toolName: event.toolName,
|
|
183
|
+
sessionId: ctx.sessionId,
|
|
184
|
+
blockSource: 'gate-legacy',
|
|
185
|
+
}, logger);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
191
|
+
// POLICY STEP 4: Edit Tool Verification (P-03)
|
|
192
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
193
|
+
// This MUST run after all other gate checks for ALL tools.
|
|
194
|
+
// Edit verification ensures oldText matches the actual file content.
|
|
195
|
+
if (event.toolName === 'edit' && profile.edit_verification?.enabled !== false) {
|
|
196
|
+
const verifyResult = handleEditVerification(event, wctx, ctx, {
|
|
197
|
+
enabled: profile.edit_verification.enabled,
|
|
198
|
+
max_file_size_bytes: profile.edit_verification.max_file_size_bytes,
|
|
199
|
+
fuzzy_match_enabled: profile.edit_verification.fuzzy_match_enabled,
|
|
200
|
+
fuzzy_match_threshold: profile.edit_verification.fuzzy_match_threshold,
|
|
201
|
+
skip_large_file_action: profile.edit_verification.skip_large_file_action as 'warn' | 'block' | undefined,
|
|
202
|
+
});
|
|
203
|
+
if (verifyResult) {
|
|
204
|
+
return verifyResult; // Block or modify params
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// All checks passed - allow the operation
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GFI Gate Module
|
|
3
|
+
*
|
|
4
|
+
* Handles Fatigue Index (GFI) based tool blocking with TIER 0-3 classification.
|
|
5
|
+
*
|
|
6
|
+
* **Responsibilities:**
|
|
7
|
+
* - Calculate dynamic GFI thresholds based on EP tier and line changes
|
|
8
|
+
* - Apply tier-based tool blocking:
|
|
9
|
+
* - TIER 0: Read-only tools (never blocked)
|
|
10
|
+
* - TIER 1: Low-risk writes (blocked when GFI >= low_risk_block threshold)
|
|
11
|
+
* - TIER 2: High-risk operations (blocked when GFI >= high_risk_block threshold)
|
|
12
|
+
* - TIER 3: Bash commands (content-dependent blocking)
|
|
13
|
+
* - Prevent subagent spawn at critically high GFI (>=90)
|
|
14
|
+
*
|
|
15
|
+
* **Configuration:**
|
|
16
|
+
* - GFI thresholds from config.gfi_gate
|
|
17
|
+
* - EP tier multipliers for dynamic threshold calculation
|
|
18
|
+
* - Large change adjustments
|
|
19
|
+
*
|
|
20
|
+
* **Block Persistence:**
|
|
21
|
+
* - Uses shared `recordGateBlockAndReturn` from gate-block-helper.ts
|
|
22
|
+
* - Ensures single authoritative block persistence path
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { getSession } from '../core/session-tracker.js';
|
|
26
|
+
import { estimateLineChanges } from '../core/risk-calculator.js';
|
|
27
|
+
import { analyzeBashCommand, calculateDynamicThreshold, type DynamicThresholdConfig } from './bash-risk.js';
|
|
28
|
+
import { BASH_TOOLS_SET, HIGH_RISK_TOOLS, LOW_RISK_WRITE_TOOLS, AGENT_TOOLS } from '../constants/tools.js';
|
|
29
|
+
import { AGENT_SPAWN_GFI_THRESHOLD } from '../config/index.js';
|
|
30
|
+
import { recordGateBlockAndReturn } from './gate-block-helper.js';
|
|
31
|
+
import { getEvolutionEngine } from '../core/evolution-engine.js';
|
|
32
|
+
import type { WorkspaceContext } from '../core/workspace-context.js';
|
|
33
|
+
import type { PluginHookBeforeToolCallEvent, PluginHookBeforeToolCallResult } from '../openclaw-sdk.js';
|
|
34
|
+
|
|
35
|
+
export interface GfiGateConfig {
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
thresholds?: {
|
|
38
|
+
low_risk_block?: number;
|
|
39
|
+
high_risk_block?: number;
|
|
40
|
+
};
|
|
41
|
+
large_change_lines?: number;
|
|
42
|
+
ep_tier_multipliers?: Record<string, number>;
|
|
43
|
+
bash_safe_patterns?: string[];
|
|
44
|
+
bash_dangerous_patterns?: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Internal helper to call the shared block helper with gfi-gate source tag.
|
|
49
|
+
*/
|
|
50
|
+
function block(
|
|
51
|
+
wctx: WorkspaceContext,
|
|
52
|
+
filePath: string,
|
|
53
|
+
reason: string,
|
|
54
|
+
toolName: string,
|
|
55
|
+
sessionId: string | undefined,
|
|
56
|
+
logger?: { info?: (message: string) => void; warn?: (message: string) => void; error?: (message: string) => void }
|
|
57
|
+
): PluginHookBeforeToolCallResult {
|
|
58
|
+
return recordGateBlockAndReturn(wctx, {
|
|
59
|
+
filePath,
|
|
60
|
+
reason,
|
|
61
|
+
toolName,
|
|
62
|
+
sessionId,
|
|
63
|
+
blockSource: 'gfi-gate',
|
|
64
|
+
}, logger || { warn: () => {}, error: () => {} });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function checkGfiGate(
|
|
68
|
+
event: PluginHookBeforeToolCallEvent,
|
|
69
|
+
wctx: WorkspaceContext,
|
|
70
|
+
sessionId: string | undefined,
|
|
71
|
+
config: GfiGateConfig,
|
|
72
|
+
logger?: { info?: (message: string) => void; warn?: (message: string) => void }
|
|
73
|
+
): PluginHookBeforeToolCallResult | undefined {
|
|
74
|
+
if (!config || config.enabled === false || !sessionId) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const session = getSession(sessionId);
|
|
79
|
+
const currentGfi = session?.currentGfi || 0;
|
|
80
|
+
|
|
81
|
+
const getEpTier = (): number => {
|
|
82
|
+
return getEvolutionEngine(wctx.workspaceDir).getTier();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// TIER 3: Bash commands
|
|
86
|
+
if (BASH_TOOLS_SET.has(event.toolName)) {
|
|
87
|
+
const command = String(event.params.command || event.params.args || '');
|
|
88
|
+
const bashRisk = analyzeBashCommand(
|
|
89
|
+
command,
|
|
90
|
+
config.bash_safe_patterns || [],
|
|
91
|
+
config.bash_dangerous_patterns || [],
|
|
92
|
+
logger
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (bashRisk === 'dangerous') {
|
|
96
|
+
logger?.warn?.(`[PD:GFI_GATE] Dangerous bash command blocked: ${command.substring(0, 50)}...`);
|
|
97
|
+
return block(wctx, command.substring(0, 100), `危险命令被拦截。检测到危险命令模式,需要确认执行意图。`, event.toolName, sessionId, logger);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (bashRisk === 'safe') {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// normal bash - check GFI threshold
|
|
105
|
+
const tier = getEpTier();
|
|
106
|
+
const baseThreshold = config.thresholds?.low_risk_block || 70;
|
|
107
|
+
const dynamicThreshold = calculateDynamicThreshold(
|
|
108
|
+
baseThreshold,
|
|
109
|
+
tier,
|
|
110
|
+
0,
|
|
111
|
+
{
|
|
112
|
+
large_change_lines: config.large_change_lines || 50,
|
|
113
|
+
ep_tier_multipliers: config.ep_tier_multipliers || { '1': 0.5, '2': 0.75, '3': 1.0, '4': 1.5, '5': 2.0 },
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
if (currentGfi >= dynamicThreshold) {
|
|
118
|
+
logger?.warn?.(`[PD:GFI_GATE] Bash blocked by GFI: ${currentGfi} >= ${dynamicThreshold}`);
|
|
119
|
+
return block(wctx, command.substring(0, 100), `疲劳指数过高 (GFI: ${currentGfi}/${dynamicThreshold})。系统进入保护模式。`, event.toolName, sessionId, logger);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// TIER 2: High-risk tools
|
|
126
|
+
if (HIGH_RISK_TOOLS.has(event.toolName)) {
|
|
127
|
+
const tier = getEpTier();
|
|
128
|
+
const baseThreshold = config.thresholds?.high_risk_block || 40;
|
|
129
|
+
const dynamicThreshold = calculateDynamicThreshold(
|
|
130
|
+
baseThreshold,
|
|
131
|
+
tier,
|
|
132
|
+
0,
|
|
133
|
+
{
|
|
134
|
+
large_change_lines: config.large_change_lines || 50,
|
|
135
|
+
ep_tier_multipliers: config.ep_tier_multipliers || { '1': 0.5, '2': 0.75, '3': 1.0, '4': 1.5, '5': 2.0 },
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
if (currentGfi >= dynamicThreshold) {
|
|
140
|
+
const filePath = event.params.file_path || event.params.path || event.params.file || event.params.target || 'unknown';
|
|
141
|
+
logger?.warn?.(`[PD:GFI_GATE] High-risk tool "${event.toolName}" blocked by GFI: ${currentGfi} >= ${dynamicThreshold}`);
|
|
142
|
+
return block(wctx, filePath, `高风险操作被拦截。GFI: ${currentGfi}/${dynamicThreshold}。高风险工具需要更低的阈值。`, event.toolName, sessionId, logger);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// TIER 1: Low-risk write tools
|
|
147
|
+
if (LOW_RISK_WRITE_TOOLS.has(event.toolName)) {
|
|
148
|
+
const tier = getEpTier();
|
|
149
|
+
const lineChanges = estimateLineChanges({ toolName: event.toolName, params: event.params });
|
|
150
|
+
const baseThreshold = config.thresholds?.low_risk_block || 70;
|
|
151
|
+
const dynamicThreshold = calculateDynamicThreshold(
|
|
152
|
+
baseThreshold,
|
|
153
|
+
tier,
|
|
154
|
+
lineChanges,
|
|
155
|
+
{
|
|
156
|
+
large_change_lines: config.large_change_lines || 50,
|
|
157
|
+
ep_tier_multipliers: config.ep_tier_multipliers || { '1': 0.5, '2': 0.75, '3': 1.0, '4': 1.5, '5': 2.0 },
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
if (currentGfi >= dynamicThreshold) {
|
|
162
|
+
const filePath = event.params.file_path || event.params.path || event.params.file || event.params.target || 'unknown';
|
|
163
|
+
logger?.warn?.(`[PD:GFI_GATE] Low-risk tool "${event.toolName}" blocked by GFI: ${currentGfi} >= ${dynamicThreshold}`);
|
|
164
|
+
return block(wctx, filePath, `疲劳指数过高 (GFI: ${currentGfi}/${dynamicThreshold})。系统进入保护模式。`, event.toolName, sessionId, logger);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// AGENT_TOOLS: Block subagent spawn when GFI is critically high
|
|
169
|
+
if (AGENT_TOOLS.has(event.toolName)) {
|
|
170
|
+
if (currentGfi >= AGENT_SPAWN_GFI_THRESHOLD) {
|
|
171
|
+
logger?.warn?.(`[PD:GFI_GATE] Agent tool "${event.toolName}" blocked by GFI: ${currentGfi} >= ${AGENT_SPAWN_GFI_THRESHOLD}`);
|
|
172
|
+
return block(wctx, 'subagent-spawn', `疲劳指数过高,禁止派生子智能体。GFI: ${currentGfi}/${AGENT_SPAWN_GFI_THRESHOLD}`, event.toolName, sessionId, logger);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|