@vascend/talos 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +202 -0
- package/dist/backend/asset-events.d.ts +31 -0
- package/dist/backend/asset-events.js +149 -0
- package/dist/backend/assets.d.ts +31 -0
- package/dist/backend/assets.js +210 -0
- package/dist/backend/auth.d.ts +18 -0
- package/dist/backend/auth.js +59 -0
- package/dist/backend/config.d.ts +14 -0
- package/dist/backend/config.js +41 -0
- package/dist/backend/conversations.d.ts +21 -0
- package/dist/backend/conversations.js +141 -0
- package/dist/backend/crypto.d.ts +9 -0
- package/dist/backend/crypto.js +68 -0
- package/dist/backend/engine.d.ts +13 -0
- package/dist/backend/engine.js +78 -0
- package/dist/backend/http.d.ts +25 -0
- package/dist/backend/http.js +112 -0
- package/dist/backend/index.d.ts +1 -0
- package/dist/backend/index.js +24 -0
- package/dist/backend/routes.d.ts +14 -0
- package/dist/backend/routes.js +169 -0
- package/dist/backend/sdk.d.ts +12 -0
- package/dist/backend/sdk.js +11 -0
- package/dist/backend/server.d.ts +12 -0
- package/dist/backend/server.js +91 -0
- package/dist/backend/temp-image-store.d.ts +46 -0
- package/dist/backend/temp-image-store.js +197 -0
- package/dist/backend/types.d.ts +103 -0
- package/dist/backend/types.js +29 -0
- package/dist/backend/users.d.ts +13 -0
- package/dist/backend/users.js +76 -0
- package/dist/backend/ws-handler.d.ts +14 -0
- package/dist/backend/ws-handler.js +72 -0
- package/dist/backend/ws.d.ts +19 -0
- package/dist/backend/ws.js +146 -0
- package/dist/core/agent.d.ts +56 -0
- package/dist/core/agent.js +1783 -0
- package/dist/core/background.d.ts +45 -0
- package/dist/core/background.js +140 -0
- package/dist/core/bootstrap.d.ts +45 -0
- package/dist/core/bootstrap.js +294 -0
- package/dist/core/cli-args.d.ts +41 -0
- package/dist/core/cli-args.js +282 -0
- package/dist/core/collapsible-output.d.ts +38 -0
- package/dist/core/collapsible-output.js +143 -0
- package/dist/core/compaction-checkpoint.d.ts +9 -0
- package/dist/core/compaction-checkpoint.js +58 -0
- package/dist/core/compaction.d.ts +42 -0
- package/dist/core/compaction.js +270 -0
- package/dist/core/config.d.ts +49 -0
- package/dist/core/config.js +417 -0
- package/dist/core/context-ledger.d.ts +99 -0
- package/dist/core/context-ledger.js +222 -0
- package/dist/core/context-policy.d.ts +17 -0
- package/dist/core/context-policy.js +81 -0
- package/dist/core/continuation-review.d.ts +23 -0
- package/dist/core/continuation-review.js +64 -0
- package/dist/core/crash-report.d.ts +3 -0
- package/dist/core/crash-report.js +27 -0
- package/dist/core/credentials.d.ts +11 -0
- package/dist/core/credentials.js +183 -0
- package/dist/core/doctor.d.ts +24 -0
- package/dist/core/doctor.js +125 -0
- package/dist/core/effort.d.ts +5 -0
- package/dist/core/effort.js +42 -0
- package/dist/core/env-paths.d.ts +3 -0
- package/dist/core/env-paths.js +38 -0
- package/dist/core/execution-guidance.d.ts +9 -0
- package/dist/core/execution-guidance.js +73 -0
- package/dist/core/execution-target.d.ts +41 -0
- package/dist/core/execution-target.js +69 -0
- package/dist/core/file-coordination.d.ts +66 -0
- package/dist/core/file-coordination.js +176 -0
- package/dist/core/file-lease-store.d.ts +14 -0
- package/dist/core/file-lease-store.js +89 -0
- package/dist/core/image-limits.d.ts +26 -0
- package/dist/core/image-limits.js +205 -0
- package/dist/core/interruptible-completion.d.ts +3 -0
- package/dist/core/interruptible-completion.js +42 -0
- package/dist/core/kingdoms-mode-state.d.ts +24 -0
- package/dist/core/kingdoms-mode-state.js +139 -0
- package/dist/core/licenza.d.ts +38 -0
- package/dist/core/licenza.js +125 -0
- package/dist/core/model-limits.d.ts +2 -0
- package/dist/core/model-limits.js +36 -0
- package/dist/core/output-lifecycle.d.ts +44 -0
- package/dist/core/output-lifecycle.js +190 -0
- package/dist/core/package-update.d.ts +15 -0
- package/dist/core/package-update.js +121 -0
- package/dist/core/permission-queue.d.ts +2 -0
- package/dist/core/permission-queue.js +20 -0
- package/dist/core/prompt-attachment.d.ts +21 -0
- package/dist/core/prompt-attachment.js +123 -0
- package/dist/core/request-plan.d.ts +16 -0
- package/dist/core/request-plan.js +36 -0
- package/dist/core/run-timing.d.ts +17 -0
- package/dist/core/run-timing.js +123 -0
- package/dist/core/self-update.d.ts +17 -0
- package/dist/core/self-update.js +54 -0
- package/dist/core/session-refs.d.ts +27 -0
- package/dist/core/session-refs.js +126 -0
- package/dist/core/session-storage.d.ts +4 -0
- package/dist/core/session-storage.js +48 -0
- package/dist/core/session-title.d.ts +1 -0
- package/dist/core/session-title.js +21 -0
- package/dist/core/session-usage.d.ts +17 -0
- package/dist/core/session-usage.js +74 -0
- package/dist/core/session.d.ts +58 -0
- package/dist/core/session.js +296 -0
- package/dist/core/settings.d.ts +17 -0
- package/dist/core/settings.js +107 -0
- package/dist/core/storage-retention.d.ts +21 -0
- package/dist/core/storage-retention.js +227 -0
- package/dist/core/text-sanitize.d.ts +1 -0
- package/dist/core/text-sanitize.js +35 -0
- package/dist/core/tool-artifacts.d.ts +6 -0
- package/dist/core/tool-artifacts.js +51 -0
- package/dist/core/tool-compress.d.ts +8 -0
- package/dist/core/tool-compress.js +111 -0
- package/dist/core/tool-executor.d.ts +16 -0
- package/dist/core/tool-executor.js +97 -0
- package/dist/core/tool-result-index.d.ts +52 -0
- package/dist/core/tool-result-index.js +327 -0
- package/dist/core/tool-result-store.d.ts +38 -0
- package/dist/core/tool-result-store.js +190 -0
- package/dist/core/tool-scheduler.d.ts +16 -0
- package/dist/core/tool-scheduler.js +35 -0
- package/dist/core/trust.d.ts +21 -0
- package/dist/core/trust.js +95 -0
- package/dist/core/types.d.ts +402 -0
- package/dist/core/types.js +1 -0
- package/dist/core/update-check.d.ts +26 -0
- package/dist/core/update-check.js +89 -0
- package/dist/core/update-process.d.ts +10 -0
- package/dist/core/update-process.js +31 -0
- package/dist/core/user-inbox.d.ts +23 -0
- package/dist/core/user-inbox.js +56 -0
- package/dist/core/user-input.d.ts +10 -0
- package/dist/core/user-input.js +35 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/version.js +10 -0
- package/dist/core/vibe-modes.d.ts +38 -0
- package/dist/core/vibe-modes.js +383 -0
- package/dist/core/workspace-roots.d.ts +13 -0
- package/dist/core/workspace-roots.js +91 -0
- package/dist/core/workspace-sessions.d.ts +51 -0
- package/dist/core/workspace-sessions.js +243 -0
- package/dist/cowork/client.d.ts +29 -0
- package/dist/cowork/client.js +49 -0
- package/dist/cowork/engine-bridge.d.ts +22 -0
- package/dist/cowork/engine-bridge.js +98 -0
- package/dist/cowork/index.d.ts +11 -0
- package/dist/cowork/index.js +16 -0
- package/dist/cowork/ipc.d.ts +97 -0
- package/dist/cowork/ipc.js +96 -0
- package/dist/cowork/manager.d.ts +66 -0
- package/dist/cowork/manager.js +325 -0
- package/dist/cowork/store.d.ts +23 -0
- package/dist/cowork/store.js +182 -0
- package/dist/cowork/sync.d.ts +20 -0
- package/dist/cowork/sync.js +164 -0
- package/dist/cowork/types.d.ts +78 -0
- package/dist/cowork/types.js +21 -0
- package/dist/extensions/ext-tools.d.ts +3 -0
- package/dist/extensions/ext-tools.js +73 -0
- package/dist/extensions/loader.d.ts +91 -0
- package/dist/extensions/loader.js +474 -0
- package/dist/extensions/settings.d.ts +20 -0
- package/dist/extensions/settings.js +86 -0
- package/dist/extensions/types.d.ts +219 -0
- package/dist/extensions/types.js +1 -0
- package/dist/horizon/async-queue.d.ts +9 -0
- package/dist/horizon/async-queue.js +46 -0
- package/dist/horizon/engine.d.ts +85 -0
- package/dist/horizon/engine.js +603 -0
- package/dist/horizon/index.d.ts +4 -0
- package/dist/horizon/index.js +2 -0
- package/dist/horizon/main-team.d.ts +163 -0
- package/dist/horizon/main-team.js +774 -0
- package/dist/horizon/types.d.ts +233 -0
- package/dist/horizon/types.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +233 -0
- package/dist/mcp/protocol.d.ts +81 -0
- package/dist/mcp/protocol.js +122 -0
- package/dist/package.json +1 -0
- package/dist/packages/packages.d.ts +12 -0
- package/dist/packages/packages.js +323 -0
- package/dist/prompts/templates.d.ts +13 -0
- package/dist/prompts/templates.js +139 -0
- package/dist/providers/anthropic-oauth.d.ts +13 -0
- package/dist/providers/anthropic-oauth.js +124 -0
- package/dist/providers/anthropic.d.ts +27 -0
- package/dist/providers/anthropic.js +526 -0
- package/dist/providers/catalog.d.ts +15 -0
- package/dist/providers/catalog.js +166 -0
- package/dist/providers/effort.d.ts +12 -0
- package/dist/providers/effort.js +102 -0
- package/dist/providers/model-catalog.d.ts +43 -0
- package/dist/providers/model-catalog.js +70 -0
- package/dist/providers/model-effort.d.ts +5 -0
- package/dist/providers/model-effort.js +43 -0
- package/dist/providers/model-registry.d.ts +39 -0
- package/dist/providers/model-registry.js +142 -0
- package/dist/providers/models-dev.d.ts +9 -0
- package/dist/providers/models-dev.js +97 -0
- package/dist/providers/oauth-callback-server.d.ts +28 -0
- package/dist/providers/oauth-callback-server.js +184 -0
- package/dist/providers/oauth-orchestrator.d.ts +58 -0
- package/dist/providers/oauth-orchestrator.js +159 -0
- package/dist/providers/oauth-store.d.ts +12 -0
- package/dist/providers/oauth-store.js +139 -0
- package/dist/providers/open-browser.d.ts +20 -0
- package/dist/providers/open-browser.js +92 -0
- package/dist/providers/openai-compat.d.ts +14 -0
- package/dist/providers/openai-compat.js +523 -0
- package/dist/providers/openai-oauth.d.ts +15 -0
- package/dist/providers/openai-oauth.js +382 -0
- package/dist/providers/openrouter-auth.d.ts +73 -0
- package/dist/providers/openrouter-auth.js +321 -0
- package/dist/providers/openrouter-manual-fallback.d.ts +25 -0
- package/dist/providers/openrouter-manual-fallback.js +161 -0
- package/dist/providers/openrouter.d.ts +15 -0
- package/dist/providers/openrouter.js +107 -0
- package/dist/providers/plan-limits.d.ts +6 -0
- package/dist/providers/plan-limits.js +175 -0
- package/dist/providers/provider-reset.d.ts +4 -0
- package/dist/providers/provider-reset.js +83 -0
- package/dist/providers/quota-limits.d.ts +4 -0
- package/dist/providers/quota-limits.js +33 -0
- package/dist/providers/registry.d.ts +33 -0
- package/dist/providers/registry.js +213 -0
- package/dist/providers/retry.d.ts +37 -0
- package/dist/providers/retry.js +347 -0
- package/dist/rpc/server.d.ts +23 -0
- package/dist/rpc/server.js +222 -0
- package/dist/sdk.d.ts +67 -0
- package/dist/sdk.js +64 -0
- package/dist/skills/skills.d.ts +17 -0
- package/dist/skills/skills.js +155 -0
- package/dist/text-sanitize.js +28 -0
- package/dist/tools/ask-user.d.ts +2 -0
- package/dist/tools/ask-user.js +60 -0
- package/dist/tools/builtin.d.ts +48 -0
- package/dist/tools/builtin.js +2494 -0
- package/dist/tools/capabilities.d.ts +5 -0
- package/dist/tools/capabilities.js +55 -0
- package/dist/tools/computer-capture.d.ts +2 -0
- package/dist/tools/computer-capture.js +91 -0
- package/dist/tools/computer-posix.d.ts +5 -0
- package/dist/tools/computer-posix.js +136 -0
- package/dist/tools/computer-use.d.ts +14 -0
- package/dist/tools/computer-use.js +108 -0
- package/dist/tools/discovery.d.ts +12 -0
- package/dist/tools/discovery.js +205 -0
- package/dist/tools/execute.d.ts +2 -0
- package/dist/tools/execute.js +73 -0
- package/dist/tools/normalize-input.d.ts +17 -0
- package/dist/tools/normalize-input.js +174 -0
- package/dist/tools/output-artifact.d.ts +3 -0
- package/dist/tools/output-artifact.js +80 -0
- package/dist/tools/pagination.d.ts +15 -0
- package/dist/tools/pagination.js +93 -0
- package/dist/tools/plan-status.d.ts +2 -0
- package/dist/tools/plan-status.js +109 -0
- package/dist/tools/program-input.d.ts +3 -0
- package/dist/tools/program-input.js +19 -0
- package/dist/tools/program.d.ts +3 -0
- package/dist/tools/program.js +567 -0
- package/dist/tools/protocol-catalog.d.ts +12 -0
- package/dist/tools/protocol-catalog.js +46 -0
- package/dist/tools/ramification-tools.d.ts +12 -0
- package/dist/tools/ramification-tools.js +528 -0
- package/dist/tools/regex-compat.d.ts +9 -0
- package/dist/tools/regex-compat.js +96 -0
- package/dist/tools/registry.d.ts +51 -0
- package/dist/tools/registry.js +185 -0
- package/dist/tools/resolve.d.ts +2 -0
- package/dist/tools/resolve.js +107 -0
- package/dist/tools/shell-env.d.ts +2 -0
- package/dist/tools/shell-env.js +7 -0
- package/dist/tools/team-input.d.ts +3 -0
- package/dist/tools/team-input.js +129 -0
- package/dist/tools/team-tools.d.ts +7 -0
- package/dist/tools/team-tools.js +348 -0
- package/dist/tools/workspace-sessions.d.ts +2 -0
- package/dist/tools/workspace-sessions.js +35 -0
- package/dist/tui/account-entry.d.ts +1 -0
- package/dist/tui/account-entry.js +93 -0
- package/dist/tui/attachment-highlight.d.ts +1 -0
- package/dist/tui/attachment-highlight.js +24 -0
- package/dist/tui/attachment-refs.d.ts +2 -0
- package/dist/tui/attachment-refs.js +3 -0
- package/dist/tui/bottom-input.d.ts +219 -0
- package/dist/tui/bottom-input.js +1958 -0
- package/dist/tui/branding.d.ts +107 -0
- package/dist/tui/branding.js +750 -0
- package/dist/tui/clipboard-image.d.ts +10 -0
- package/dist/tui/clipboard-image.js +163 -0
- package/dist/tui/clipboard-text.d.ts +9 -0
- package/dist/tui/clipboard-text.js +51 -0
- package/dist/tui/clipboard-windows.d.ts +8 -0
- package/dist/tui/clipboard-windows.js +84 -0
- package/dist/tui/collapsible-command.d.ts +15 -0
- package/dist/tui/collapsible-command.js +48 -0
- package/dist/tui/command-feedback.d.ts +10 -0
- package/dist/tui/command-feedback.js +46 -0
- package/dist/tui/command-output-registry.d.ts +28 -0
- package/dist/tui/command-output-registry.js +103 -0
- package/dist/tui/command-transcript.d.ts +12 -0
- package/dist/tui/command-transcript.js +90 -0
- package/dist/tui/commands.d.ts +20 -0
- package/dist/tui/commands.js +131 -0
- package/dist/tui/context-bar.d.ts +4 -0
- package/dist/tui/context-bar.js +74 -0
- package/dist/tui/context-meter.d.ts +25 -0
- package/dist/tui/context-meter.js +81 -0
- package/dist/tui/cost-binding.d.ts +8 -0
- package/dist/tui/cost-binding.js +43 -0
- package/dist/tui/cost-tracker.d.ts +49 -0
- package/dist/tui/cost-tracker.js +122 -0
- package/dist/tui/diff.d.ts +9 -0
- package/dist/tui/diff.js +119 -0
- package/dist/tui/i18n-catalog.d.ts +5 -0
- package/dist/tui/i18n-catalog.js +184 -0
- package/dist/tui/i18n.d.ts +6 -0
- package/dist/tui/i18n.js +10 -0
- package/dist/tui/image-attachments.d.ts +46 -0
- package/dist/tui/image-attachments.js +167 -0
- package/dist/tui/images.d.ts +12 -0
- package/dist/tui/images.js +87 -0
- package/dist/tui/intro.d.ts +13 -0
- package/dist/tui/intro.js +109 -0
- package/dist/tui/language-preference.d.ts +6 -0
- package/dist/tui/language-preference.js +24 -0
- package/dist/tui/live-output.d.ts +2 -0
- package/dist/tui/live-output.js +18 -0
- package/dist/tui/locales.d.ts +19 -0
- package/dist/tui/locales.js +22 -0
- package/dist/tui/login-menu.d.ts +17 -0
- package/dist/tui/login-menu.js +58 -0
- package/dist/tui/logo.d.ts +8 -0
- package/dist/tui/logo.js +305 -0
- package/dist/tui/markdown-inline.d.ts +3 -0
- package/dist/tui/markdown-inline.js +99 -0
- package/dist/tui/markdown-table.d.ts +4 -0
- package/dist/tui/markdown-table.js +63 -0
- package/dist/tui/markdown.d.ts +11 -0
- package/dist/tui/markdown.js +257 -0
- package/dist/tui/mcp-transcript.d.ts +7 -0
- package/dist/tui/mcp-transcript.js +40 -0
- package/dist/tui/model-details.d.ts +2 -0
- package/dist/tui/model-details.js +21 -0
- package/dist/tui/model-selection.d.ts +7 -0
- package/dist/tui/model-selection.js +41 -0
- package/dist/tui/native-scrollback.d.ts +27 -0
- package/dist/tui/native-scrollback.js +134 -0
- package/dist/tui/onboarding.d.ts +72 -0
- package/dist/tui/onboarding.js +207 -0
- package/dist/tui/paste-collapse.d.ts +39 -0
- package/dist/tui/paste-collapse.js +117 -0
- package/dist/tui/perm-mode.d.ts +8 -0
- package/dist/tui/perm-mode.js +41 -0
- package/dist/tui/prompt-queue-store.d.ts +26 -0
- package/dist/tui/prompt-queue-store.js +87 -0
- package/dist/tui/prompt-queue.d.ts +47 -0
- package/dist/tui/prompt-queue.js +187 -0
- package/dist/tui/provider-menu.d.ts +33 -0
- package/dist/tui/provider-menu.js +175 -0
- package/dist/tui/question.d.ts +24 -0
- package/dist/tui/question.js +32 -0
- package/dist/tui/queue-screen.d.ts +25 -0
- package/dist/tui/queue-screen.js +152 -0
- package/dist/tui/queue-team.d.ts +3 -0
- package/dist/tui/queue-team.js +28 -0
- package/dist/tui/queued-questions.d.ts +20 -0
- package/dist/tui/queued-questions.js +163 -0
- package/dist/tui/quick-help.d.ts +1 -0
- package/dist/tui/quick-help.js +53 -0
- package/dist/tui/repl.d.ts +78 -0
- package/dist/tui/repl.js +4130 -0
- package/dist/tui/restore-queued-input.d.ts +3 -0
- package/dist/tui/restore-queued-input.js +20 -0
- package/dist/tui/review-detail.d.ts +6 -0
- package/dist/tui/review-detail.js +56 -0
- package/dist/tui/review-files.d.ts +3 -0
- package/dist/tui/review-files.js +22 -0
- package/dist/tui/review-render.d.ts +22 -0
- package/dist/tui/review-render.js +98 -0
- package/dist/tui/review-screen.d.ts +38 -0
- package/dist/tui/review-screen.js +358 -0
- package/dist/tui/review-store.d.ts +60 -0
- package/dist/tui/review-store.js +270 -0
- package/dist/tui/review-team.d.ts +2 -0
- package/dist/tui/review-team.js +27 -0
- package/dist/tui/selector-mouse.d.ts +26 -0
- package/dist/tui/selector-mouse.js +65 -0
- package/dist/tui/selector.d.ts +51 -0
- package/dist/tui/selector.js +299 -0
- package/dist/tui/session-replay.d.ts +10 -0
- package/dist/tui/session-replay.js +78 -0
- package/dist/tui/session-usage.d.ts +22 -0
- package/dist/tui/session-usage.js +55 -0
- package/dist/tui/skill-transcript.d.ts +5 -0
- package/dist/tui/skill-transcript.js +31 -0
- package/dist/tui/startup.d.ts +5 -0
- package/dist/tui/startup.js +61 -0
- package/dist/tui/status-line-loader.d.ts +8 -0
- package/dist/tui/status-line-loader.js +33 -0
- package/dist/tui/status-line.d.ts +38 -0
- package/dist/tui/status-line.js +213 -0
- package/dist/tui/system-language.d.ts +8 -0
- package/dist/tui/system-language.js +41 -0
- package/dist/tui/task-labels.d.ts +2 -0
- package/dist/tui/task-labels.js +7 -0
- package/dist/tui/term-bg.d.ts +4 -0
- package/dist/tui/term-bg.js +67 -0
- package/dist/tui/terminal-screen.d.ts +12 -0
- package/dist/tui/terminal-screen.js +1 -0
- package/dist/tui/terminal-text.d.ts +7 -0
- package/dist/tui/terminal-text.js +123 -0
- package/dist/tui/theme.d.ts +25 -0
- package/dist/tui/theme.js +383 -0
- package/dist/tui/tool-style.d.ts +7 -0
- package/dist/tui/tool-style.js +119 -0
- package/dist/tui/update-prompt.d.ts +14 -0
- package/dist/tui/update-prompt.js +104 -0
- package/dist/tui/usage-footer.d.ts +9 -0
- package/dist/tui/usage-footer.js +123 -0
- package/dist/tui/vascend-login.d.ts +68 -0
- package/dist/tui/vascend-login.js +355 -0
- package/dist/tui/web-login.d.ts +28 -0
- package/dist/tui/web-login.js +115 -0
- package/dist/vascend/activity-status.d.ts +12 -0
- package/dist/vascend/activity-status.js +68 -0
- package/dist/vascend/architecture-map.d.ts +73 -0
- package/dist/vascend/architecture-map.js +424 -0
- package/dist/vascend/attention-layout.d.ts +19 -0
- package/dist/vascend/attention-layout.js +141 -0
- package/dist/vascend/budget-allocator.d.ts +31 -0
- package/dist/vascend/budget-allocator.js +79 -0
- package/dist/vascend/candidate-collector.d.ts +20 -0
- package/dist/vascend/candidate-collector.js +220 -0
- package/dist/vascend/code-events.d.ts +24 -0
- package/dist/vascend/code-events.js +304 -0
- package/dist/vascend/code-graph-memory.d.ts +38 -0
- package/dist/vascend/code-graph-memory.js +334 -0
- package/dist/vascend/code-graph-runtime.d.ts +19 -0
- package/dist/vascend/code-graph-runtime.js +190 -0
- package/dist/vascend/code-graph-types.d.ts +58 -0
- package/dist/vascend/code-graph-types.js +50 -0
- package/dist/vascend/code-parser.d.ts +4 -0
- package/dist/vascend/code-parser.js +257 -0
- package/dist/vascend/competitor-knowledge.d.ts +53 -0
- package/dist/vascend/competitor-knowledge.js +262 -0
- package/dist/vascend/completeness.d.ts +16 -0
- package/dist/vascend/completeness.js +90 -0
- package/dist/vascend/context-autotuner.d.ts +45 -0
- package/dist/vascend/context-autotuner.js +231 -0
- package/dist/vascend/context-candidate.d.ts +45 -0
- package/dist/vascend/context-candidate.js +150 -0
- package/dist/vascend/context-capsule.d.ts +51 -0
- package/dist/vascend/context-capsule.js +133 -0
- package/dist/vascend/context-fabric.d.ts +108 -0
- package/dist/vascend/context-fabric.js +480 -0
- package/dist/vascend/context-feedback-loop.d.ts +56 -0
- package/dist/vascend/context-feedback-loop.js +204 -0
- package/dist/vascend/context-learning-identity.d.ts +4 -0
- package/dist/vascend/context-learning-identity.js +8 -0
- package/dist/vascend/context-links.d.ts +14 -0
- package/dist/vascend/context-links.js +83 -0
- package/dist/vascend/context-lint.d.ts +22 -0
- package/dist/vascend/context-lint.js +91 -0
- package/dist/vascend/context-market-selection.d.ts +17 -0
- package/dist/vascend/context-market-selection.js +50 -0
- package/dist/vascend/context-metrics.d.ts +25 -0
- package/dist/vascend/context-metrics.js +57 -0
- package/dist/vascend/context-pack-render.d.ts +16 -0
- package/dist/vascend/context-pack-render.js +52 -0
- package/dist/vascend/context-pareto.d.ts +33 -0
- package/dist/vascend/context-pareto.js +165 -0
- package/dist/vascend/context-pattern-explorer.d.ts +41 -0
- package/dist/vascend/context-pattern-explorer.js +276 -0
- package/dist/vascend/context-regret.d.ts +32 -0
- package/dist/vascend/context-regret.js +93 -0
- package/dist/vascend/context-retriever.d.ts +22 -0
- package/dist/vascend/context-retriever.js +243 -0
- package/dist/vascend/context-scope-index.d.ts +5 -0
- package/dist/vascend/context-scope-index.js +96 -0
- package/dist/vascend/context-scorer.d.ts +35 -0
- package/dist/vascend/context-scorer.js +162 -0
- package/dist/vascend/context-search-index.d.ts +12 -0
- package/dist/vascend/context-search-index.js +25 -0
- package/dist/vascend/context-snapshot.d.ts +22 -0
- package/dist/vascend/context-snapshot.js +135 -0
- package/dist/vascend/context-window-compiler.d.ts +42 -0
- package/dist/vascend/context-window-compiler.js +237 -0
- package/dist/vascend/contract-memory.d.ts +61 -0
- package/dist/vascend/contract-memory.js +435 -0
- package/dist/vascend/council.d.ts +58 -0
- package/dist/vascend/council.js +337 -0
- package/dist/vascend/decision-promotion.d.ts +48 -0
- package/dist/vascend/decision-promotion.js +410 -0
- package/dist/vascend/delta-context.d.ts +12 -0
- package/dist/vascend/delta-context.js +36 -0
- package/dist/vascend/dev-context-compiler.d.ts +27 -0
- package/dist/vascend/dev-context-compiler.js +133 -0
- package/dist/vascend/dev-context-layout.d.ts +30 -0
- package/dist/vascend/dev-context-layout.js +262 -0
- package/dist/vascend/evidence-slots.d.ts +14 -0
- package/dist/vascend/evidence-slots.js +55 -0
- package/dist/vascend/expansion-levels.d.ts +15 -0
- package/dist/vascend/expansion-levels.js +178 -0
- package/dist/vascend/file-lock.d.ts +7 -0
- package/dist/vascend/file-lock.js +95 -0
- package/dist/vascend/granular-kingdom.d.ts +25 -0
- package/dist/vascend/granular-kingdom.js +259 -0
- package/dist/vascend/granular-launcher.d.ts +48 -0
- package/dist/vascend/granular-launcher.js +202 -0
- package/dist/vascend/kingdom-bus.d.ts +25 -0
- package/dist/vascend/kingdom-bus.js +54 -0
- package/dist/vascend/kingdom-channel.d.ts +22 -0
- package/dist/vascend/kingdom-channel.js +180 -0
- package/dist/vascend/kingdom-kpi.d.ts +48 -0
- package/dist/vascend/kingdom-kpi.js +172 -0
- package/dist/vascend/kingdom-live.d.ts +28 -0
- package/dist/vascend/kingdom-live.js +61 -0
- package/dist/vascend/kingdom-run.d.ts +18 -0
- package/dist/vascend/kingdom-run.js +506 -0
- package/dist/vascend/kingdom-scribe.d.ts +20 -0
- package/dist/vascend/kingdom-scribe.js +52 -0
- package/dist/vascend/kingdom.d.ts +79 -0
- package/dist/vascend/kingdom.js +870 -0
- package/dist/vascend/lexical-index.d.ts +10 -0
- package/dist/vascend/lexical-index.js +99 -0
- package/dist/vascend/lexical-search.d.ts +29 -0
- package/dist/vascend/lexical-search.js +262 -0
- package/dist/vascend/long-term-context.d.ts +51 -0
- package/dist/vascend/long-term-context.js +194 -0
- package/dist/vascend/mandate.d.ts +33 -0
- package/dist/vascend/mandate.js +107 -0
- package/dist/vascend/memory-packet.d.ts +13 -0
- package/dist/vascend/memory-packet.js +155 -0
- package/dist/vascend/memory-status.d.ts +22 -0
- package/dist/vascend/memory-status.js +73 -0
- package/dist/vascend/memory-store.d.ts +62 -0
- package/dist/vascend/memory-store.js +273 -0
- package/dist/vascend/objective-revision.d.ts +69 -0
- package/dist/vascend/objective-revision.js +319 -0
- package/dist/vascend/patch-plan-store.d.ts +33 -0
- package/dist/vascend/patch-plan-store.js +240 -0
- package/dist/vascend/patch-plan.d.ts +97 -0
- package/dist/vascend/patch-plan.js +345 -0
- package/dist/vascend/plan-progress.d.ts +11 -0
- package/dist/vascend/plan-progress.js +68 -0
- package/dist/vascend/plan-store.d.ts +64 -0
- package/dist/vascend/plan-store.js +460 -0
- package/dist/vascend/proof-chains.d.ts +19 -0
- package/dist/vascend/proof-chains.js +120 -0
- package/dist/vascend/ramification-store.d.ts +25 -0
- package/dist/vascend/ramification-store.js +94 -0
- package/dist/vascend/ramification.d.ts +193 -0
- package/dist/vascend/ramification.js +583 -0
- package/dist/vascend/recall-planner.d.ts +17 -0
- package/dist/vascend/recall-planner.js +109 -0
- package/dist/vascend/requirements.d.ts +31 -0
- package/dist/vascend/requirements.js +151 -0
- package/dist/vascend/reviewer.d.ts +9 -0
- package/dist/vascend/reviewer.js +93 -0
- package/dist/vascend/room-graph.d.ts +29 -0
- package/dist/vascend/room-graph.js +242 -0
- package/dist/vascend/room-memory.d.ts +57 -0
- package/dist/vascend/room-memory.js +631 -0
- package/dist/vascend/runtime.d.ts +84 -0
- package/dist/vascend/runtime.js +286 -0
- package/dist/vascend/self-improve.d.ts +104 -0
- package/dist/vascend/self-improve.js +396 -0
- package/dist/vascend/session-search.d.ts +52 -0
- package/dist/vascend/session-search.js +349 -0
- package/dist/vascend/supersession-graph.d.ts +14 -0
- package/dist/vascend/supersession-graph.js +70 -0
- package/dist/vascend/team-areas.d.ts +9 -0
- package/dist/vascend/team-areas.js +28 -0
- package/dist/vascend/team-handoff.d.ts +24 -0
- package/dist/vascend/team-handoff.js +37 -0
- package/dist/vascend/team-scheduler.d.ts +13 -0
- package/dist/vascend/team-scheduler.js +74 -0
- package/dist/vascend/team-session.d.ts +42 -0
- package/dist/vascend/team-session.js +142 -0
- package/dist/vascend/test-failure-memory.d.ts +76 -0
- package/dist/vascend/test-failure-memory.js +354 -0
- package/dist/vascend/token-market.d.ts +42 -0
- package/dist/vascend/token-market.js +144 -0
- package/dist/vascend/tuner-baseline-store.d.ts +52 -0
- package/dist/vascend/tuner-baseline-store.js +446 -0
- package/dist/vascend/user-profile.d.ts +44 -0
- package/dist/vascend/user-profile.js +131 -0
- package/dist/vascend/vision.d.ts +94 -0
- package/dist/vascend/vision.js +375 -0
- package/dist/vascend/work-agent.d.ts +12 -0
- package/dist/vascend/work-agent.js +83 -0
- package/dist/vascend/work-queue.d.ts +62 -0
- package/dist/vascend/work-queue.js +255 -0
- package/dist/vascend/work-runner.d.ts +64 -0
- package/dist/vascend/work-runner.js +137 -0
- package/dist/vascend/worktree.d.ts +38 -0
- package/dist/vascend/worktree.js +206 -0
- package/dist/vendor/computer-use/README.md +7 -0
- package/dist/vendor/computer-use/computer-desktop.js +211 -0
- package/dist/vendor/computer-use/computer-observe.js +315 -0
- package/dist/vendor/computer-use/computer-scripts.js +1230 -0
- package/dist/vendor/computer-use/computer-tools.js +2136 -0
- package/dist/vendor/computer-use/package.json +1 -0
- package/dist/vendor/computer-use/rac/atomic-input.js +91 -0
- package/dist/vendor/computer-use/rac/grammatica.js +101 -0
- package/dist/vendor/computer-use/rac/parser.js +185 -0
- package/dist/vendor/computer-use/rac/protocol.js +136 -0
- package/install.ps1 +30 -0
- package/install.sh +50 -0
- package/package.json +56 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Token Market (metodo Danilov, Memory OS) -- L3: Optimization Layer.
|
|
2
|
+
//
|
|
3
|
+
// Il salto sopra le quote fisse del BudgetAllocator: la context window non e' un
|
|
4
|
+
// insieme di cassetti a percentuale fissa, ma un MERCATO. Ogni capsula fa
|
|
5
|
+
// un'offerta per lo spazio; i token vanno a chi produce piu' valore per token.
|
|
6
|
+
//
|
|
7
|
+
// bid_i = (relevance + dependency + riskReduction + novelty + trust)_i
|
|
8
|
+
// / tokenCost_i
|
|
9
|
+
//
|
|
10
|
+
// Ogni zona ha un prezzo dinamico:
|
|
11
|
+
//
|
|
12
|
+
// price_zone = congestion_zone + stalePenalty_zone - missionNeed_zone
|
|
13
|
+
//
|
|
14
|
+
// Una prova decisionale puo' "pagare" per entrare anche se l'evidence budget e'
|
|
15
|
+
// quasi pieno, mentre una nota ripetuta viene respinta. L'esito assegna a ogni
|
|
16
|
+
// capsula un LIVELLO di espansione (R0-R4) o il DROP, rispettando il budget.
|
|
17
|
+
//
|
|
18
|
+
// Modulo PURO e DETERMINISTICO: nessun side-effect, nessuna rete. L'asta e'
|
|
19
|
+
// greedy ordinata per bid (tie-break stabile su id), quindi riproducibile.
|
|
20
|
+
import { bestExpansion, tokensAtLevel, utilityAtLevel, } from "./expansion-levels.js";
|
|
21
|
+
import { isStale, withExpansion, confidenceWeightOf, } from "./context-capsule.js";
|
|
22
|
+
// Valore marginale di una capsula: somma dei segnali positivi. riskReduction =
|
|
23
|
+
// quanto la capsula RIDUCE il rischio (decisione attiva/dipendenza forte) meno
|
|
24
|
+
// il rischio che AGGIUNGE (stale). Deterministico.
|
|
25
|
+
function marginalValue(c, relevance, novelty) {
|
|
26
|
+
const trust = confidenceWeightOf(c.header.confidence);
|
|
27
|
+
const dependency = c.metrics.utility >= 0.7 ? 1 : c.metrics.utility >= 0.5 ? 0.5 : 0;
|
|
28
|
+
// riskReduction: una decisione attiva o un prerequisito riduce il rischio di
|
|
29
|
+
// risposta errata; una capsula stale lo AUMENTA (riskReduction negativo).
|
|
30
|
+
let riskReduction = 0;
|
|
31
|
+
if (c.header.type === "decision" && c.header.status === "active")
|
|
32
|
+
riskReduction += 0.6;
|
|
33
|
+
if (c.metrics.utility >= 0.7)
|
|
34
|
+
riskReduction += 0.3;
|
|
35
|
+
if (isStale(c))
|
|
36
|
+
riskReduction -= 0.8;
|
|
37
|
+
riskReduction = clampSigned(riskReduction);
|
|
38
|
+
const rel = clamp01(relevance);
|
|
39
|
+
const nov = clamp01(novelty);
|
|
40
|
+
const total = rel + dependency + Math.max(0, riskReduction) + nov + trust;
|
|
41
|
+
return { relevance: rel, dependency, riskReduction, novelty: nov, trust, total };
|
|
42
|
+
}
|
|
43
|
+
// Calcola il bid di una capsula al suo livello DESIDERATO (bestExpansion).
|
|
44
|
+
export function computeBid(c, ctx) {
|
|
45
|
+
const relevance = ctx.relevance?.get(c.header.id) ?? 0;
|
|
46
|
+
const novelty = ctx.novelty?.get(c.header.id) ?? 1;
|
|
47
|
+
const mv = marginalValue(c, relevance, novelty);
|
|
48
|
+
const desiredLevel = bestExpansion(c, { tokenBudget: ctx.tokenBudget, ...ctx.expansion });
|
|
49
|
+
const tokenCost = Math.max(1, tokensAtLevel(c, desiredLevel));
|
|
50
|
+
const bid = mv.total / tokenCost;
|
|
51
|
+
return {
|
|
52
|
+
id: c.header.id,
|
|
53
|
+
relevance: mv.relevance,
|
|
54
|
+
dependency: mv.dependency,
|
|
55
|
+
riskReduction: mv.riskReduction,
|
|
56
|
+
novelty: mv.novelty,
|
|
57
|
+
trust: mv.trust,
|
|
58
|
+
tokenCost,
|
|
59
|
+
bid,
|
|
60
|
+
desiredLevel,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Esegue l'asta: ordina le capsule per bid decrescente e le ammette finche' il
|
|
64
|
+
// budget regge, al loro livello desiderato. Se una capsula non entra al livello
|
|
65
|
+
// desiderato, prova a DEGRADARLA (livello piu' basso, piu' economico) prima di
|
|
66
|
+
// scartarla: e' il rate-distortion che paga il prezzo dello spazio scarso.
|
|
67
|
+
// Deterministico: tie-break su id.
|
|
68
|
+
export function runTokenMarket(capsules, ctx) {
|
|
69
|
+
const bids = capsules.map((c) => ({ capsule: c, bid: computeBid(c, ctx) }));
|
|
70
|
+
bids.sort((a, b) => b.bid.bid - a.bid.bid || a.bid.id.localeCompare(b.bid.id));
|
|
71
|
+
const admitted = [];
|
|
72
|
+
const dropped = [];
|
|
73
|
+
let used = 0;
|
|
74
|
+
const budget = Math.max(0, ctx.tokenBudget);
|
|
75
|
+
for (const { capsule, bid } of bids) {
|
|
76
|
+
let placed = false;
|
|
77
|
+
// Prova dal livello desiderato verso il basso (degrado): R desiderato..R0.
|
|
78
|
+
for (let lvl = bid.desiredLevel; lvl >= 0; lvl--) {
|
|
79
|
+
const level = lvl;
|
|
80
|
+
const tokens = tokensAtLevel(capsule, level);
|
|
81
|
+
if (used + tokens <= budget) {
|
|
82
|
+
admitted.push({
|
|
83
|
+
capsule: withExpansion(capsule, level),
|
|
84
|
+
bid,
|
|
85
|
+
level,
|
|
86
|
+
tokensUsed: tokens,
|
|
87
|
+
});
|
|
88
|
+
used += tokens;
|
|
89
|
+
placed = true;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!placed) {
|
|
94
|
+
dropped.push({ capsule, bid, level: "drop", tokensUsed: 0 });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { admitted, dropped, tokensUsed: used, tokenBudget: budget };
|
|
98
|
+
}
|
|
99
|
+
// price_zone = congestion + stalePenalty - missionNeed, clampato >= 0.
|
|
100
|
+
// Una zona poco richiesta dalla mission e congestionata costa di piu' (frena gli
|
|
101
|
+
// ingressi); una zona che serve alla mission costa meno (lascia entrare prove).
|
|
102
|
+
export function zonePrice(input) {
|
|
103
|
+
const p = clamp01(input.congestion) + clamp01(input.stalePenalty) - clamp01(input.missionNeed);
|
|
104
|
+
return Math.max(0, round(p));
|
|
105
|
+
}
|
|
106
|
+
// Diagnostica dell'asta come blocco Danilov.
|
|
107
|
+
export function formatMarketResult(r, opts) {
|
|
108
|
+
const top = opts?.top ?? r.admitted.length;
|
|
109
|
+
const lines = [
|
|
110
|
+
"[TOKEN_MARKET]",
|
|
111
|
+
`@asta: budget=${r.tokenBudget}tok, usati=${r.tokensUsed}tok, ammesse=${r.admitted.length}, drop=${r.dropped.length}`,
|
|
112
|
+
"--- ammesse (bid desc) ---",
|
|
113
|
+
];
|
|
114
|
+
r.admitted.slice(0, top).forEach((a) => {
|
|
115
|
+
lines.push(`@adm[${a.bid.id}]: R${a.level} bid=${round(a.bid.bid)} (${a.tokensUsed}tok)`);
|
|
116
|
+
});
|
|
117
|
+
if (r.dropped.length) {
|
|
118
|
+
lines.push("--- drop ---");
|
|
119
|
+
r.dropped.forEach((d) => lines.push(`@drop[${d.bid.id}]: bid=${round(d.bid.bid)} (no budget)`));
|
|
120
|
+
}
|
|
121
|
+
lines.push("OUTPUT: i token vanno alle capsule con piu' valore per token.");
|
|
122
|
+
return lines.join("\n");
|
|
123
|
+
}
|
|
124
|
+
function clamp01(v) {
|
|
125
|
+
if (Number.isNaN(v))
|
|
126
|
+
return 0;
|
|
127
|
+
if (v < 0)
|
|
128
|
+
return 0;
|
|
129
|
+
if (v > 1)
|
|
130
|
+
return 1;
|
|
131
|
+
return v;
|
|
132
|
+
}
|
|
133
|
+
function clampSigned(v) {
|
|
134
|
+
if (Number.isNaN(v))
|
|
135
|
+
return 0;
|
|
136
|
+
if (v < -1)
|
|
137
|
+
return -1;
|
|
138
|
+
if (v > 1)
|
|
139
|
+
return 1;
|
|
140
|
+
return v;
|
|
141
|
+
}
|
|
142
|
+
function round(v) {
|
|
143
|
+
return Math.round(v * 1000) / 1000;
|
|
144
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type TuneConfig } from "./context-autotuner.js";
|
|
2
|
+
export declare const TUNER_BASELINE_SCHEMA_VERSION: 1;
|
|
3
|
+
export declare const DEFAULT_BASELINE_SCOPE = "global";
|
|
4
|
+
export interface TunerBaseline {
|
|
5
|
+
readonly version: 1;
|
|
6
|
+
readonly scope: string;
|
|
7
|
+
readonly config: TuneConfig;
|
|
8
|
+
readonly bestScore: number;
|
|
9
|
+
readonly lastScore: number;
|
|
10
|
+
readonly observations: number;
|
|
11
|
+
readonly createdAt: string;
|
|
12
|
+
readonly updatedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface BaselineObservation {
|
|
15
|
+
readonly config: TuneConfig;
|
|
16
|
+
readonly score: number;
|
|
17
|
+
readonly initialScore?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function learningRate(observations: number, gain: number): number;
|
|
20
|
+
export declare function blendConfig(base: TuneConfig, obs: TuneConfig, alpha: number): TuneConfig;
|
|
21
|
+
export declare function mergeObservation(baseline: TunerBaseline, obs: BaselineObservation, opts?: {
|
|
22
|
+
readonly now?: string;
|
|
23
|
+
}): TunerBaseline;
|
|
24
|
+
export declare const MIN_PRIOR_OBSERVATIONS = 3;
|
|
25
|
+
export declare const MIN_PRIOR_SCORE = 1;
|
|
26
|
+
export declare function blendPrior(baselines: readonly TunerBaseline[]): TuneConfig | null;
|
|
27
|
+
export declare function initialBaseline(scope: string, opts?: {
|
|
28
|
+
readonly now?: string;
|
|
29
|
+
}): TunerBaseline;
|
|
30
|
+
export declare function parseBaseline(raw: unknown, scopeFallback: string, opts?: {
|
|
31
|
+
readonly now?: string;
|
|
32
|
+
}): TunerBaseline;
|
|
33
|
+
export declare function baselineToJSON(b: TunerBaseline): Record<string, unknown>;
|
|
34
|
+
export declare function formatBaseline(b: TunerBaseline): string;
|
|
35
|
+
export declare class TunerBaselineStore {
|
|
36
|
+
private readonly file;
|
|
37
|
+
private readonly dir;
|
|
38
|
+
private baselines;
|
|
39
|
+
private priorCache;
|
|
40
|
+
private constructor();
|
|
41
|
+
static open(dir: string, storeId: string): TunerBaselineStore;
|
|
42
|
+
get(scope?: string): TunerBaseline;
|
|
43
|
+
private freshBaseline;
|
|
44
|
+
private prior;
|
|
45
|
+
has(scope?: string): boolean;
|
|
46
|
+
all(): readonly TunerBaseline[];
|
|
47
|
+
startConfig(scope?: string): TuneConfig;
|
|
48
|
+
observe(scope: string, obs: BaselineObservation, opts?: {
|
|
49
|
+
readonly now?: string;
|
|
50
|
+
}): TunerBaseline;
|
|
51
|
+
private persistUnlocked;
|
|
52
|
+
}
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
// Tuner Baseline Store (metodo Danilov, Memory OS) -- L4: l'apprendimento.
|
|
2
|
+
//
|
|
3
|
+
// L'anello di retroazione (context-feedback-loop) trova una bestConfig ottima
|
|
4
|
+
// PER QUEL TURNO, ma poi la getta: il turno dopo riparte da DEFAULT_CONFIG e
|
|
5
|
+
// ri-paga la convergenza da zero. Questo modulo chiude l'ultimo anello:
|
|
6
|
+
// PERSISTE la configurazione appresa come BASELINE, cosi' i turni e le SESSIONI
|
|
7
|
+
// successive ripartono dall'architettura gia' migliorata invece che dai default.
|
|
8
|
+
//
|
|
9
|
+
// turno 1: DEFAULT -> loop -> bestConfig --> baseline.observe(best)
|
|
10
|
+
// turno 2: baseline.config (gia' buona) -> loop -> bestConfig' -> baseline.observe
|
|
11
|
+
// ... la baseline converge verso la configurazione che funziona davvero
|
|
12
|
+
//
|
|
13
|
+
// E' apprendimento CUMULATIVO e DETERMINISTICO dell'architettura del context:
|
|
14
|
+
// non genera testo, non chiama il modello, non tocca la rete. Aggiorna pesi e
|
|
15
|
+
// soglie via media mobile esponenziale (EMA), pesata sulla qualita' osservata.
|
|
16
|
+
//
|
|
17
|
+
// - EMA: nuova_baseline = (1-alpha)*baseline + alpha*osservata.
|
|
18
|
+
// alpha cresce con il guadagno di qualita' (un'osservazione molto migliore
|
|
19
|
+
// pesa di piu') e cala col numero di osservazioni gia' viste (stabilita').
|
|
20
|
+
// - MONOTONIA MORBIDA: una config che PEGGIORA non sposta la baseline; una
|
|
21
|
+
// che migliora la attira verso di se' in proporzione al miglioramento.
|
|
22
|
+
// - CLAMP: ogni leva resta nei range sani dell'autotuner (no divergenza).
|
|
23
|
+
// - SCOPE: una baseline per "scope" (di default il progetto), cosi' progetti
|
|
24
|
+
// diversi imparano architetture diverse senza interferire.
|
|
25
|
+
//
|
|
26
|
+
// Persistenza: file JSON `<storeId>.tuner.json` -> mappa { [scope]: Baseline }.
|
|
27
|
+
// Stesso stile di VascendVisionStore: API immutabile, persistenza su mutazione,
|
|
28
|
+
// parsing robusto (file corrotto -> si riparte dai default).
|
|
29
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
30
|
+
import { basename, dirname, join } from "node:path";
|
|
31
|
+
import { DEFAULT_WEIGHTS, DEFAULT_THRESHOLDS } from "./context-scorer.js";
|
|
32
|
+
import { DEFAULT_CONFIG } from "./context-autotuner.js";
|
|
33
|
+
import { withLockSync } from "./file-lock.js";
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// 1. MODELLO
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
export const TUNER_BASELINE_SCHEMA_VERSION = 1;
|
|
38
|
+
// Lo scope di default quando il chiamante non ne passa uno.
|
|
39
|
+
export const DEFAULT_BASELINE_SCOPE = "global";
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// 2. RANGE SANI (riallineati all'autotuner: l'apprendimento non puo' divergere)
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
const WEIGHT_BOUNDS = {
|
|
44
|
+
relevance: [0.5, 2.0],
|
|
45
|
+
dependency: [0.3, 1.5],
|
|
46
|
+
trust: [0.2, 1.2],
|
|
47
|
+
freshness: [0.1, 1.0],
|
|
48
|
+
novelty: [0.1, 1.0],
|
|
49
|
+
conflictRisk: [0.5, 2.5],
|
|
50
|
+
tokenCost: [0.05, 0.8],
|
|
51
|
+
};
|
|
52
|
+
const HIGH_BOUNDS = [0.6, 1.8];
|
|
53
|
+
const MID_BOUNDS = [0.2, 0.9];
|
|
54
|
+
// Estremi del passo di apprendimento. alpha grande = impara in fretta ma
|
|
55
|
+
// instabile; piccolo = stabile ma lento. Restiamo in una banda prudente.
|
|
56
|
+
const ALPHA_MIN = 0.1;
|
|
57
|
+
const ALPHA_MAX = 0.5;
|
|
58
|
+
function clamp(v, lo, hi) {
|
|
59
|
+
if (!Number.isFinite(v))
|
|
60
|
+
return lo;
|
|
61
|
+
return Math.max(lo, Math.min(hi, v));
|
|
62
|
+
}
|
|
63
|
+
function round3(v) {
|
|
64
|
+
return Math.round(v * 1000) / 1000;
|
|
65
|
+
}
|
|
66
|
+
function nowIso() {
|
|
67
|
+
return new Date().toISOString();
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// 3. BLEND EMA (cuore dell'apprendimento)
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Calcola il tasso di apprendimento alpha per un'osservazione. Cresce col
|
|
73
|
+
// guadagno di qualita' (un salto grande tira di piu' la baseline) e cala col
|
|
74
|
+
// numero di osservazioni gia' viste (piu' esperienza = piu' stabilita').
|
|
75
|
+
// gainFactor in [0,1]: quanto e' migliore l'osservazione rispetto al passato.
|
|
76
|
+
// ageFactor in (0,1]: smorzamento per esperienza accumulata.
|
|
77
|
+
export function learningRate(observations, gain) {
|
|
78
|
+
// gain atteso 0..100 (delta di qualityScore). Normalizziamo su una scala di
|
|
79
|
+
// 20 punti: un guadagno >= 20 conta come "molto migliore" (gainFactor=1).
|
|
80
|
+
const gainFactor = clamp(gain / 20, 0, 1);
|
|
81
|
+
// Piu' osservazioni -> meno reattivita': 1/(1+obs) smorza nel tempo.
|
|
82
|
+
const ageFactor = 1 / (1 + Math.max(0, observations));
|
|
83
|
+
const alpha = ALPHA_MIN + (ALPHA_MAX - ALPHA_MIN) * gainFactor * Math.max(ageFactor, 0.2);
|
|
84
|
+
return clamp(alpha, ALPHA_MIN, ALPHA_MAX);
|
|
85
|
+
}
|
|
86
|
+
// Media mobile esponenziale di un singolo valore, clampata nel suo range.
|
|
87
|
+
function emaValue(base, obs, alpha, lo, hi) {
|
|
88
|
+
return clamp(round3(base * (1 - alpha) + obs * alpha), lo, hi);
|
|
89
|
+
}
|
|
90
|
+
// Fonde due config con tasso alpha: ogni leva via EMA, clampata nei range sani.
|
|
91
|
+
// Mantiene l'invariante di tier (mid sempre sotto high).
|
|
92
|
+
export function blendConfig(base, obs, alpha) {
|
|
93
|
+
const w = (k) => emaValue(base.weights[k], obs.weights[k], alpha, WEIGHT_BOUNDS[k][0], WEIGHT_BOUNDS[k][1]);
|
|
94
|
+
const weights = {
|
|
95
|
+
relevance: w("relevance"),
|
|
96
|
+
dependency: w("dependency"),
|
|
97
|
+
trust: w("trust"),
|
|
98
|
+
freshness: w("freshness"),
|
|
99
|
+
novelty: w("novelty"),
|
|
100
|
+
conflictRisk: w("conflictRisk"),
|
|
101
|
+
tokenCost: w("tokenCost"),
|
|
102
|
+
};
|
|
103
|
+
const high = emaValue(base.thresholds.high, obs.thresholds.high, alpha, HIGH_BOUNDS[0], HIGH_BOUNDS[1]);
|
|
104
|
+
const midRaw = emaValue(base.thresholds.mid, obs.thresholds.mid, alpha, MID_BOUNDS[0], MID_BOUNDS[1]);
|
|
105
|
+
const mid = Math.min(midRaw, round3(high - 0.1));
|
|
106
|
+
return { weights, thresholds: { high, mid } };
|
|
107
|
+
}
|
|
108
|
+
// Incorpora un'osservazione in una baseline e ritorna la NUOVA baseline
|
|
109
|
+
// (immutabile). Regola fondamentale:
|
|
110
|
+
// - se l'osservazione PEGGIORA (score < lastScore) la baseline NON si sposta:
|
|
111
|
+
// solo lastScore viene aggiornato (memoria dell'andamento) -- monotonia.
|
|
112
|
+
// - se l'osservazione MIGLIORA o pareggia, la config si fonde via EMA verso
|
|
113
|
+
// l'osservata, con alpha pesato sul guadagno.
|
|
114
|
+
// PURA e deterministica.
|
|
115
|
+
export function mergeObservation(baseline, obs, opts) {
|
|
116
|
+
const ts = opts?.now ?? nowIso();
|
|
117
|
+
const improving = obs.score >= baseline.lastScore;
|
|
118
|
+
if (!improving) {
|
|
119
|
+
// Peggioramento: non spostiamo la config appresa, ma registriamo l'esito.
|
|
120
|
+
return {
|
|
121
|
+
...baseline,
|
|
122
|
+
lastScore: obs.score,
|
|
123
|
+
bestScore: Math.max(baseline.bestScore, obs.score),
|
|
124
|
+
observations: baseline.observations + 1,
|
|
125
|
+
updatedAt: ts,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const gain = obs.score - (obs.initialScore ?? baseline.lastScore);
|
|
129
|
+
const alpha = learningRate(baseline.observations, Math.max(0, gain));
|
|
130
|
+
const config = blendConfig(baseline.config, obs.config, alpha);
|
|
131
|
+
return {
|
|
132
|
+
version: TUNER_BASELINE_SCHEMA_VERSION,
|
|
133
|
+
scope: baseline.scope,
|
|
134
|
+
config,
|
|
135
|
+
bestScore: Math.max(baseline.bestScore, obs.score),
|
|
136
|
+
lastScore: obs.score,
|
|
137
|
+
observations: baseline.observations + 1,
|
|
138
|
+
createdAt: baseline.createdAt,
|
|
139
|
+
updatedAt: ts,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// 3-bis. PRIOR FRA SCOPE (l'esperienza si trasferisce)
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
//
|
|
146
|
+
// L'EMA fa imparare uno scope dai propri turni. Ma uno scope NUOVO nasceva
|
|
147
|
+
// sempre da DEFAULT_CONFIG, e siccome un progetto tipico dura una manciata di
|
|
148
|
+
// turni non arrivava mai a imparare niente: i .tuner.json reali mostrano le
|
|
149
|
+
// sessioni lunghe a 100 e i progetti nuovi fermi a 46 con una osservazione.
|
|
150
|
+
//
|
|
151
|
+
// Il prior chiude questo buco: cio' che l'architettura del contesto ha imparato
|
|
152
|
+
// ALTROVE e' il punto di partenza piu' sensato di un default scritto a mano.
|
|
153
|
+
// Non e' una config nuova, e' una media pesata di configurazioni gia' validate.
|
|
154
|
+
//
|
|
155
|
+
// Chi entra nella media: solo baseline con abbastanza esperienza E una qualita'
|
|
156
|
+
// misurata. Una baseline con una sola osservazione non e' esperienza, e una con
|
|
157
|
+
// bestScore 0 non ha mai dimostrato niente — pesarle sarebbe propagare rumore.
|
|
158
|
+
// Sotto queste soglie una baseline non ha ancora imparato abbastanza da poter
|
|
159
|
+
// insegnare a un'altra.
|
|
160
|
+
export const MIN_PRIOR_OBSERVATIONS = 3;
|
|
161
|
+
export const MIN_PRIOR_SCORE = 1;
|
|
162
|
+
// Quante baseline sorelle al massimo si leggono dal disco per costruire il
|
|
163
|
+
// prior: un tetto tiene il costo costante anche in una cartella cresciuta.
|
|
164
|
+
const MAX_PRIOR_FILES = 64;
|
|
165
|
+
// Peso di una baseline nella media: l'esperienza (osservazioni) moltiplicata
|
|
166
|
+
// per la qualita' raggiunta. Chi ha girato di piu' ED e' arrivato piu' in alto
|
|
167
|
+
// insegna di piu'.
|
|
168
|
+
function priorWeight(b) {
|
|
169
|
+
return b.observations * (b.bestScore / 100);
|
|
170
|
+
}
|
|
171
|
+
// Media pesata delle baseline mature. Ritorna null quando non c'e' esperienza
|
|
172
|
+
// da cui attingere: in quel caso il chiamante resta ai default, che e' il
|
|
173
|
+
// comportamento di prima (non-regressione).
|
|
174
|
+
export function blendPrior(baselines) {
|
|
175
|
+
const mature = baselines
|
|
176
|
+
.filter((b) => b.observations >= MIN_PRIOR_OBSERVATIONS && b.bestScore >= MIN_PRIOR_SCORE)
|
|
177
|
+
// Ordine stabile: la media di float non deve dipendere da come il
|
|
178
|
+
// filesystem ha elencato i file.
|
|
179
|
+
.slice()
|
|
180
|
+
.sort((a, b) => (a.scope < b.scope ? -1 : a.scope > b.scope ? 1 : 0));
|
|
181
|
+
if (!mature.length)
|
|
182
|
+
return null;
|
|
183
|
+
const total = mature.reduce((sum, b) => sum + priorWeight(b), 0);
|
|
184
|
+
if (!(total > 0))
|
|
185
|
+
return null;
|
|
186
|
+
const mean = (pick) => mature.reduce((sum, b) => sum + pick(b) * priorWeight(b), 0) / total;
|
|
187
|
+
const w = (k) => clamp(round3(mean((b) => b.config.weights[k])), WEIGHT_BOUNDS[k][0], WEIGHT_BOUNDS[k][1]);
|
|
188
|
+
const high = clamp(round3(mean((b) => b.config.thresholds.high)), HIGH_BOUNDS[0], HIGH_BOUNDS[1]);
|
|
189
|
+
const midRaw = clamp(round3(mean((b) => b.config.thresholds.mid)), MID_BOUNDS[0], MID_BOUNDS[1]);
|
|
190
|
+
return {
|
|
191
|
+
weights: {
|
|
192
|
+
relevance: w("relevance"),
|
|
193
|
+
dependency: w("dependency"),
|
|
194
|
+
trust: w("trust"),
|
|
195
|
+
freshness: w("freshness"),
|
|
196
|
+
novelty: w("novelty"),
|
|
197
|
+
conflictRisk: w("conflictRisk"),
|
|
198
|
+
tokenCost: w("tokenCost"),
|
|
199
|
+
},
|
|
200
|
+
// Stessa invariante del blend: il tier mid non puo' raggiungere l'high.
|
|
201
|
+
thresholds: { high, mid: Math.min(midRaw, round3(high - 0.1)) },
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// Baseline iniziale (default) per uno scope: parte dalla config di default.
|
|
205
|
+
export function initialBaseline(scope, opts) {
|
|
206
|
+
const ts = opts?.now ?? nowIso();
|
|
207
|
+
return {
|
|
208
|
+
version: TUNER_BASELINE_SCHEMA_VERSION,
|
|
209
|
+
scope: scope.trim() || DEFAULT_BASELINE_SCOPE,
|
|
210
|
+
config: DEFAULT_CONFIG,
|
|
211
|
+
bestScore: 0,
|
|
212
|
+
lastScore: 0,
|
|
213
|
+
observations: 0,
|
|
214
|
+
createdAt: ts,
|
|
215
|
+
updatedAt: ts,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
// 4. PARSING ROBUSTO + SERIALIZZAZIONE
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
function num(v, fallback) {
|
|
222
|
+
const n = typeof v === "number" ? v : typeof v === "string" ? Number(v) : NaN;
|
|
223
|
+
return Number.isFinite(n) ? n : fallback;
|
|
224
|
+
}
|
|
225
|
+
// Normalizza pesi grezzi nei range sani, riempiendo i mancanti dai default.
|
|
226
|
+
function parseWeights(raw) {
|
|
227
|
+
const o = (raw ?? {});
|
|
228
|
+
const w = (k) => clamp(round3(num(o[k], DEFAULT_WEIGHTS[k])), WEIGHT_BOUNDS[k][0], WEIGHT_BOUNDS[k][1]);
|
|
229
|
+
return {
|
|
230
|
+
relevance: w("relevance"),
|
|
231
|
+
dependency: w("dependency"),
|
|
232
|
+
trust: w("trust"),
|
|
233
|
+
freshness: w("freshness"),
|
|
234
|
+
novelty: w("novelty"),
|
|
235
|
+
conflictRisk: w("conflictRisk"),
|
|
236
|
+
tokenCost: w("tokenCost"),
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function parseThresholds(raw) {
|
|
240
|
+
const o = (raw ?? {});
|
|
241
|
+
const high = clamp(round3(num(o["high"], DEFAULT_THRESHOLDS.high)), HIGH_BOUNDS[0], HIGH_BOUNDS[1]);
|
|
242
|
+
const midRaw = clamp(round3(num(o["mid"], DEFAULT_THRESHOLDS.mid)), MID_BOUNDS[0], MID_BOUNDS[1]);
|
|
243
|
+
const mid = Math.min(midRaw, round3(high - 0.1));
|
|
244
|
+
return { high, mid };
|
|
245
|
+
}
|
|
246
|
+
// Deserializza una singola baseline da oggetto grezzo. Mai lancia: riempie i
|
|
247
|
+
// campi mancanti/invalidi dai default e clampa tutto.
|
|
248
|
+
export function parseBaseline(raw, scopeFallback, opts) {
|
|
249
|
+
const o = (raw ?? {});
|
|
250
|
+
const ts = opts?.now ?? nowIso();
|
|
251
|
+
const scope = (typeof o["scope"] === "string" && o["scope"].trim()) || scopeFallback || DEFAULT_BASELINE_SCOPE;
|
|
252
|
+
return {
|
|
253
|
+
version: TUNER_BASELINE_SCHEMA_VERSION,
|
|
254
|
+
scope,
|
|
255
|
+
config: { weights: parseWeights(o["config"]?.["weights"]), thresholds: parseThresholds(o["config"]?.["thresholds"]) },
|
|
256
|
+
bestScore: clamp(num(o["bestScore"], 0), 0, 100),
|
|
257
|
+
lastScore: clamp(num(o["lastScore"], 0), 0, 100),
|
|
258
|
+
observations: Math.max(0, Math.floor(num(o["observations"], 0))),
|
|
259
|
+
createdAt: (typeof o["createdAt"] === "string" && o["createdAt"]) || ts,
|
|
260
|
+
updatedAt: (typeof o["updatedAt"] === "string" && o["updatedAt"]) || ts,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
// Serializza una baseline in oggetto JSON-stabile (chiavi ordinate).
|
|
264
|
+
export function baselineToJSON(b) {
|
|
265
|
+
return {
|
|
266
|
+
version: b.version,
|
|
267
|
+
scope: b.scope,
|
|
268
|
+
config: {
|
|
269
|
+
weights: {
|
|
270
|
+
relevance: b.config.weights.relevance,
|
|
271
|
+
dependency: b.config.weights.dependency,
|
|
272
|
+
trust: b.config.weights.trust,
|
|
273
|
+
freshness: b.config.weights.freshness,
|
|
274
|
+
novelty: b.config.weights.novelty,
|
|
275
|
+
conflictRisk: b.config.weights.conflictRisk,
|
|
276
|
+
tokenCost: b.config.weights.tokenCost,
|
|
277
|
+
},
|
|
278
|
+
thresholds: { high: b.config.thresholds.high, mid: b.config.thresholds.mid },
|
|
279
|
+
},
|
|
280
|
+
bestScore: b.bestScore,
|
|
281
|
+
lastScore: b.lastScore,
|
|
282
|
+
observations: b.observations,
|
|
283
|
+
createdAt: b.createdAt,
|
|
284
|
+
updatedAt: b.updatedAt,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
// Blocco Danilov per log/TUI.
|
|
288
|
+
export function formatBaseline(b) {
|
|
289
|
+
return [
|
|
290
|
+
`[TUNER_BASELINE:${b.scope}]`,
|
|
291
|
+
`@appreso: obs=${b.observations}, best=${b.bestScore}, last=${b.lastScore}`,
|
|
292
|
+
`@pesi: rel=${b.config.weights.relevance} dep=${b.config.weights.dependency} trust=${b.config.weights.trust} fresh=${b.config.weights.freshness} nov=${b.config.weights.novelty} conf=${b.config.weights.conflictRisk} cost=${b.config.weights.tokenCost}`,
|
|
293
|
+
`@soglie: high=${b.config.thresholds.high} mid=${b.config.thresholds.mid}`,
|
|
294
|
+
"OUTPUT: usa config come punto di partenza dell'anello (apprendimento cumulativo).",
|
|
295
|
+
].join("\n");
|
|
296
|
+
}
|
|
297
|
+
// ---------------------------------------------------------------------------
|
|
298
|
+
// 5. STORE PERSISTENTE
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// Store persistente delle baseline apprese: file `<storeId>.tuner.json` ->
|
|
301
|
+
// mappa { [scope]: TunerBaseline }. API immutabile verso l'esterno, persistenza
|
|
302
|
+
// su mutazione, robusto al file corrotto. Stesso stile di VascendVisionStore.
|
|
303
|
+
export class TunerBaselineStore {
|
|
304
|
+
file;
|
|
305
|
+
dir;
|
|
306
|
+
baselines = {};
|
|
307
|
+
// undefined = prior non ancora calcolato; null = calcolato e non esiste
|
|
308
|
+
// esperienza da cui attingere. Il disco si legge una volta per store, e solo
|
|
309
|
+
// se serve davvero: nel caso comune (scope gia' appreso) non si legge affatto.
|
|
310
|
+
priorCache;
|
|
311
|
+
constructor(file, dir) {
|
|
312
|
+
this.file = file;
|
|
313
|
+
this.dir = dir;
|
|
314
|
+
}
|
|
315
|
+
// Apre lo store per uno scope di file (di norma il progetto/sessione). Il
|
|
316
|
+
// file e' separato dagli store di sessione cosi' la baseline VIVE FRA SESSIONI.
|
|
317
|
+
static open(dir, storeId) {
|
|
318
|
+
const store = new TunerBaselineStore(join(dir, `${storeId}.tuner.json`), dir);
|
|
319
|
+
store.baselines = readBaselineFile(store.file);
|
|
320
|
+
return store;
|
|
321
|
+
}
|
|
322
|
+
// Ritorna la baseline dello scope. Se lo scope e' nuovo parte dal PRIOR
|
|
323
|
+
// appreso sugli altri progetti invece che dai default: un progetto nuovo non
|
|
324
|
+
// deve ripagare da zero una convergenza gia' pagata altrove.
|
|
325
|
+
// Non persiste: e' una lettura pura.
|
|
326
|
+
get(scope = DEFAULT_BASELINE_SCOPE) {
|
|
327
|
+
const key = (scope || DEFAULT_BASELINE_SCOPE).trim() || DEFAULT_BASELINE_SCOPE;
|
|
328
|
+
return this.baselines[key] ?? this.freshBaseline(key);
|
|
329
|
+
}
|
|
330
|
+
// La baseline di partenza per uno scope mai visto: default piu' il prior, se
|
|
331
|
+
// c'e'. bestScore e observations restano a zero — il prior offre un punto di
|
|
332
|
+
// partenza, non un merito che questo scope non ha ancora guadagnato.
|
|
333
|
+
freshBaseline(scope, opts) {
|
|
334
|
+
const base = initialBaseline(scope, opts);
|
|
335
|
+
const prior = this.prior();
|
|
336
|
+
return prior ? { ...base, config: prior } : base;
|
|
337
|
+
}
|
|
338
|
+
// Il prior appreso dalle baseline sorelle nella stessa cartella (gli altri
|
|
339
|
+
// progetti e sessioni). Memoizzato: vale per la vita dello store.
|
|
340
|
+
prior() {
|
|
341
|
+
if (this.priorCache !== undefined)
|
|
342
|
+
return this.priorCache;
|
|
343
|
+
this.priorCache = blendPrior(readSiblingBaselines(this.dir, this.file));
|
|
344
|
+
return this.priorCache;
|
|
345
|
+
}
|
|
346
|
+
has(scope = DEFAULT_BASELINE_SCOPE) {
|
|
347
|
+
return Boolean(this.baselines[(scope || DEFAULT_BASELINE_SCOPE).trim()]);
|
|
348
|
+
}
|
|
349
|
+
all() {
|
|
350
|
+
return Object.values(this.baselines);
|
|
351
|
+
}
|
|
352
|
+
// La config da usare come PUNTO DI PARTENZA dell'anello per uno scope. Se non
|
|
353
|
+
// c'e' ancora apprendimento, ritorna i default.
|
|
354
|
+
startConfig(scope = DEFAULT_BASELINE_SCOPE) {
|
|
355
|
+
return this.get(scope).config;
|
|
356
|
+
}
|
|
357
|
+
// Incorpora un'osservazione (config+score trovati dall'anello), aggiorna la
|
|
358
|
+
// baseline via EMA e persiste. Ritorna la nuova baseline.
|
|
359
|
+
observe(scope, obs, opts) {
|
|
360
|
+
const key = (scope || DEFAULT_BASELINE_SCOPE).trim() || DEFAULT_BASELINE_SCOPE;
|
|
361
|
+
return withLockSync(this.file, () => {
|
|
362
|
+
// Rileggi DENTRO il lock: due sessioni/vassalli aperti sulla stessa
|
|
363
|
+
// baseline non possono sovrascriversi a vicenda con snapshot stantii.
|
|
364
|
+
const disk = readBaselineFile(this.file);
|
|
365
|
+
const cur = disk[key] ?? this.baselines[key] ?? this.freshBaseline(key, opts);
|
|
366
|
+
const next = mergeObservation(cur, obs, opts);
|
|
367
|
+
this.baselines = { ...disk, [key]: next };
|
|
368
|
+
this.persistUnlocked();
|
|
369
|
+
return next;
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
persistUnlocked() {
|
|
373
|
+
mkdirSync(dirname(this.file), { recursive: true });
|
|
374
|
+
const ordered = {};
|
|
375
|
+
for (const [scope, b] of Object.entries(this.baselines)) {
|
|
376
|
+
ordered[scope] = baselineToJSON(b);
|
|
377
|
+
}
|
|
378
|
+
const temp = `${this.file}.${process.pid}.${Date.now()}.tmp`;
|
|
379
|
+
writeFileSync(temp, JSON.stringify(ordered, null, 2) + "\n", "utf8");
|
|
380
|
+
try {
|
|
381
|
+
renameSync(temp, this.file);
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
rmSync(this.file, { force: true });
|
|
385
|
+
renameSync(temp, this.file);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
// Le baseline degli ALTRI store nella stessa cartella: e' li' che vive
|
|
390
|
+
// l'esperienza degli altri progetti. Il proprio file e' escluso — un prior
|
|
391
|
+
// costruito su se stessi non insegnerebbe niente.
|
|
392
|
+
//
|
|
393
|
+
// Best-effort in ogni passaggio: una cartella illeggibile o un file corrotto
|
|
394
|
+
// fanno tornare cio' che si e' riusciti a leggere. Il prior e' un miglioramento
|
|
395
|
+
// opportunistico, non una dipendenza: se manca, si resta ai default.
|
|
396
|
+
function readSiblingBaselines(dir, ownFile) {
|
|
397
|
+
let names;
|
|
398
|
+
try {
|
|
399
|
+
names = readdirSync(dir);
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
return [];
|
|
403
|
+
}
|
|
404
|
+
const own = basename(ownFile);
|
|
405
|
+
const candidates = names.filter((name) => name.endsWith(".tuner.json") && name !== own);
|
|
406
|
+
// Piu' recenti prima: se la cartella e' cresciuta oltre il tetto, l'esperienza
|
|
407
|
+
// fresca conta piu' di quella vecchia.
|
|
408
|
+
const ordered = candidates
|
|
409
|
+
.map((name) => {
|
|
410
|
+
const full = join(dir, name);
|
|
411
|
+
let mtime = 0;
|
|
412
|
+
try {
|
|
413
|
+
mtime = statSync(full).mtimeMs;
|
|
414
|
+
}
|
|
415
|
+
catch {
|
|
416
|
+
mtime = 0;
|
|
417
|
+
}
|
|
418
|
+
return { full, mtime };
|
|
419
|
+
})
|
|
420
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
421
|
+
.slice(0, MAX_PRIOR_FILES);
|
|
422
|
+
const out = [];
|
|
423
|
+
for (const { full } of ordered) {
|
|
424
|
+
for (const baseline of Object.values(readBaselineFile(full)))
|
|
425
|
+
out.push(baseline);
|
|
426
|
+
}
|
|
427
|
+
return out;
|
|
428
|
+
}
|
|
429
|
+
function readBaselineFile(file) {
|
|
430
|
+
if (!existsSync(file))
|
|
431
|
+
return {};
|
|
432
|
+
try {
|
|
433
|
+
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
434
|
+
const out = {};
|
|
435
|
+
for (const [scope, value] of Object.entries(raw ?? {})) {
|
|
436
|
+
const parsed = parseBaseline(value, scope);
|
|
437
|
+
out[parsed.scope] = parsed;
|
|
438
|
+
}
|
|
439
|
+
return out;
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
// File corrotto: fail-open sui default. La prossima observe lo sostituisce
|
|
443
|
+
// atomicamente sotto lock con uno store valido.
|
|
444
|
+
return {};
|
|
445
|
+
}
|
|
446
|
+
}
|