micro-models-agent 2.16.1 → 2.17.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/CHANGELOG.md +34 -0
- package/README.md +8 -3
- package/dist/assets/app.js +1 -314
- package/dist/assets/hljs.js +5 -1244
- package/dist/assets/index.html +11 -0
- package/dist/assets/js/api.js +1 -28
- package/dist/assets/js/core/menus.js +1 -0
- package/dist/assets/js/core/store/feed.js +1 -0
- package/dist/assets/js/core/store/index.js +1 -0
- package/dist/assets/js/core/store/session.js +1 -0
- package/dist/assets/js/core/store/settings.js +1 -0
- package/dist/assets/js/core/store/tabs.js +1 -0
- package/dist/assets/js/dialog.js +1 -105
- package/dist/assets/js/dom.js +1 -178
- package/dist/assets/js/feed/core.js +1 -0
- package/dist/assets/js/feed/history.js +1 -0
- package/dist/assets/js/feed/plan.js +1 -0
- package/dist/assets/js/feed/question.js +3 -0
- package/dist/assets/js/feed/sidebar.js +1 -0
- package/dist/assets/js/feed/stream.js +1 -0
- package/dist/assets/js/feed/turn.js +5 -0
- package/dist/assets/js/feed.js +1 -1250
- package/dist/assets/js/format.js +2 -122
- package/dist/assets/js/i18n.js +1 -46
- package/dist/assets/js/rail.js +1 -114
- package/dist/assets/js/session/cmdk.js +1 -0
- package/dist/assets/js/session/composer.js +1 -0
- package/dist/assets/js/session/sessions-menu.js +1 -0
- package/dist/assets/js/session/tabs.js +1 -0
- package/dist/assets/js/settings/controls.js +1 -0
- package/dist/assets/js/settings/editors.js +1 -0
- package/dist/assets/js/settings/form.js +1 -0
- package/dist/assets/js/settings/modal.js +1 -0
- package/dist/assets/js/settings/panels.js +1 -0
- package/dist/assets/js/settings/providers.js +1 -0
- package/dist/assets/js/settings/search.js +1 -0
- package/dist/assets/js/settings/subdialog.js +1 -0
- package/dist/assets/js/settings/write.js +1 -0
- package/dist/assets/js/settings.js +1 -1914
- package/dist/assets/js/sidebar/core.js +1 -0
- package/dist/assets/js/sidebar/lsp.js +2 -0
- package/dist/assets/js/sidebar/map.js +1 -0
- package/dist/assets/js/sidebar/state.js +1 -0
- package/dist/assets/js/sidebar/trace.js +5 -0
- package/dist/assets/js/sidebar.js +1 -705
- package/dist/assets/js/store.js +1 -82
- package/dist/assets/js/subdialog.js +1 -0
- package/dist/assets/md.js +1 -291
- package/dist/assets/setup.js +3 -816
- package/dist/assets/smd.js +29 -1665
- package/dist/assets/styles.css +1 -1598
- package/dist/certification/certifications.json +1 -494
- package/dist/i18n/en.json +1 -1851
- package/dist/i18n/ru.json +1 -1854
- package/dist/main.js +815 -55797
- package/dist/modules/browser/bridge-server.mjs +2 -252
- package/package.json +10 -5
- package/dist/assets/js/settings-controls.js +0 -452
- package/dist/assets/js/tabs.js +0 -867
- package/dist/cli/cache-line.js +0 -31
- package/dist/cli/command-suggest.js +0 -39
- package/dist/cli/commands.js +0 -781
- package/dist/cli/completer.js +0 -268
- package/dist/cli/index.js +0 -3
- package/dist/cli/json-payload.js +0 -32
- package/dist/cli/main.js +0 -346
- package/dist/cli/onboarding-commands.js +0 -126
- package/dist/cli/plugin-commands.js +0 -38
- package/dist/cli/relaunch.js +0 -40
- package/dist/cli/repl-commands-lsp.js +0 -75
- package/dist/cli/repl-commands-skills.js +0 -105
- package/dist/cli/repl-commands.js +0 -1218
- package/dist/cli/repl.js +0 -1238
- package/dist/cli/run-result.js +0 -38
- package/dist/cli/security-commands.js +0 -177
- package/dist/cli/setup-order.js +0 -6
- package/dist/cli/setup-prompt.js +0 -50
- package/dist/cli/setup.js +0 -161
- package/dist/cli/web-command.js +0 -98
- package/dist/config/budget.js +0 -48
- package/dist/config/config.js +0 -345
- package/dist/config/defaults.js +0 -197
- package/dist/config/domains.js +0 -135
- package/dist/config/env.js +0 -46
- package/dist/config/experts.js +0 -17
- package/dist/config/index.js +0 -5
- package/dist/config/paths.js +0 -56
- package/dist/config/redact.js +0 -44
- package/dist/config/registry-extra.js +0 -334
- package/dist/config/registry.js +0 -584
- package/dist/config/security.js +0 -212
- package/dist/config/timeouts.js +0 -74
- package/dist/config/types.js +0 -1
- package/dist/config/utils.js +0 -57
- package/dist/core/agent/artifact-progress.js +0 -59
- package/dist/core/agent/artifact-resolve.js +0 -79
- package/dist/core/agent/audit-gate.js +0 -53
- package/dist/core/agent/compaction.js +0 -89
- package/dist/core/agent/constants.js +0 -90
- package/dist/core/agent/context-log.js +0 -454
- package/dist/core/agent/context-renderer.js +0 -45
- package/dist/core/agent/critic-gate.js +0 -132
- package/dist/core/agent/hallucination-gate.js +0 -197
- package/dist/core/agent/loop-state.js +0 -68
- package/dist/core/agent/prefix-monitor.js +0 -101
- package/dist/core/agent/reasoning-resolver.js +0 -65
- package/dist/core/agent/token-tracker.js +0 -99
- package/dist/core/agent/tool-batch.js +0 -312
- package/dist/core/agent/tool-images.js +0 -18
- package/dist/core/agent/tool-output.js +0 -116
- package/dist/core/agent/tool-pairing.js +0 -60
- package/dist/core/agent-moe.js +0 -248
- package/dist/core/agent.js +0 -1299
- package/dist/core/bootstrap/agent-phase.js +0 -66
- package/dist/core/bootstrap/config-phase.js +0 -86
- package/dist/core/bootstrap/modules-phase.js +0 -269
- package/dist/core/bootstrap/provider-phase.js +0 -183
- package/dist/core/bootstrap/session-phase.js +0 -204
- package/dist/core/bootstrap/state.js +0 -94
- package/dist/core/bootstrap/workspace-phase.js +0 -115
- package/dist/core/bootstrap.js +0 -112
- package/dist/core/crash-handler.js +0 -62
- package/dist/core/environment.js +0 -224
- package/dist/core/host-plan.js +0 -43
- package/dist/core/host.js +0 -23
- package/dist/core/index.js +0 -3
- package/dist/core/prompt-builder.js +0 -95
- package/dist/core/prompt-overflow.js +0 -306
- package/dist/core/session-logger.js +0 -375
- package/dist/core/system-prompt.js +0 -117
- package/dist/core/types.js +0 -1
- package/dist/core/version.js +0 -28
- package/dist/core/web-host.js +0 -34
- package/dist/core/workspace.js +0 -80
- package/dist/i18n/index.js +0 -80
- package/dist/index.js +0 -30
- package/dist/llm/cache-usage.js +0 -76
- package/dist/llm/image-utils.js +0 -138
- package/dist/llm/index.js +0 -4
- package/dist/llm/llm-errors.js +0 -50
- package/dist/llm/model-loader.js +0 -86
- package/dist/llm/models-dev.js +0 -121
- package/dist/llm/openai-compat.js +0 -756
- package/dist/llm/orchestrator.js +0 -294
- package/dist/llm/provider-budget.js +0 -68
- package/dist/llm/provider-context.js +0 -233
- package/dist/llm/provider.js +0 -9
- package/dist/llm/response.js +0 -44
- package/dist/llm/stream-state.js +0 -26
- package/dist/llm/token-counter.js +0 -83
- package/dist/llm/types.js +0 -1
- package/dist/logger/app-logger.js +0 -212
- package/dist/logger/file-log.js +0 -160
- package/dist/logger/index.js +0 -2
- package/dist/migration/backup.js +0 -56
- package/dist/migration/detect.js +0 -61
- package/dist/migration/index.js +0 -3
- package/dist/modules/artifacts/store.js +0 -62
- package/dist/modules/browser/actions.js +0 -79
- package/dist/modules/browser/bridge-client.js +0 -203
- package/dist/modules/browser/bridge-path.js +0 -10
- package/dist/modules/browser/console-buffer.js +0 -37
- package/dist/modules/browser/cookie-store.js +0 -29
- package/dist/modules/browser/driver-types.js +0 -1
- package/dist/modules/browser/driver.js +0 -186
- package/dist/modules/browser/index.js +0 -9
- package/dist/modules/browser/module.js +0 -30
- package/dist/modules/browser/session.js +0 -322
- package/dist/modules/browser/snapshot.js +0 -154
- package/dist/modules/browser/types.js +0 -13
- package/dist/modules/certification/cli.js +0 -264
- package/dist/modules/certification/fact-checker.js +0 -90
- package/dist/modules/certification/loader.js +0 -127
- package/dist/modules/certification/manifest.js +0 -231
- package/dist/modules/certification/runner.js +0 -233
- package/dist/modules/certification/scenarios.js +0 -586
- package/dist/modules/certification/syntax-scenarios.js +0 -50
- package/dist/modules/certification/types.js +0 -1
- package/dist/modules/context/chunk-query.js +0 -122
- package/dist/modules/context/fact-extractor.js +0 -170
- package/dist/modules/context/history.js +0 -15
- package/dist/modules/context/index.js +0 -2
- package/dist/modules/context/manager.js +0 -482
- package/dist/modules/critic/client.js +0 -176
- package/dist/modules/critic/evidence.js +0 -81
- package/dist/modules/critic/provider.js +0 -45
- package/dist/modules/critic/tools.js +0 -78
- package/dist/modules/critic/types.js +0 -1
- package/dist/modules/execution/audit-runners.js +0 -206
- package/dist/modules/execution/auditor.js +0 -222
- package/dist/modules/execution/execution-plugin.js +0 -478
- package/dist/modules/execution/index.js +0 -8
- package/dist/modules/execution/input-from.js +0 -70
- package/dist/modules/execution/module.js +0 -891
- package/dist/modules/execution/moe-executor.js +0 -443
- package/dist/modules/execution/plan-actions.js +0 -642
- package/dist/modules/execution/plan-checks.js +0 -35
- package/dist/modules/execution/plan-coverage.js +0 -71
- package/dist/modules/execution/plan-persister.js +0 -46
- package/dist/modules/execution/plan-steps.js +0 -31
- package/dist/modules/execution/plan-store.js +0 -274
- package/dist/modules/execution/plan-tool.js +0 -249
- package/dist/modules/execution/plan-validator.js +0 -197
- package/dist/modules/execution/planner.js +0 -103
- package/dist/modules/execution/stuck-detector.js +0 -834
- package/dist/modules/execution/tracker.js +0 -92
- package/dist/modules/execution/transient-error.js +0 -30
- package/dist/modules/execution/types.js +0 -1
- package/dist/modules/execution/verifier.js +0 -343
- package/dist/modules/execution/windows-commands.js +0 -52
- package/dist/modules/hallucination/artifact-claim.js +0 -93
- package/dist/modules/hallucination/confidence.js +0 -81
- package/dist/modules/hallucination/consistency.js +0 -37
- package/dist/modules/hallucination/detector.js +0 -57
- package/dist/modules/hallucination/factual.js +0 -205
- package/dist/modules/hallucination/index.js +0 -6
- package/dist/modules/hallucination/js-identifiers.js +0 -261
- package/dist/modules/hallucination/llm-judge.js +0 -116
- package/dist/modules/hallucination/success-claim.js +0 -59
- package/dist/modules/index.js +0 -5
- package/dist/modules/indexer/cache.js +0 -88
- package/dist/modules/indexer/index.js +0 -4
- package/dist/modules/indexer/map-command.js +0 -33
- package/dist/modules/indexer/map-select.js +0 -87
- package/dist/modules/indexer/module.js +0 -293
- package/dist/modules/indexer/project-profile.js +0 -184
- package/dist/modules/indexer/symbols.js +0 -189
- package/dist/modules/indexer/walker.js +0 -285
- package/dist/modules/lsp/check-tool.js +0 -61
- package/dist/modules/lsp/client.js +0 -406
- package/dist/modules/lsp/command.js +0 -53
- package/dist/modules/lsp/config.js +0 -189
- package/dist/modules/lsp/index.js +0 -4
- package/dist/modules/lsp/module.js +0 -295
- package/dist/modules/lsp/probe.js +0 -86
- package/dist/modules/lsp/project-root.js +0 -69
- package/dist/modules/lsp/startup-check.js +0 -154
- package/dist/modules/lsp/types.js +0 -1
- package/dist/modules/mcp/client.js +0 -445
- package/dist/modules/mcp/index.js +0 -4
- package/dist/modules/mcp/module.js +0 -295
- package/dist/modules/mcp/registry.js +0 -20
- package/dist/modules/memory/index.js +0 -2
- package/dist/modules/memory/module.js +0 -101
- package/dist/modules/memory/search.js +0 -45
- package/dist/modules/memory/store.js +0 -107
- package/dist/modules/onboarding/init.js +0 -47
- package/dist/modules/onboarding/meet.js +0 -30
- package/dist/modules/onboarding/mode.js +0 -30
- package/dist/modules/onboarding/prompts.js +0 -43
- package/dist/modules/pipelines/engine.js +0 -70
- package/dist/modules/pipelines/index.js +0 -4
- package/dist/modules/pipelines/parser.js +0 -59
- package/dist/modules/pipelines/template.js +0 -18
- package/dist/modules/plugins/builtin/lint-on-write.js +0 -377
- package/dist/modules/plugins/builtin/notify.js +0 -11
- package/dist/modules/plugins/index.js +0 -2
- package/dist/modules/plugins/loader.js +0 -85
- package/dist/modules/plugins/manager.js +0 -244
- package/dist/modules/plugins/types.js +0 -1
- package/dist/modules/pricing/index.js +0 -70
- package/dist/modules/pricing/prices.js +0 -147
- package/dist/modules/processes/detect.js +0 -34
- package/dist/modules/processes/index.js +0 -4
- package/dist/modules/processes/kill-tree.js +0 -52
- package/dist/modules/processes/registry.js +0 -294
- package/dist/modules/processes/runner.js +0 -23
- package/dist/modules/providers/cache.js +0 -23
- package/dist/modules/providers/capabilities.js +0 -28
- package/dist/modules/providers/create.js +0 -21
- package/dist/modules/providers/factory.js +0 -28
- package/dist/modules/providers/fallback.js +0 -81
- package/dist/modules/providers/health.js +0 -47
- package/dist/modules/providers/index.js +0 -6
- package/dist/modules/providers/manager.js +0 -207
- package/dist/modules/providers/naming.js +0 -15
- package/dist/modules/providers/preflight.js +0 -71
- package/dist/modules/providers/presets.js +0 -232
- package/dist/modules/providers/registry.js +0 -27
- package/dist/modules/providers/types.js +0 -1
- package/dist/modules/reasoning/policy.js +0 -42
- package/dist/modules/reasoning/probe.js +0 -116
- package/dist/modules/registry.js +0 -48
- package/dist/modules/security/audit-log.js +0 -119
- package/dist/modules/security/audit-notifier.js +0 -267
- package/dist/modules/security/command-validator.js +0 -272
- package/dist/modules/security/content-scanner.js +0 -53
- package/dist/modules/security/data-sanitizer.js +0 -82
- package/dist/modules/security/encryption.js +0 -216
- package/dist/modules/security/index.js +0 -15
- package/dist/modules/security/network-validator.js +0 -236
- package/dist/modules/security/path-validator.js +0 -261
- package/dist/modules/security/protected-paths.js +0 -73
- package/dist/modules/security/rate-limiter.js +0 -98
- package/dist/modules/security/security-policies.js +0 -499
- package/dist/modules/security/session-encryption.js +0 -182
- package/dist/modules/security/session-isolation.js +0 -75
- package/dist/modules/session/auto-name.js +0 -63
- package/dist/modules/session/export.js +0 -98
- package/dist/modules/session/index.js +0 -4
- package/dist/modules/session/manager.js +0 -234
- package/dist/modules/session/module.js +0 -33
- package/dist/modules/session/store.js +0 -295
- package/dist/modules/session/types.js +0 -1
- package/dist/modules/setup/answers.js +0 -35
- package/dist/modules/setup/apply.js +0 -79
- package/dist/modules/setup/discovery.js +0 -72
- package/dist/modules/skills/index.js +0 -3
- package/dist/modules/skills/loader.js +0 -86
- package/dist/modules/skills/matcher.js +0 -27
- package/dist/modules/skills/module.js +0 -141
- package/dist/modules/types.js +0 -1
- package/dist/modules/updater/changelog-reader.js +0 -93
- package/dist/modules/updater/checker.js +0 -101
- package/dist/modules/updater/dev-detect.js +0 -18
- package/dist/modules/updater/index.js +0 -4
- package/dist/modules/updater/module.js +0 -129
- package/dist/modules/user-profile/compressor.js +0 -18
- package/dist/modules/user-profile/index.js +0 -2
- package/dist/modules/user-profile/profile.js +0 -77
- package/dist/modules/webui/answer-api.js +0 -29
- package/dist/modules/webui/assets.js +0 -50
- package/dist/modules/webui/body.js +0 -21
- package/dist/modules/webui/commands-settings.js +0 -209
- package/dist/modules/webui/commands-shared.js +0 -60
- package/dist/modules/webui/commands.js +0 -174
- package/dist/modules/webui/config-api.js +0 -134
- package/dist/modules/webui/file-api.js +0 -202
- package/dist/modules/webui/forward.js +0 -159
- package/dist/modules/webui/history-api.js +0 -112
- package/dist/modules/webui/host-state.js +0 -60
- package/dist/modules/webui/i18n-api.js +0 -9
- package/dist/modules/webui/limits.js +0 -6
- package/dist/modules/webui/log-forward.js +0 -20
- package/dist/modules/webui/memory-commands.js +0 -64
- package/dist/modules/webui/model-cache.js +0 -18
- package/dist/modules/webui/module.js +0 -148
- package/dist/modules/webui/persist.js +0 -24
- package/dist/modules/webui/prompt-io.js +0 -97
- package/dist/modules/webui/providers-api.js +0 -337
- package/dist/modules/webui/providers-view.js +0 -56
- package/dist/modules/webui/reasoning-view.js +0 -15
- package/dist/modules/webui/run-agent.js +0 -81
- package/dist/modules/webui/server.js +0 -284
- package/dist/modules/webui/sessions-api.js +0 -178
- package/dist/modules/webui/settings-api.js +0 -561
- package/dist/modules/webui/setup-api.js +0 -201
- package/dist/modules/webui/state.js +0 -74
- package/dist/modules/webui/util.js +0 -261
- package/dist/output/bus.js +0 -37
- package/dist/output/channel.js +0 -285
- package/dist/output/format.js +0 -15
- package/dist/output/index.js +0 -8
- package/dist/output/json-sink.js +0 -24
- package/dist/output/machine.js +0 -9
- package/dist/output/session-sink.js +0 -27
- package/dist/output/types.js +0 -1
- package/dist/tools/approve.js +0 -41
- package/dist/tools/attach-image.js +0 -102
- package/dist/tools/auto-fixer.js +0 -180
- package/dist/tools/auto-tags.js +0 -83
- package/dist/tools/bash.js +0 -649
- package/dist/tools/browser.js +0 -160
- package/dist/tools/chunk-query.js +0 -112
- package/dist/tools/create-dir.js +0 -60
- package/dist/tools/delete-file.js +0 -67
- package/dist/tools/download-file.js +0 -142
- package/dist/tools/edit-file.js +0 -136
- package/dist/tools/enable-tools.js +0 -59
- package/dist/tools/executor.js +0 -304
- package/dist/tools/file-info.js +0 -49
- package/dist/tools/filter-tools.js +0 -17
- package/dist/tools/glob-tool.js +0 -37
- package/dist/tools/grep-tool.js +0 -142
- package/dist/tools/hidden-tools-block.js +0 -37
- package/dist/tools/index.js +0 -88
- package/dist/tools/list-dir.js +0 -53
- package/dist/tools/load-skill.js +0 -51
- package/dist/tools/mcp-call.js +0 -80
- package/dist/tools/meet-done.js +0 -14
- package/dist/tools/move-file.js +0 -94
- package/dist/tools/path-utils.js +0 -108
- package/dist/tools/pipeline-run.js +0 -167
- package/dist/tools/preview.js +0 -2
- package/dist/tools/process-ids.js +0 -31
- package/dist/tools/process-kill.js +0 -33
- package/dist/tools/process-list.js +0 -38
- package/dist/tools/process-log.js +0 -49
- package/dist/tools/process-wait.js +0 -63
- package/dist/tools/prompt-io.js +0 -29
- package/dist/tools/question.js +0 -288
- package/dist/tools/read-file.js +0 -200
- package/dist/tools/recall.js +0 -124
- package/dist/tools/registry.js +0 -48
- package/dist/tools/remember.js +0 -72
- package/dist/tools/scope-check.js +0 -32
- package/dist/tools/scope-request.js +0 -96
- package/dist/tools/search-history.js +0 -88
- package/dist/tools/session-info.js +0 -46
- package/dist/tools/set-thinking.js +0 -75
- package/dist/tools/subagent.js +0 -257
- package/dist/tools/syntax-validator.js +0 -379
- package/dist/tools/types.js +0 -1
- package/dist/tools/user-input.js +0 -134
- package/dist/tools/web-browse.js +0 -93
- package/dist/tools/web-fetch.js +0 -108
- package/dist/tools/web-search.js +0 -107
- package/dist/tools/write-file.js +0 -128
- package/dist/ui/action-log.js +0 -13
- package/dist/ui/box.js +0 -78
- package/dist/ui/colors.js +0 -6
- package/dist/ui/diff.js +0 -189
- package/dist/ui/index.js +0 -7
- package/dist/ui/line-editor.js +0 -1083
- package/dist/ui/line-math.js +0 -98
- package/dist/ui/md-formatter.js +0 -322
- package/dist/ui/output.js +0 -19
- package/dist/ui/plan-view.js +0 -109
- package/dist/ui/renderer.js +0 -589
- package/dist/ui/spinner.js +0 -91
- package/dist/ui/table.js +0 -142
- package/dist/ui/theme.js +0 -143
- package/dist/utils/child-run.js +0 -20
- package/dist/utils/error.js +0 -4
- package/dist/utils/index.js +0 -6
- package/dist/utils/retry.js +0 -17
- package/dist/utils/sleep.js +0 -23
- package/dist/utils/truncate.js +0 -9
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// Сборка пакета доказательств для критика: дайджест тулов, файлы, команды.
|
|
2
|
-
import { readFileSync } from "fs";
|
|
3
|
-
import { resolve } from "path";
|
|
4
|
-
import { summarizeToolArgs } from "../../core/agent/tool-output";
|
|
5
|
-
const MUTATING_TOOLS = new Set(["write_file", "edit_file", "delete_file", "move_file", "create_dir"]);
|
|
6
|
-
/** Мутация работы = тул, меняющий ФС (bash входит; plan/todo-бухгалтерия — нет). */
|
|
7
|
-
export function isWorkMutation(name) {
|
|
8
|
-
return MUTATING_TOOLS.has(name) || name === "bash";
|
|
9
|
-
}
|
|
10
|
-
const MAX_DIGEST_LINES = 40;
|
|
11
|
-
/** Хвост вывода, прикладываемый к bash/фейловым строкам дайджеста (результаты тестов/сборки — сигнал верификации). */
|
|
12
|
-
const MAX_DIGEST_OUTPUT_CHARS = 300;
|
|
13
|
-
const MAX_EXCERPT_FILES = 5;
|
|
14
|
-
const MAX_EXCERPT_CHARS = 1200;
|
|
15
|
-
/** Собирает EvidencePack из событий тулов: дайджест, файлы, команды, выдержки. */
|
|
16
|
-
export function buildEvidencePack(input) {
|
|
17
|
-
const changedFiles = new Set();
|
|
18
|
-
const commands = [];
|
|
19
|
-
const digest = [];
|
|
20
|
-
for (const ev of input.toolEvents) {
|
|
21
|
-
digest.push(digestLine(ev));
|
|
22
|
-
const file = changedFileOf(ev);
|
|
23
|
-
if (file)
|
|
24
|
-
changedFiles.add(file);
|
|
25
|
-
const cmd = commandOf(ev);
|
|
26
|
-
if (cmd)
|
|
27
|
-
commands.push(cmd);
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
task: input.task,
|
|
31
|
-
planSummary: input.planSummary,
|
|
32
|
-
changedFiles: [...changedFiles],
|
|
33
|
-
commands,
|
|
34
|
-
toolDigest: digest.slice(-MAX_DIGEST_LINES).join("\n"),
|
|
35
|
-
fileExcerpts: input.baseDir ? readExcerpts(input.baseDir, [...changedFiles]) : undefined,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/** Одна строка дайджеста на событие. Вывод bash (результаты тестов/сборки) и вывод
|
|
39
|
-
* ошибок идут вместе со строкой — иначе критик судит об успехе вслепую. */
|
|
40
|
-
function digestLine(ev) {
|
|
41
|
-
const args = ev.args ? summarizeToolArgs(ev.args) : "";
|
|
42
|
-
const line = `${ev.ok === false ? "✗" : "✓"} ${ev.tool} ${args}`.trim();
|
|
43
|
-
if (ev.output && (ev.tool === "bash" || ev.ok === false)) {
|
|
44
|
-
return `${line} » ${ev.output.slice(-MAX_DIGEST_OUTPUT_CHARS)}`;
|
|
45
|
-
}
|
|
46
|
-
return line;
|
|
47
|
-
}
|
|
48
|
-
/** Относительный путь файла, затронутого событием write/edit. */
|
|
49
|
-
function changedFileOf(ev) {
|
|
50
|
-
if (ev.tool !== "write_file" && ev.tool !== "edit_file")
|
|
51
|
-
return undefined;
|
|
52
|
-
return typeof ev.args?.path === "string" ? ev.args.path : undefined;
|
|
53
|
-
}
|
|
54
|
-
/** Событие bash как запись команды, видимая критику (с ограниченным хвостом вывода). */
|
|
55
|
-
function commandOf(ev) {
|
|
56
|
-
if (ev.tool !== "bash" || typeof ev.args?.command !== "string")
|
|
57
|
-
return undefined;
|
|
58
|
-
return {
|
|
59
|
-
command: ev.args.command,
|
|
60
|
-
exitCode: ev.ok === false ? 1 : 0,
|
|
61
|
-
output: ev.output?.slice(-MAX_DIGEST_OUTPUT_CHARS),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
/** Best-effort ограниченные head-выдержки изменённых файлов. Нечитаемые (удалены, бинарные, вне root) — пропуск, никогда не бросает. */
|
|
65
|
-
function readExcerpts(baseDir, paths) {
|
|
66
|
-
const out = [];
|
|
67
|
-
const root = resolve(baseDir);
|
|
68
|
-
for (const p of paths.slice(0, MAX_EXCERPT_FILES)) {
|
|
69
|
-
try {
|
|
70
|
-
const abs = resolve(root, p);
|
|
71
|
-
if (abs !== root && !abs.startsWith(`${root}/`) && !abs.startsWith(`${root}\\`))
|
|
72
|
-
continue;
|
|
73
|
-
const text = readFileSync(abs, "utf-8");
|
|
74
|
-
out.push({ path: p, excerpt: text.slice(0, MAX_EXCERPT_CHARS) });
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
// Нечитаемый (удалён, бинарный, вне root) — молча пропускаем.
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return out;
|
|
81
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ProviderManager } from "../providers/manager";
|
|
2
|
-
import { FallbackProvider } from "../providers/fallback";
|
|
3
|
-
const DEFAULT_CRITIC_BASE_URL = "http://localhost:1234/v1";
|
|
4
|
-
/** Окно контекста, если ни запись провайдера, ни конфиг его не задали. */
|
|
5
|
-
const DEFAULT_CRITIC_CONTEXT_WINDOW = 32768;
|
|
6
|
-
/**
|
|
7
|
-
* Резолвит LLM для критика (Phase 2). Зеркалит OrchestratorClient:
|
|
8
|
-
* управляемый провайдер строится через ProviderManager (per-entry
|
|
9
|
-
* contextWindow/retry/rateLimits, failover) ТОЛЬКО если задан `critic.model`;
|
|
10
|
-
* иначе критик делит активный провайдер (поведение v1). `critic.provider`
|
|
11
|
-
* без модели сохраняет поведение v1.
|
|
12
|
-
*
|
|
13
|
-
* Fail-open: битый оверрайд предупреждает и откатывается к активному
|
|
14
|
-
* провайдеру — неверно настроенный критик не должен молча отключать проверку.
|
|
15
|
-
*/
|
|
16
|
-
export function buildCriticProvider(critic, config, defaultProvider, deps) {
|
|
17
|
-
const model = critic?.model?.trim();
|
|
18
|
-
if (!model)
|
|
19
|
-
return defaultProvider;
|
|
20
|
-
try {
|
|
21
|
-
const providerCfg = critic?.provider ?? {
|
|
22
|
-
type: "openai-compat",
|
|
23
|
-
baseUrl: DEFAULT_CRITIC_BASE_URL,
|
|
24
|
-
};
|
|
25
|
-
const manager = new ProviderManager({ ...providerCfg, baseUrl: providerCfg.baseUrl || DEFAULT_CRITIC_BASE_URL }, {
|
|
26
|
-
contextWindow: config.contextWindow ?? DEFAULT_CRITIC_CONTEXT_WINDOW,
|
|
27
|
-
retry: config.retry,
|
|
28
|
-
rateLimits: config.security?.rateLimits,
|
|
29
|
-
getSessionId: deps?.getSessionId,
|
|
30
|
-
logger: deps?.logger,
|
|
31
|
-
});
|
|
32
|
-
manager.setModel(model);
|
|
33
|
-
let provider = manager.active;
|
|
34
|
-
if (providerCfg.fallback && manager.listNames().length > 1) {
|
|
35
|
-
provider = new FallbackProvider(manager, (from, to, error) => {
|
|
36
|
-
deps?.logger?.warn(`critic provider failover: ${from} -> ${to} (${error.message.slice(0, 120)})`);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
return provider;
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
deps?.logger?.warn(`critic provider override failed, using active provider: ${String(err?.message ?? err).slice(0, 160)}`);
|
|
43
|
-
return defaultProvider;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ограниченный read-only контур верификации (Phase 2, Agent-as-a-Judge).
|
|
3
|
-
*
|
|
4
|
-
* После вердикта concern/critical критик может запросить конкретные файловые
|
|
5
|
-
* проверки, чтобы подтвердить/опровергнуть проблему, а не судить вслепую.
|
|
6
|
-
* Доступны только read-only тулы — записи, shell, web и память исключены,
|
|
7
|
-
* так что скомпрометированный/запутавшийся критик ничего не мутирует. Цикл
|
|
8
|
-
* ограничен (доп. LLM-вызовы + проверки делят verify-таймаут), при сбое —
|
|
9
|
-
* откат к вердикту первого прохода.
|
|
10
|
-
*/
|
|
11
|
-
/** Read-only тулы, доступные критику. Записи/shell/web/память исключены by design. */
|
|
12
|
-
export const CRITIC_READONLY_TOOLS = ["read_file", "grep", "glob", "file_info", "list_dir"];
|
|
13
|
-
/** Жёсткий кап проверок на вердикт (внутренний дефолт, не конфиг — спек §4.3). */
|
|
14
|
-
export const MAX_CRITIC_CHECKS = 3;
|
|
15
|
-
/** Символов вывода на проверку, возвращаемых критику (ограничено — у verify-вызова свой бюджет). */
|
|
16
|
-
export const MAX_CHECK_OUTPUT_CHARS = 1500;
|
|
17
|
-
/** True, если тул разрешён критику (входит в read-only allowlist). */
|
|
18
|
-
export function isAllowedCriticTool(tool) {
|
|
19
|
-
return CRITIC_READONLY_TOOLS.includes(tool);
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Проверки из вердикта критика (сырой массив `checks`, allowlist + кап).
|
|
23
|
-
* Чужое — неизвестные тулы, не-объектные args — молча дропается:
|
|
24
|
-
* критик теряет только глубину верификации, не корректность.
|
|
25
|
-
*/
|
|
26
|
-
export function parseChecks(verdict) {
|
|
27
|
-
if (!verdict?.checks || !Array.isArray(verdict.checks))
|
|
28
|
-
return [];
|
|
29
|
-
const out = [];
|
|
30
|
-
for (const c of verdict.checks) {
|
|
31
|
-
if (out.length >= MAX_CRITIC_CHECKS)
|
|
32
|
-
break;
|
|
33
|
-
const check = asCriticCheck(c);
|
|
34
|
-
if (check)
|
|
35
|
-
out.push(check);
|
|
36
|
-
}
|
|
37
|
-
return out;
|
|
38
|
-
}
|
|
39
|
-
/** Одна сырая запись → валидированная проверка, или null, если непригодна/запрещена. */
|
|
40
|
-
function asCriticCheck(c) {
|
|
41
|
-
if (!c || typeof c !== "object")
|
|
42
|
-
return null;
|
|
43
|
-
const rec = c;
|
|
44
|
-
if (typeof rec.tool !== "string" || !isAllowedCriticTool(rec.tool))
|
|
45
|
-
return null;
|
|
46
|
-
if (!rec.args || typeof rec.args !== "object" || Array.isArray(rec.args))
|
|
47
|
-
return null;
|
|
48
|
-
return { tool: rec.tool, args: rec.args };
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Выполняет валидированные проверки через инжектированный раннер (в Agent —
|
|
52
|
-
* ToolExecutor с read-only allowlist). Последовательно, никогда параллельно
|
|
53
|
-
* с вызовами тулов главного цикла. Сбой одной проверки даёт failure-результат,
|
|
54
|
-
* остальные проверки не прерываются.
|
|
55
|
-
*/
|
|
56
|
-
export async function runCriticChecks(checks, runCheck) {
|
|
57
|
-
const out = [];
|
|
58
|
-
for (const c of checks.slice(0, MAX_CRITIC_CHECKS)) {
|
|
59
|
-
try {
|
|
60
|
-
const r = await runCheck(c.tool, c.args);
|
|
61
|
-
out.push({ tool: c.tool, ok: r.ok, output: (r.output ?? "").slice(0, MAX_CHECK_OUTPUT_CHARS) });
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
out.push({
|
|
65
|
-
tool: c.tool,
|
|
66
|
-
ok: false,
|
|
67
|
-
output: `check failed: ${String(err?.message ?? err).slice(0, 200)}`,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return out;
|
|
72
|
-
}
|
|
73
|
-
/** Рендерит результаты проверок строками доказательств, видимых критику. */
|
|
74
|
-
export function renderCheckResults(results) {
|
|
75
|
-
return results
|
|
76
|
-
.map((r) => `${r.ok ? "✓" : "✗"} ${r.tool} » ${r.output}`)
|
|
77
|
-
.join("\n");
|
|
78
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
// Раннеры финального аудита: поиск тестов, прогон тестов, поиск корня typecheck.
|
|
2
|
-
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
3
|
-
import { dirname, join, resolve } from "path";
|
|
4
|
-
import { detectTestResults } from "../../tools/bash";
|
|
5
|
-
import { processRegistry } from "../processes";
|
|
6
|
-
import { resolveTscCommand } from "../lsp/project-root";
|
|
7
|
-
/** Каталоги, где тестовые файлы не ищем. */
|
|
8
|
-
export const SKIP_DIRS = new Set([
|
|
9
|
-
"node_modules",
|
|
10
|
-
".git",
|
|
11
|
-
".mma",
|
|
12
|
-
"dist",
|
|
13
|
-
"build",
|
|
14
|
-
"coverage",
|
|
15
|
-
".next",
|
|
16
|
-
".nuxt",
|
|
17
|
-
"vendor",
|
|
18
|
-
]);
|
|
19
|
-
const TEST_EXT_RE = /\.(test|spec)\.[jt]sx?$/i;
|
|
20
|
-
const PY_TEST_RE = /^test_.*\.py$|^.*_test\.py$/i;
|
|
21
|
-
/**
|
|
22
|
-
* Резолвит тестовую команду проекта из манифеста: финальный аудит реально
|
|
23
|
-
* гоняет раннер проекта, а не всегда `bun test` (Python/Go-проект или
|
|
24
|
-
* vitest/jest-сетап под bun test упал бы или молча не дал сводки).
|
|
25
|
-
*
|
|
26
|
-
* Приоритет: package.json scripts.test → конфиги тест-фреймворков → Python-
|
|
27
|
-
* маркеры (pyproject/pytest.ini/conftest.py) → go.mod → Cargo.toml → bun.
|
|
28
|
-
*/
|
|
29
|
-
export function resolveTestCommand(dir) {
|
|
30
|
-
const pkgPath = join(dir, "package.json");
|
|
31
|
-
if (existsSync(pkgPath)) {
|
|
32
|
-
try {
|
|
33
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
34
|
-
const script = pkg?.scripts?.test;
|
|
35
|
-
if (typeof script === "string" && script.trim())
|
|
36
|
-
return script.trim();
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
/* битый package.json — идём дальше */
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
for (const f of [
|
|
43
|
-
"vitest.config.ts",
|
|
44
|
-
"vitest.config.js",
|
|
45
|
-
"vitest.config.mjs",
|
|
46
|
-
"jest.config.js",
|
|
47
|
-
"jest.config.ts",
|
|
48
|
-
"jest.config.mjs",
|
|
49
|
-
"jest.config.cjs",
|
|
50
|
-
"bunfig.toml",
|
|
51
|
-
]) {
|
|
52
|
-
if (existsSync(join(dir, f))) {
|
|
53
|
-
if (f.startsWith("vitest"))
|
|
54
|
-
return "bunx vitest run";
|
|
55
|
-
if (f.startsWith("jest"))
|
|
56
|
-
return "npx --no-install jest";
|
|
57
|
-
if (f === "bunfig.toml")
|
|
58
|
-
return "bun test";
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (existsSync(join(dir, "pyproject.toml")) ||
|
|
62
|
-
existsSync(join(dir, "pytest.ini")) ||
|
|
63
|
-
existsSync(join(dir, "conftest.py"))) {
|
|
64
|
-
return "python -m pytest -q";
|
|
65
|
-
}
|
|
66
|
-
if (existsSync(join(dir, "go.mod")))
|
|
67
|
-
return "go test ./...";
|
|
68
|
-
if (existsSync(join(dir, "Cargo.toml")))
|
|
69
|
-
return "cargo test";
|
|
70
|
-
return "bun test";
|
|
71
|
-
}
|
|
72
|
-
/** Рекурсивный поиск тестового файла с капом глубины и ранним выходом. */
|
|
73
|
-
export function findTestFile(dir, depth = 0) {
|
|
74
|
-
if (depth > 5)
|
|
75
|
-
return null;
|
|
76
|
-
let entries;
|
|
77
|
-
try {
|
|
78
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
for (const e of entries) {
|
|
84
|
-
const full = join(dir, e.name);
|
|
85
|
-
if (e.isDirectory()) {
|
|
86
|
-
if (SKIP_DIRS.has(e.name))
|
|
87
|
-
continue;
|
|
88
|
-
const found = findTestFile(full, depth + 1);
|
|
89
|
-
if (found)
|
|
90
|
-
return found;
|
|
91
|
-
}
|
|
92
|
-
else if (TEST_EXT_RE.test(e.name) || PY_TEST_RE.test(e.name)) {
|
|
93
|
-
return full;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
/** Вытаскивает имена упавших тестов из вывода раннера (стиль bun/vitest). */
|
|
99
|
-
function extractFailingNames(output, limit = 5) {
|
|
100
|
-
const names = [];
|
|
101
|
-
for (const m of output.matchAll(/\(fail\)\s*([^\n]+)/g)) {
|
|
102
|
-
const name = m[1].trim();
|
|
103
|
-
if (name && !names.includes(name))
|
|
104
|
-
names.push(name);
|
|
105
|
-
if (names.length >= limit)
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
return names;
|
|
109
|
-
}
|
|
110
|
-
/** Прогоняет тесты проекта (90s) и разбирает сводку раннера. Таймаут — inconclusive. */
|
|
111
|
-
export async function runTests(baseDir) {
|
|
112
|
-
const command = resolveTestCommand(baseDir);
|
|
113
|
-
const entry = processRegistry.start(command, baseDir);
|
|
114
|
-
const exited = await processRegistry.waitForExit(entry.id, 90_000);
|
|
115
|
-
const output = entry.log.join("\n");
|
|
116
|
-
processRegistry.remove(entry.id);
|
|
117
|
-
if (!exited) {
|
|
118
|
-
// Таймаут — успех/фейл незавершённого прогона утверждать не можем.
|
|
119
|
-
return {
|
|
120
|
-
checked: true,
|
|
121
|
-
passed: true, // don't block completion on an inconclusive run
|
|
122
|
-
failed: 0,
|
|
123
|
-
passedCount: 0,
|
|
124
|
-
detail: `test run timed out after 90s — result unknown`,
|
|
125
|
-
command,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
const run = detectTestResults(output);
|
|
129
|
-
if (!run) {
|
|
130
|
-
// Нет узнаваемой сводки раннера. Ненулевой exit — прогон (или раннер) упал:
|
|
131
|
-
// аудит его пропускать не должен; репортим "как минимум один фейл", т.к.
|
|
132
|
-
// посчитать не можем. Exit 0 с неузнанным выводом — checked, но inconclusive.
|
|
133
|
-
return {
|
|
134
|
-
checked: true,
|
|
135
|
-
passed: entry.exitCode === 0,
|
|
136
|
-
failed: entry.exitCode === 0 ? 0 : 1,
|
|
137
|
-
passedCount: 0,
|
|
138
|
-
detail: output.slice(0, 200).trim(),
|
|
139
|
-
command,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
const names = extractFailingNames(output);
|
|
143
|
-
return {
|
|
144
|
-
checked: true,
|
|
145
|
-
passed: run.failed === 0,
|
|
146
|
-
failed: run.failed,
|
|
147
|
-
passedCount: run.passed,
|
|
148
|
-
detail: names.length
|
|
149
|
-
? names.join("; ")
|
|
150
|
-
: run.summary || `${run.failed} failed / ${run.passed} passed`,
|
|
151
|
-
command,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
/** Первая строка `error TS…` из вывода tsc, или null если нет/inconclusive. */
|
|
155
|
-
export function parseTypecheckErrors(output) {
|
|
156
|
-
const line = output.split("\n").find((l) => /error TS\d+/.test(l));
|
|
157
|
-
return line ? line.trim().slice(0, 300) : null;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Находит ближайший корень проекта с tsconfig.json.
|
|
161
|
-
*
|
|
162
|
-
* Агент часто создаёт проект во вложенной папке baseDir (напр. `bicycle-shop/`),
|
|
163
|
-
* и tsconfig лежит в `baseDir/bicycle-shop/`; старый гейт `existsSync(baseDir/tsconfig.json)`
|
|
164
|
-
* молча скипал финальный typecheck — аудит проходил при десятках tsc-ошибок
|
|
165
|
-
* (было в обеих разобранных сессиях). Обходит каждого кандидата (baseDir плюс
|
|
166
|
-
* резолвленные файлы шагов) вверх до ближайшего tsconfig.json, предпочитая
|
|
167
|
-
* мельчайшее попадание (проект baseDir бьёт шальной tsconfig выше). Null, если
|
|
168
|
-
* tsconfig недостижим. `existingFiles` — резолвленные абсолютные пути
|
|
169
|
-
* (относительные токены резолвились бы от cwd процесса, не от baseDir).
|
|
170
|
-
*/
|
|
171
|
-
export function findTypecheckRoot(baseDir, existingFiles = []) {
|
|
172
|
-
const candidates = [baseDir, ...existingFiles];
|
|
173
|
-
let best = null;
|
|
174
|
-
for (const start of candidates) {
|
|
175
|
-
let dir = resolve(start);
|
|
176
|
-
for (let depth = 0; depth <= 10; depth++) {
|
|
177
|
-
if (existsSync(join(dir, "tsconfig.json"))) {
|
|
178
|
-
if (!best || depth < best.depth)
|
|
179
|
-
best = { depth, root: dir };
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
const parent = dirname(dir);
|
|
183
|
-
if (parent === dir)
|
|
184
|
-
break;
|
|
185
|
-
dir = parent;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return best?.root ?? null;
|
|
189
|
-
}
|
|
190
|
-
/** Прогоняет `tsc --noEmit --skipLibCheck` (90s). Null, если проверить нельзя/таймаут. */
|
|
191
|
-
export async function runTypecheck(baseDir) {
|
|
192
|
-
// Локальный tsc напрямую: npx-обёртка добавляет секунды и без локального
|
|
193
|
-
// пакета уходит в сеть. Нет tsc — проверка невозможна, не блокируем.
|
|
194
|
-
const tsc = resolveTscCommand(baseDir);
|
|
195
|
-
if (!tsc)
|
|
196
|
-
return null;
|
|
197
|
-
const entry = processRegistry.start(`${tsc} --noEmit --skipLibCheck`, baseDir);
|
|
198
|
-
const exited = await processRegistry.waitForExit(entry.id, 90_000);
|
|
199
|
-
const output = entry.log.join("\n");
|
|
200
|
-
processRegistry.remove(entry.id);
|
|
201
|
-
// Таймаут или вывод без строк `error TS` (нет typescript / не та рабочая
|
|
202
|
-
// папка) — inconclusive, завершение на этом не блокируем.
|
|
203
|
-
if (!exited)
|
|
204
|
-
return null;
|
|
205
|
-
return parseTypecheckErrors(output);
|
|
206
|
-
}
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
// Финальный аудитор: файлы done-шагов, тесты, typecheck, сводка честности.
|
|
2
|
-
import { existsSync, readdirSync } from "fs";
|
|
3
|
-
import { resolve, join, basename } from "path";
|
|
4
|
-
import { t } from "../../i18n/index";
|
|
5
|
-
import { extractFileLikeTokens, stripUrls } from "../hallucination/js-identifiers";
|
|
6
|
-
import { toForwardSlash } from "../../tools/path-utils";
|
|
7
|
-
import { SKIP_DIRS, findTestFile, findTypecheckRoot, runTests, runTypecheck, } from "./audit-runners";
|
|
8
|
-
export { parseTypecheckErrors } from "./audit-runners";
|
|
9
|
-
const MASS_EDIT_THRESHOLD = 10;
|
|
10
|
-
/** Кап глубины обхода поддерева для резолва файлов. */
|
|
11
|
-
const RESOLVE_MAX_DEPTH = 8;
|
|
12
|
-
/**
|
|
13
|
-
* Резолвит файловый токен шага плана в существующий файл.
|
|
14
|
-
*
|
|
15
|
-
* Описание шага часто называет файл голым basename ("App.tsx") или частично
|
|
16
|
-
* префиксным путём ("src/App.tsx"), а реальный файл лежит во вложенной папке
|
|
17
|
-
* проекта относительно baseDir агента (напр. `bicycle-shop/src/App.tsx`).
|
|
18
|
-
* Наивный резолв от baseDir репортит файл пропавшим — было в ses_mssl5izw:
|
|
19
|
-
* финальный audit-gate вечно реджектил полностью готовую задачу с "1 files
|
|
20
|
-
* missing", загоняя модель в read/retry-петлю.
|
|
21
|
-
*
|
|
22
|
-
* Стратегия: сначала точный резолв, затем ограниченный обход поддерева с
|
|
23
|
-
* матчем точного basename или суффикса пути ("App.tsx" и "src/App.tsx"
|
|
24
|
-
* находят "bicycle-shop/src/App.tsx").
|
|
25
|
-
*/
|
|
26
|
-
export function findExistingFile(baseDir, filePath) {
|
|
27
|
-
const direct = resolve(baseDir, filePath);
|
|
28
|
-
if (existsSync(direct))
|
|
29
|
-
return direct;
|
|
30
|
-
const name = basename(filePath).toLowerCase();
|
|
31
|
-
const suffix = toForwardSlash(filePath).toLowerCase();
|
|
32
|
-
let found = null;
|
|
33
|
-
const walk = (dir, depth) => {
|
|
34
|
-
if (found || depth > RESOLVE_MAX_DEPTH)
|
|
35
|
-
return;
|
|
36
|
-
let entries;
|
|
37
|
-
try {
|
|
38
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
for (const e of entries) {
|
|
44
|
-
if (found)
|
|
45
|
-
return;
|
|
46
|
-
const full = join(dir, e.name);
|
|
47
|
-
if (e.isDirectory()) {
|
|
48
|
-
if (SKIP_DIRS.has(e.name))
|
|
49
|
-
continue;
|
|
50
|
-
walk(full, depth + 1);
|
|
51
|
-
}
|
|
52
|
-
else if (e.name.toLowerCase() === name ||
|
|
53
|
-
toForwardSlash(full)
|
|
54
|
-
.toLowerCase()
|
|
55
|
-
.endsWith(`/${suffix}`)) {
|
|
56
|
-
found = full;
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
walk(baseDir, 0);
|
|
62
|
-
return found;
|
|
63
|
-
}
|
|
64
|
-
/** Аудитор: проверяет done-шаги плана — файлы, тесты, typecheck. */
|
|
65
|
-
export class Auditor {
|
|
66
|
-
baseDir;
|
|
67
|
-
constructor(baseDir) {
|
|
68
|
-
this.baseDir = baseDir;
|
|
69
|
-
}
|
|
70
|
-
/** Аудитит план: файлы done-шагов, реальный прогон тестов, typecheck, сводка. */
|
|
71
|
-
async audit(plan) {
|
|
72
|
-
// Существования требуем только с файлов шагов, которые модель заявила
|
|
73
|
-
// готовыми. Скипнутые/пендинг шаги в "missing files" вклада не дают
|
|
74
|
-
// (было: проза скипнутого шага с "type.ts" вечно реджектила готовую
|
|
75
|
-
// задачу гейтом с "1 files missing").
|
|
76
|
-
const doneCreate = plan.steps.filter((s) => s.status === "done" && s.kind !== "delete");
|
|
77
|
-
const doneDelete = plan.steps.filter((s) => s.status === "done" && s.kind === "delete");
|
|
78
|
-
const createText = doneCreate.map((s) => s.description.replace(/\([^)]*\)/g, " ")).join(" ");
|
|
79
|
-
const deleteText = doneDelete.map((s) => s.description.replace(/\([^)]*\)/g, " ")).join(" ");
|
|
80
|
-
// Токены файлов извлекаем ТЕМ ЖЕ общим фильтром, что фактическая проверка
|
|
81
|
-
// галлюцинаций (js-identifiers.ts). URL вырезаем заранее, чтобы hostname /
|
|
82
|
-
// https://host/repo.git в описании шага не репортился пропавшим файлом
|
|
83
|
-
// (было: git-remote план флаговал `whom-pointing-jewel-maine.trycloudflare.com`).
|
|
84
|
-
const createFiles = extractFileLikeTokens(stripUrls(createText));
|
|
85
|
-
const deleteFiles = extractFileLikeTokens(stripUrls(deleteText));
|
|
86
|
-
const missingFiles = [];
|
|
87
|
-
const existingFiles = [];
|
|
88
|
-
const leftoverFiles = [];
|
|
89
|
-
for (const filePath of createFiles) {
|
|
90
|
-
const resolved = findExistingFile(this.baseDir, filePath);
|
|
91
|
-
if (resolved) {
|
|
92
|
-
// Храним резолвленный абсолютный путь: findTypecheckRoot идёт от него
|
|
93
|
-
// вверх к ближайшему tsconfig, а относительный токен резолвился бы
|
|
94
|
-
// от cwd процесса вместо baseDir.
|
|
95
|
-
existingFiles.push(resolved);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
missingFiles.push(filePath);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// Done-шаг kind=delete требует ОТСУТСТВИЯ именованных файлов.
|
|
102
|
-
for (const filePath of deleteFiles) {
|
|
103
|
-
if (findExistingFile(this.baseDir, filePath)) {
|
|
104
|
-
leftoverFiles.push(filePath);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
// Реальный прогон тестов: слову модели (и exit-кодам) не верим — реально
|
|
108
|
-
// исполняем тесты и смотрим сводку раннера. Ловит финальные "all 7
|
|
109
|
-
// passing ✅", прячущие 3 упавших.
|
|
110
|
-
//
|
|
111
|
-
// Решение EVIDENCE-based (тестовый файл есть на диске), не классификация
|
|
112
|
-
// прозы шагов по ключевым словам: правило #10 запрещает выводить требования
|
|
113
|
-
// из слов "test"/"тест" (план с тестами, но без такого слова, скипал аудит;
|
|
114
|
-
// постороннее "testing" форсило 90s-прогон).
|
|
115
|
-
let testRun = null;
|
|
116
|
-
if (findTestFile(this.baseDir)) {
|
|
117
|
-
try {
|
|
118
|
-
testRun = await runTests(this.baseDir);
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
testRun = null; // сбой инфры — на нём не блокируемся
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
// Реальный typecheck: аудит ловит "сборка сломана", даже если все файлы на
|
|
125
|
-
// месте (было: удаление .js оставило .tsx-исходники с 11 tsc-ошибками, а
|
|
126
|
-
// агент заявил успех). Гоняется, только если tsconfig.json достижим от
|
|
127
|
-
// baseDir или резолвленных файлов шагов И файловые проверки уже прошли —
|
|
128
|
-
// обречённому на missing/leftover аудиту 90s tsc-спавн не платим.
|
|
129
|
-
// Inconclusive-результаты не блокируют.
|
|
130
|
-
let typecheckError = null;
|
|
131
|
-
if (missingFiles.length === 0 && leftoverFiles.length === 0) {
|
|
132
|
-
const root = findTypecheckRoot(this.baseDir, existingFiles);
|
|
133
|
-
if (root) {
|
|
134
|
-
try {
|
|
135
|
-
typecheckError = await runTypecheck(root);
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
typecheckError = null;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const doneSteps = plan.steps.filter((s) => s.status === "done").length;
|
|
143
|
-
// done + skipped — оба осознанные терминальные состояния: `done` заявляет
|
|
144
|
-
// работу, `skipped` документирует решение, что шаг не нужен (задокументированная
|
|
145
|
-
// лазейка deliverable-gate). Ни то, ни другое — не ложь для аудита: план с
|
|
146
|
-
// легитимно скипнутым шагом обязан проходить (было: скипнутый шаг 1 вечно
|
|
147
|
-
// держал задачу реджектнутой).
|
|
148
|
-
const terminalSteps = plan.steps.filter((s) => s.status === "done" || s.status === "skipped").length;
|
|
149
|
-
const totalSteps = plan.steps.length;
|
|
150
|
-
const auditedFiles = [...new Set([...createFiles, ...deleteFiles])];
|
|
151
|
-
let massEditWarning = null;
|
|
152
|
-
if (auditedFiles.length > MASS_EDIT_THRESHOLD) {
|
|
153
|
-
massEditWarning = t("exec.mass_edit_warning", {
|
|
154
|
-
count: String(auditedFiles.length),
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
const testsFailing = testRun !== null && !testRun.passed;
|
|
158
|
-
const typecheckFailing = typecheckError !== null;
|
|
159
|
-
const passed = missingFiles.length === 0 && leftoverFiles.length === 0 && !testsFailing && !typecheckFailing;
|
|
160
|
-
// Сводка "Task complete ✓" для незаконченного плана — ложь, которую модель
|
|
161
|
-
// читает как зелёный свет (было: audit-gate инжектил "[✓] Task complete:
|
|
162
|
-
// 1/3 steps done" при 2 пендинг шагах). Сводка заявляет завершение, только
|
|
163
|
-
// если реально done каждый шаг.
|
|
164
|
-
const stepsPending = terminalSteps < totalSteps;
|
|
165
|
-
let summary;
|
|
166
|
-
if (missingFiles.length > 0) {
|
|
167
|
-
summary = t("exec.audit_fail", {
|
|
168
|
-
done: doneSteps,
|
|
169
|
-
total: totalSteps,
|
|
170
|
-
files: missingFiles.length,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
else if (leftoverFiles.length > 0) {
|
|
174
|
-
summary = t("exec.audit_leftovers", {
|
|
175
|
-
done: doneSteps,
|
|
176
|
-
total: totalSteps,
|
|
177
|
-
files: leftoverFiles.length,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
else if (testsFailing) {
|
|
181
|
-
summary = t("exec.audit_fail_tests", {
|
|
182
|
-
done: doneSteps,
|
|
183
|
-
total: totalSteps,
|
|
184
|
-
failed: String(testRun.failed),
|
|
185
|
-
passed: String(testRun.passedCount),
|
|
186
|
-
detail: testRun.detail,
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
else if (typecheckFailing) {
|
|
190
|
-
summary = t("exec.audit_fail_typecheck", {
|
|
191
|
-
done: doneSteps,
|
|
192
|
-
total: totalSteps,
|
|
193
|
-
missing: String(missingFiles.length),
|
|
194
|
-
typeError: typecheckError,
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
else if (stepsPending) {
|
|
198
|
-
summary = t("exec.audit_pending", {
|
|
199
|
-
done: doneSteps,
|
|
200
|
-
total: totalSteps,
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
summary = t("exec.audit_pass", {
|
|
205
|
-
done: doneSteps,
|
|
206
|
-
total: totalSteps,
|
|
207
|
-
files: existingFiles.length,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return {
|
|
211
|
-
passed,
|
|
212
|
-
missingFiles,
|
|
213
|
-
leftoverFiles,
|
|
214
|
-
createdFiles: existingFiles,
|
|
215
|
-
modifiedFiles: [],
|
|
216
|
-
summary,
|
|
217
|
-
massEditWarning,
|
|
218
|
-
testRun,
|
|
219
|
-
typecheckError,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
}
|