agent-nuvira 3.3.12 → 3.3.14
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 +67 -1
- package/dist/agents/agents/planner.d.ts.map +1 -1
- package/dist/agents/agents/planner.js +9 -0
- package/dist/agents/agents/planner.js.map +1 -1
- package/dist/agents/agents/reasoner.d.ts.map +1 -1
- package/dist/agents/agents/reasoner.js +13 -0
- package/dist/agents/agents/reasoner.js.map +1 -1
- package/dist/agents/orchestrator.d.ts +31 -0
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +103 -135
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/cli/chat.d.ts +89 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +798 -39
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +20 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts +12 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +107 -3
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/decisions.d.ts +28 -0
- package/dist/cli/decisions.d.ts.map +1 -0
- package/dist/cli/decisions.js +140 -0
- package/dist/cli/decisions.js.map +1 -0
- package/dist/cli/doctor.d.ts +6 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +46 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +6 -0
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/failover-runner.d.ts.map +1 -1
- package/dist/cli/failover-runner.js +19 -1
- package/dist/cli/failover-runner.js.map +1 -1
- package/dist/cli/feedback.d.ts.map +1 -1
- package/dist/cli/feedback.js +5 -1
- package/dist/cli/feedback.js.map +1 -1
- package/dist/cli/hooks.d.ts +30 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +224 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/knowledge.d.ts +31 -0
- package/dist/cli/knowledge.d.ts.map +1 -0
- package/dist/cli/knowledge.js +223 -0
- package/dist/cli/knowledge.js.map +1 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +92 -18
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts +20 -0
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +294 -14
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/omniroute-control.d.ts +88 -0
- package/dist/cli/omniroute-control.d.ts.map +1 -0
- package/dist/cli/omniroute-control.js +179 -0
- package/dist/cli/omniroute-control.js.map +1 -0
- package/dist/cli/omniroute.d.ts +21 -0
- package/dist/cli/omniroute.d.ts.map +1 -0
- package/dist/cli/omniroute.js +67 -0
- package/dist/cli/omniroute.js.map +1 -0
- package/dist/cli/rate.d.ts +78 -0
- package/dist/cli/rate.d.ts.map +1 -0
- package/dist/cli/rate.js +294 -0
- package/dist/cli/rate.js.map +1 -0
- package/dist/config/process-env.d.ts.map +1 -1
- package/dist/config/process-env.js +10 -0
- package/dist/config/process-env.js.map +1 -1
- package/dist/config/types.d.ts +8 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/context/history.d.ts +21 -0
- package/dist/context/history.d.ts.map +1 -1
- package/dist/context/history.js +50 -0
- package/dist/context/history.js.map +1 -1
- package/dist/enterprise/vault.d.ts.map +1 -1
- package/dist/enterprise/vault.js +5 -21
- package/dist/enterprise/vault.js.map +1 -1
- package/dist/gateway/hook-contract.d.ts +206 -0
- package/dist/gateway/hook-contract.d.ts.map +1 -0
- package/dist/gateway/hook-contract.js +449 -0
- package/dist/gateway/hook-contract.js.map +1 -0
- package/dist/gateway/hooks.d.ts.map +1 -1
- package/dist/gateway/hooks.js +14 -0
- package/dist/gateway/hooks.js.map +1 -1
- package/dist/inference/gemini-adapter.d.ts.map +1 -1
- package/dist/inference/gemini-adapter.js +4 -0
- package/dist/inference/gemini-adapter.js.map +1 -1
- package/dist/inference/interface.d.ts +54 -0
- package/dist/inference/interface.d.ts.map +1 -1
- package/dist/inference/model-id-validation.d.ts +57 -0
- package/dist/inference/model-id-validation.d.ts.map +1 -0
- package/dist/inference/model-id-validation.js +127 -0
- package/dist/inference/model-id-validation.js.map +1 -0
- package/dist/inference/native-tools.d.ts +16 -1
- package/dist/inference/native-tools.d.ts.map +1 -1
- package/dist/inference/native-tools.js +34 -10
- package/dist/inference/native-tools.js.map +1 -1
- package/dist/inference/openai-compat-adapter.d.ts.map +1 -1
- package/dist/inference/openai-compat-adapter.js +12 -1
- package/dist/inference/openai-compat-adapter.js.map +1 -1
- package/dist/inference/provider-catalog.d.ts +11 -0
- package/dist/inference/provider-catalog.d.ts.map +1 -1
- package/dist/inference/provider-catalog.js +80 -0
- package/dist/inference/provider-catalog.js.map +1 -1
- package/dist/inference/route-resolver.d.ts +32 -8
- package/dist/inference/route-resolver.d.ts.map +1 -1
- package/dist/inference/route-resolver.js +175 -1
- package/dist/inference/route-resolver.js.map +1 -1
- package/dist/inference/tool-call-utils.d.ts.map +1 -1
- package/dist/inference/tool-call-utils.js +10 -8
- package/dist/inference/tool-call-utils.js.map +1 -1
- package/dist/inference/tools.d.ts +17 -1
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +69 -19
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/acceptance-model.d.ts +247 -0
- package/dist/learning/acceptance-model.d.ts.map +1 -0
- package/dist/learning/acceptance-model.js +708 -0
- package/dist/learning/acceptance-model.js.map +1 -0
- package/dist/learning/auto-router.d.ts +121 -24
- package/dist/learning/auto-router.d.ts.map +1 -1
- package/dist/learning/auto-router.js +374 -96
- package/dist/learning/auto-router.js.map +1 -1
- package/dist/learning/autonomy-policy.d.ts +12 -16
- package/dist/learning/autonomy-policy.d.ts.map +1 -1
- package/dist/learning/autonomy-policy.js +50 -48
- package/dist/learning/autonomy-policy.js.map +1 -1
- package/dist/learning/behavioural-labels.d.ts +86 -0
- package/dist/learning/behavioural-labels.d.ts.map +1 -0
- package/dist/learning/behavioural-labels.js +166 -0
- package/dist/learning/behavioural-labels.js.map +1 -0
- package/dist/learning/capability-evidence.d.ts +167 -0
- package/dist/learning/capability-evidence.d.ts.map +1 -0
- package/dist/learning/capability-evidence.js +210 -0
- package/dist/learning/capability-evidence.js.map +1 -0
- package/dist/learning/capability-readiness.d.ts +64 -0
- package/dist/learning/capability-readiness.d.ts.map +1 -0
- package/dist/learning/capability-readiness.js +74 -0
- package/dist/learning/capability-readiness.js.map +1 -0
- package/dist/learning/capability-types.d.ts +169 -0
- package/dist/learning/capability-types.d.ts.map +1 -0
- package/dist/learning/capability-types.js +20 -0
- package/dist/learning/capability-types.js.map +1 -0
- package/dist/learning/catalog-feed.d.ts +89 -0
- package/dist/learning/catalog-feed.d.ts.map +1 -0
- package/dist/learning/catalog-feed.js +211 -0
- package/dist/learning/catalog-feed.js.map +1 -0
- package/dist/learning/cli-intent-effects.d.ts +60 -0
- package/dist/learning/cli-intent-effects.d.ts.map +1 -0
- package/dist/learning/cli-intent-effects.js +153 -0
- package/dist/learning/cli-intent-effects.js.map +1 -0
- package/dist/learning/command-adaptation.d.ts +41 -0
- package/dist/learning/command-adaptation.d.ts.map +1 -0
- package/dist/learning/command-adaptation.js +122 -0
- package/dist/learning/command-adaptation.js.map +1 -0
- package/dist/learning/consent-picture.d.ts +42 -0
- package/dist/learning/consent-picture.d.ts.map +1 -0
- package/dist/learning/consent-picture.js +53 -0
- package/dist/learning/consent-picture.js.map +1 -0
- package/dist/learning/context-budget.d.ts +37 -6
- package/dist/learning/context-budget.d.ts.map +1 -1
- package/dist/learning/context-budget.js +38 -9
- package/dist/learning/context-budget.js.map +1 -1
- package/dist/learning/decision-log.d.ts +114 -0
- package/dist/learning/decision-log.d.ts.map +1 -0
- package/dist/learning/decision-log.js +296 -0
- package/dist/learning/decision-log.js.map +1 -0
- package/dist/learning/deliverable-class.d.ts.map +1 -1
- package/dist/learning/deliverable-class.js +19 -0
- package/dist/learning/deliverable-class.js.map +1 -1
- package/dist/learning/deliverable-corpus.d.ts +117 -0
- package/dist/learning/deliverable-corpus.d.ts.map +1 -0
- package/dist/learning/deliverable-corpus.js +176 -0
- package/dist/learning/deliverable-corpus.js.map +1 -0
- package/dist/learning/error-repair.d.ts +45 -2
- package/dist/learning/error-repair.d.ts.map +1 -1
- package/dist/learning/error-repair.js +95 -0
- package/dist/learning/error-repair.js.map +1 -1
- package/dist/learning/exhaustion-report.d.ts +136 -0
- package/dist/learning/exhaustion-report.d.ts.map +1 -0
- package/dist/learning/exhaustion-report.js +239 -0
- package/dist/learning/exhaustion-report.js.map +1 -0
- package/dist/learning/failure-bookkeeping.d.ts +16 -0
- package/dist/learning/failure-bookkeeping.d.ts.map +1 -1
- package/dist/learning/failure-bookkeeping.js +51 -5
- package/dist/learning/failure-bookkeeping.js.map +1 -1
- package/dist/learning/gate-friction.d.ts +39 -0
- package/dist/learning/gate-friction.d.ts.map +1 -0
- package/dist/learning/gate-friction.js +91 -0
- package/dist/learning/gate-friction.js.map +1 -0
- package/dist/learning/harness-narration.d.ts +34 -0
- package/dist/learning/harness-narration.d.ts.map +1 -0
- package/dist/learning/harness-narration.js +58 -0
- package/dist/learning/harness-narration.js.map +1 -0
- package/dist/learning/hub-skill-catalog.d.ts.map +1 -1
- package/dist/learning/hub-skill-catalog.js +1 -2
- package/dist/learning/hub-skill-catalog.js.map +1 -1
- package/dist/learning/hybrid-router.d.ts +65 -0
- package/dist/learning/hybrid-router.d.ts.map +1 -1
- package/dist/learning/hybrid-router.js +186 -0
- package/dist/learning/hybrid-router.js.map +1 -1
- package/dist/learning/knowledge-base.d.ts +350 -0
- package/dist/learning/knowledge-base.d.ts.map +1 -0
- package/dist/learning/knowledge-base.js +906 -0
- package/dist/learning/knowledge-base.js.map +1 -0
- package/dist/learning/knowledge-eval.d.ts +171 -0
- package/dist/learning/knowledge-eval.d.ts.map +1 -0
- package/dist/learning/knowledge-eval.js +196 -0
- package/dist/learning/knowledge-eval.js.map +1 -0
- package/dist/learning/knowledge-turn.d.ts +92 -0
- package/dist/learning/knowledge-turn.d.ts.map +1 -0
- package/dist/learning/knowledge-turn.js +190 -0
- package/dist/learning/knowledge-turn.js.map +1 -0
- package/dist/learning/learned-commands.d.ts +64 -0
- package/dist/learning/learned-commands.d.ts.map +1 -0
- package/dist/learning/learned-commands.js +108 -0
- package/dist/learning/learned-commands.js.map +1 -0
- package/dist/learning/lexical-search.d.ts +50 -0
- package/dist/learning/lexical-search.d.ts.map +1 -0
- package/dist/learning/lexical-search.js +111 -0
- package/dist/learning/lexical-search.js.map +1 -0
- package/dist/learning/machine-facts.d.ts +71 -0
- package/dist/learning/machine-facts.d.ts.map +1 -0
- package/dist/learning/machine-facts.js +164 -0
- package/dist/learning/machine-facts.js.map +1 -0
- package/dist/learning/markdown-outline.d.ts +73 -0
- package/dist/learning/markdown-outline.d.ts.map +1 -0
- package/dist/learning/markdown-outline.js +136 -0
- package/dist/learning/markdown-outline.js.map +1 -0
- package/dist/learning/model-first-router.d.ts +33 -1
- package/dist/learning/model-first-router.d.ts.map +1 -1
- package/dist/learning/model-first-router.js +123 -9
- package/dist/learning/model-first-router.js.map +1 -1
- package/dist/learning/model-identity.d.ts +80 -0
- package/dist/learning/model-identity.d.ts.map +1 -0
- package/dist/learning/model-identity.js +115 -0
- package/dist/learning/model-identity.js.map +1 -0
- package/dist/learning/model-registry.d.ts +141 -2
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +324 -38
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/model-scoring.d.ts.map +1 -1
- package/dist/learning/model-scoring.js +8 -1
- package/dist/learning/model-scoring.js.map +1 -1
- package/dist/learning/model-selection.d.ts +2 -1
- package/dist/learning/model-selection.d.ts.map +1 -1
- package/dist/learning/model-selection.js +76 -2
- package/dist/learning/model-selection.js.map +1 -1
- package/dist/learning/outcome-observation.d.ts +49 -0
- package/dist/learning/outcome-observation.d.ts.map +1 -0
- package/dist/learning/outcome-observation.js +95 -0
- package/dist/learning/outcome-observation.js.map +1 -0
- package/dist/learning/pair-entitlement.d.ts +184 -0
- package/dist/learning/pair-entitlement.d.ts.map +1 -0
- package/dist/learning/pair-entitlement.js +214 -0
- package/dist/learning/pair-entitlement.js.map +1 -0
- package/dist/learning/project-docs.d.ts +83 -0
- package/dist/learning/project-docs.d.ts.map +1 -0
- package/dist/learning/project-docs.js +132 -0
- package/dist/learning/project-docs.js.map +1 -0
- package/dist/learning/provider-fallback.d.ts +23 -1
- package/dist/learning/provider-fallback.d.ts.map +1 -1
- package/dist/learning/provider-fallback.js +24 -0
- package/dist/learning/provider-fallback.js.map +1 -1
- package/dist/learning/quota-ledger.d.ts +13 -0
- package/dist/learning/quota-ledger.d.ts.map +1 -1
- package/dist/learning/quota-ledger.js +28 -0
- package/dist/learning/quota-ledger.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +65 -1
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +123 -1
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/requirement-probe.d.ts +55 -0
- package/dist/learning/requirement-probe.d.ts.map +1 -0
- package/dist/learning/requirement-probe.js +77 -0
- package/dist/learning/requirement-probe.js.map +1 -0
- package/dist/learning/resilient-call.d.ts +20 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +42 -4
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/response-usability.d.ts +85 -0
- package/dist/learning/response-usability.d.ts.map +1 -0
- package/dist/learning/response-usability.js +135 -0
- package/dist/learning/response-usability.js.map +1 -0
- package/dist/learning/router-bandit.d.ts +132 -0
- package/dist/learning/router-bandit.d.ts.map +1 -1
- package/dist/learning/router-bandit.js +253 -0
- package/dist/learning/router-bandit.js.map +1 -1
- package/dist/learning/routing-history.d.ts +41 -2
- package/dist/learning/routing-history.d.ts.map +1 -1
- package/dist/learning/routing-history.js.map +1 -1
- package/dist/learning/run-trace.d.ts +21 -0
- package/dist/learning/run-trace.d.ts.map +1 -1
- package/dist/learning/run-trace.js +38 -0
- package/dist/learning/run-trace.js.map +1 -1
- package/dist/learning/seeded-benchmark.d.ts +14 -0
- package/dist/learning/seeded-benchmark.d.ts.map +1 -1
- package/dist/learning/seeded-benchmark.js +43 -4
- package/dist/learning/seeded-benchmark.js.map +1 -1
- package/dist/learning/session-grant.d.ts +75 -0
- package/dist/learning/session-grant.d.ts.map +1 -0
- package/dist/learning/session-grant.js +112 -0
- package/dist/learning/session-grant.js.map +1 -0
- package/dist/learning/task-model-continuity.d.ts +73 -0
- package/dist/learning/task-model-continuity.d.ts.map +1 -0
- package/dist/learning/task-model-continuity.js +87 -0
- package/dist/learning/task-model-continuity.js.map +1 -0
- package/dist/learning/turn-feedback.d.ts +93 -0
- package/dist/learning/turn-feedback.d.ts.map +1 -0
- package/dist/learning/turn-feedback.js +127 -0
- package/dist/learning/turn-feedback.js.map +1 -0
- package/dist/learning/turn-report.d.ts +104 -2
- package/dist/learning/turn-report.d.ts.map +1 -1
- package/dist/learning/turn-report.js +161 -6
- package/dist/learning/turn-report.js.map +1 -1
- package/dist/learning/verdict-routing.d.ts +51 -0
- package/dist/learning/verdict-routing.d.ts.map +1 -0
- package/dist/learning/verdict-routing.js +122 -0
- package/dist/learning/verdict-routing.js.map +1 -0
- package/dist/mcp/client.d.ts.map +1 -1
- package/dist/mcp/client.js +5 -0
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/manager.d.ts +10 -0
- package/dist/mcp/manager.d.ts.map +1 -1
- package/dist/mcp/manager.js +20 -0
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/mcp-discovery.d.ts +34 -0
- package/dist/mcp/mcp-discovery.d.ts.map +1 -0
- package/dist/mcp/mcp-discovery.js +71 -0
- package/dist/mcp/mcp-discovery.js.map +1 -0
- package/dist/mcp/mcp-schema-cache.d.ts +17 -0
- package/dist/mcp/mcp-schema-cache.d.ts.map +1 -1
- package/dist/mcp/mcp-schema-cache.js +47 -3
- package/dist/mcp/mcp-schema-cache.js.map +1 -1
- package/dist/mcp/types.d.ts +28 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/security/secret-scan.d.ts +156 -0
- package/dist/security/secret-scan.d.ts.map +1 -0
- package/dist/security/secret-scan.js +525 -0
- package/dist/security/secret-scan.js.map +1 -0
- package/dist/tools/ask-user.d.ts.map +1 -1
- package/dist/tools/ask-user.js +4 -0
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/capability-registry.d.ts +150 -0
- package/dist/tools/capability-registry.d.ts.map +1 -0
- package/dist/tools/capability-registry.js +400 -0
- package/dist/tools/capability-registry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -1
- package/dist/tools/child-agent-runtime.js +19 -5
- package/dist/tools/child-agent-runtime.js.map +1 -1
- package/dist/tools/coding-tools.d.ts +17 -5
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +80 -11
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/command-memo.d.ts +116 -0
- package/dist/tools/command-memo.d.ts.map +1 -0
- package/dist/tools/command-memo.js +202 -0
- package/dist/tools/command-memo.js.map +1 -0
- package/dist/tools/git-tool.d.ts.map +1 -1
- package/dist/tools/git-tool.js +13 -3
- package/dist/tools/git-tool.js.map +1 -1
- package/dist/tools/harness-directive.d.ts +42 -0
- package/dist/tools/harness-directive.d.ts.map +1 -0
- package/dist/tools/harness-directive.js +45 -0
- package/dist/tools/harness-directive.js.map +1 -0
- package/dist/tools/loop-skill-hint.d.ts +74 -174
- package/dist/tools/loop-skill-hint.d.ts.map +1 -1
- package/dist/tools/loop-skill-hint.js +110 -536
- package/dist/tools/loop-skill-hint.js.map +1 -1
- package/dist/tools/mcp-client-tool.d.ts +2 -0
- package/dist/tools/mcp-client-tool.d.ts.map +1 -1
- package/dist/tools/mcp-client-tool.js +3 -0
- package/dist/tools/mcp-client-tool.js.map +1 -1
- package/dist/tools/modality/shared.d.ts +1 -4
- package/dist/tools/modality/shared.d.ts.map +1 -1
- package/dist/tools/modality/shared.js +7 -22
- package/dist/tools/modality/shared.js.map +1 -1
- package/dist/tools/plan-store.d.ts +44 -4
- package/dist/tools/plan-store.d.ts.map +1 -1
- package/dist/tools/plan-store.js +93 -9
- package/dist/tools/plan-store.js.map +1 -1
- package/dist/tools/registry.d.ts +76 -3
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +623 -15
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/remediation-ladder.d.ts +91 -0
- package/dist/tools/remediation-ladder.d.ts.map +1 -0
- package/dist/tools/remediation-ladder.js +316 -0
- package/dist/tools/remediation-ladder.js.map +1 -0
- package/dist/tools/run-cli.d.ts.map +1 -1
- package/dist/tools/run-cli.js +29 -4
- package/dist/tools/run-cli.js.map +1 -1
- package/dist/tools/run-terminal.d.ts +11 -0
- package/dist/tools/run-terminal.d.ts.map +1 -1
- package/dist/tools/run-terminal.js +289 -10
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/skills-hub.d.ts +7 -0
- package/dist/tools/skills-hub.d.ts.map +1 -1
- package/dist/tools/skills-hub.js +11 -2
- package/dist/tools/skills-hub.js.map +1 -1
- package/dist/tools/step-artifact.d.ts +35 -0
- package/dist/tools/step-artifact.d.ts.map +1 -0
- package/dist/tools/step-artifact.js +154 -0
- package/dist/tools/step-artifact.js.map +1 -0
- package/dist/tools/tool-loop.d.ts +327 -13
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +891 -66
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/toolsets.js +4 -4
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/tools/worktree.d.ts +11 -2
- package/dist/tools/worktree.d.ts.map +1 -1
- package/dist/tools/worktree.js +11 -2
- package/dist/tools/worktree.js.map +1 -1
- package/dist/utils/atomic-store.d.ts +53 -0
- package/dist/utils/atomic-store.d.ts.map +1 -0
- package/dist/utils/atomic-store.js +178 -0
- package/dist/utils/atomic-store.js.map +1 -0
- package/dist/utils/binary-probe.d.ts +25 -0
- package/dist/utils/binary-probe.d.ts.map +1 -0
- package/dist/utils/binary-probe.js +48 -0
- package/dist/utils/binary-probe.js.map +1 -0
- package/dist/utils/workspace-path.d.ts +50 -0
- package/dist/utils/workspace-path.d.ts.map +1 -0
- package/dist/utils/workspace-path.js +86 -0
- package/dist/utils/workspace-path.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +24 -0
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +38 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/project-context.d.ts +27 -2
- package/dist/web-dashboard/project-context.d.ts.map +1 -1
- package/dist/web-dashboard/project-context.js +32 -2
- package/dist/web-dashboard/project-context.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +40 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +733 -15
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +236 -1
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.d.ts +18 -2
- package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.js +94 -12
- package/dist/web-dashboard/workspace-guard.js.map +1 -1
- package/dist/web-dashboard/workspace-resolution.d.ts +87 -0
- package/dist/web-dashboard/workspace-resolution.d.ts.map +1 -0
- package/dist/web-dashboard/workspace-resolution.js +105 -0
- package/dist/web-dashboard/workspace-resolution.js.map +1 -0
- package/package.json +1 -1
- package/src/web-dashboard/public/assets/index-tK8Y2qHB.css +1 -0
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js +210 -0
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/src/web-dashboard/public/assets/index-BrZcYhy6.js +0 -207
- package/src/web-dashboard/public/assets/index-BrZcYhy6.js.map +0 -1
- package/src/web-dashboard/public/assets/index-DsWczTa6.css +0 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn outcome → router learning signal.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS. `RouterBandit` has always carried a measured-quality reward model — `testPassed`,
|
|
5
|
+
* `userAccepted`, `verificationPassed`, `qualityScore` — with arms for the provider AND the concrete
|
|
6
|
+
* model, and `applyReward` already folds all four into the reward. But nothing on the real path ever
|
|
7
|
+
* filled it in: `AutoModelRouter.recordOutcome` forwarded `undefined` to every arm, so the reward was
|
|
8
|
+
* a cost-adjusted coin flip on "the agent did not throw". That is the D2 defect one layer down — a
|
|
9
|
+
* response that was empty or useless still counted as a success for the purpose of learning.
|
|
10
|
+
*
|
|
11
|
+
* The harness ALREADY derives the honest signal: `TurnReport.verification` is built from recorded tool
|
|
12
|
+
* and plan evidence and can never be talked up by the model's narration. This module is the single
|
|
13
|
+
* pure translation between that verdict and the learning payload, so the mapping is ONE reviewable
|
|
14
|
+
* decision instead of a payload assembled ad hoc at each call site.
|
|
15
|
+
*
|
|
16
|
+
* WHAT IT DELIBERATELY DOES NOT DO.
|
|
17
|
+
* - It records NOTHING when the report carries no verdict about the model. A plain answer with no
|
|
18
|
+
* plan and no changes is not evidence of quality, and inventing a neutral sample for it would
|
|
19
|
+
* dilute the samples that are real.
|
|
20
|
+
* - It never GUESSES a `qualityScore`. It now carries one — but only from the FITTED
|
|
21
|
+
* acceptance model (`acceptance-model.ts`), which is a measured scale built from the user's own
|
|
22
|
+
* verdicts and which refuses to fit below its sample floor. On a machine with too few ratings the
|
|
23
|
+
* field is absent, exactly as before: a made-up number written into a learning record is worse
|
|
24
|
+
* than a missing one, because the record outlives whoever knows it was fabricated.
|
|
25
|
+
* (`NUVIRA_BANDIT_QUALITY=off` disables it outright.)
|
|
26
|
+
* - It never attributes an environmental failure to the model: a `blocked` turn is a wall the run hit,
|
|
27
|
+
* not a capability verdict.
|
|
28
|
+
*/
|
|
29
|
+
import { cachedAcceptanceFit, featuresFromReport, predictAcceptance, } from './acceptance-model.js';
|
|
30
|
+
import { envBuff } from '../config/paths.js';
|
|
31
|
+
/**
|
|
32
|
+
* The Q off-switch. Unset/empty = ON; an explicit OFF word disables the measured
|
|
33
|
+
* quality score so the router falls back to the derived signals it always had.
|
|
34
|
+
* (`NUVIRA_BANDIT_QUALITY=off`.)
|
|
35
|
+
*/
|
|
36
|
+
const OFF_WORDS = new Set(['0', 'false', 'off', 'no']);
|
|
37
|
+
export function banditQualityEnabled() {
|
|
38
|
+
const v = envBuff('BANDIT_QUALITY');
|
|
39
|
+
if (v === undefined || v === '')
|
|
40
|
+
return true;
|
|
41
|
+
return !OFF_WORDS.has(v.toLowerCase());
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The measured `qualityScore` for a turn, or `undefined`.
|
|
45
|
+
*
|
|
46
|
+
* `undefined` is the honest default: the fitted acceptance model refuses below
|
|
47
|
+
* its sample floor, so on a machine with too few ratings the router learns
|
|
48
|
+
* exactly what it learned before. A number is written ONLY when a trained model
|
|
49
|
+
* exists — never a guessed constant (see `DESIGN_CAPABILITY_BY_MEASUREMENT.md`).
|
|
50
|
+
*/
|
|
51
|
+
function qualityScoreForTurn(report, opts) {
|
|
52
|
+
const features = featuresFromReport(report);
|
|
53
|
+
if (opts.qualityScoreFor)
|
|
54
|
+
return opts.qualityScoreFor(features);
|
|
55
|
+
if (!banditQualityEnabled())
|
|
56
|
+
return undefined;
|
|
57
|
+
const fit = cachedAcceptanceFit();
|
|
58
|
+
return fit.ok ? predictAcceptance(fit.model, features) : undefined;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Map a turn's verification verdict to what the router should learn from it.
|
|
62
|
+
* Returns `null` when the turn carries no evidence about the model.
|
|
63
|
+
*/
|
|
64
|
+
export function turnOutcomeObservation(report, opts = {}) {
|
|
65
|
+
if (!report)
|
|
66
|
+
return null;
|
|
67
|
+
// ACCURACY EVIDENCE — the turn's own checks, when it ran any. `checksPassed` is
|
|
68
|
+
// tri-state precisely so that "nobody checked" contributes no `testPassed` sample:
|
|
69
|
+
// a plain question and a failing test suite must not teach the same lesson.
|
|
70
|
+
const checkData = report.checksPassed === undefined ? {} : { testPassed: report.checksPassed };
|
|
71
|
+
// MEASURED QUALITY — the one input derived signals cannot supply (was the work
|
|
72
|
+
// WANTED, not just "did it verify"). Present only when the acceptance model has
|
|
73
|
+
// trained on enough of the user's own verdicts; otherwise omitted entirely.
|
|
74
|
+
const quality = qualityScoreForTurn(report, opts);
|
|
75
|
+
const qualityData = quality === undefined ? {} : { qualityScore: quality };
|
|
76
|
+
switch (report.verification) {
|
|
77
|
+
case 'verified':
|
|
78
|
+
// A change was made and an observation followed it.
|
|
79
|
+
return { outcome: 'success', outcomeData: { verificationPassed: true, ...checkData, ...qualityData } };
|
|
80
|
+
case 'unverified':
|
|
81
|
+
// The turn ran, and its work could not be confirmed (an edit with no
|
|
82
|
+
// observation, an honesty flag, or an unobserved mutation). Booked as a
|
|
83
|
+
// success WITH `verificationPassed: false` rather than as a hard failure:
|
|
84
|
+
// the model DID answer, and the reward model's own penalty for an
|
|
85
|
+
// unverified success is the calibrated weight for exactly this shape.
|
|
86
|
+
// Calling it a failure outright would double-penalise one event.
|
|
87
|
+
return { outcome: 'success', outcomeData: { verificationPassed: false, ...checkData, ...qualityData } };
|
|
88
|
+
default:
|
|
89
|
+
// 'blocked' — a step could not complete (often environmental, not the
|
|
90
|
+
// model's doing). 'not-applicable' — nothing checkable happened. Neither
|
|
91
|
+
// is evidence about the model, so neither is recorded.
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=outcome-observation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outcome-observation.js","sourceRoot":"","sources":["../../src/learning/outcome-observation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAElB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAO7C;;;;GAIG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAEvD,MAAM,UAAU,oBAAoB;IAClC,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACzC,CAAC;AAUD;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAC1B,MAAkB,EAClB,IAA4B;IAE5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAC;IAClC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAqC,EACrC,OAA+B,EAAE;IAEjC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,gFAAgF;IAChF,mFAAmF;IACnF,4EAA4E;IAC5E,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;IAC/F,+EAA+E;IAC/E,gFAAgF;IAChF,4EAA4E;IAC5E,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IAC3E,QAAQ,MAAM,CAAC,YAAY,EAAE,CAAC;QAC5B,KAAK,UAAU;YACb,oDAAoD;YACpD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,SAAS,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;QACzG,KAAK,YAAY;YACf,qEAAqE;YACrE,wEAAwE;YACxE,0EAA0E;YAC1E,kEAAkE;YAClE,sEAAsE;YACtE,iEAAiE;YACjE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;QAC1G;YACE,sEAAsE;YACtE,yEAAyE;YACzE,uDAAuD;YACvD,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PAIR ENTITLEMENT — of two providers that both list the same model, which one
|
|
3
|
+
* can actually serve it RIGHT NOW?
|
|
4
|
+
*
|
|
5
|
+
* THE DEFECT THIS CLOSES (reported 2026-10-07). Four providers list a DeepSeek
|
|
6
|
+
* model. One key genuinely has access to it; on the others the account has no
|
|
7
|
+
* model access and no free tokens. Ranking is per MODEL, so all four twins
|
|
8
|
+
* present the same capability rank — and the router, ordering on rank (and, on
|
|
9
|
+
* a tie, on whichever provider it happened to score first), could spend the
|
|
10
|
+
* turn's first call on a pair the registry had ALREADY recorded as refused:
|
|
11
|
+
* a `402 Insufficient credits` / `403` / `credit-exhausted` round trip, then a
|
|
12
|
+
* failover, then the turn finally starts. Measured in run D of this programme:
|
|
13
|
+
* a strict pin at `openrouter/deepseek/deepseek-v4.1-flash` failed in 6 SECONDS
|
|
14
|
+
* with `402 Insufficient credits` — while `deepseek/deepseek-flash`, the same
|
|
15
|
+
* model on a funded account, sat in the pool.
|
|
16
|
+
*
|
|
17
|
+
* The registry already knew. `ModelRegistryEntry` carries `status`,
|
|
18
|
+
* `lastError`, `deadPair` and `quotaParkedUntil` for every provider × model
|
|
19
|
+
* pair, and two predicates in `model-registry.ts` interpret them
|
|
20
|
+
* (`isEntitlementFailure`, `isNonexistentPair`). What did not exist was a single
|
|
21
|
+
* answer to "may the router call THIS PAIR", asked before the call instead of
|
|
22
|
+
* after it.
|
|
23
|
+
*
|
|
24
|
+
* ─── DOCTRINE (read before changing the order below) ───────────────────────
|
|
25
|
+
*
|
|
26
|
+
* 1. **The verdict is per PAIR, never per model.** `openrouter`'s exhausted
|
|
27
|
+
* credit balance and `deepseek`'s funded account are facts about two
|
|
28
|
+
* different ACCOUNTS. Two twins may share a canonical model id and still
|
|
29
|
+
* have opposite verdicts, and each verdict is read from ITS OWN registry row.
|
|
30
|
+
* Nothing here ever infers "this provider is funded because its twin is" —
|
|
31
|
+
* that is the F6 defect (an availability verdict erased by unrelated
|
|
32
|
+
* evidence) wearing a new hat.
|
|
33
|
+
* 2. **A refusal is a NO, and it is FINAL while a funded alternative exists.**
|
|
34
|
+
* `refused` means the account cannot serve this pairing: no credits, no
|
|
35
|
+
* billing, a rejected key, or the id does not exist on that endpoint. None
|
|
36
|
+
* of those are repaired by retrying, so a refused pair is never picked while
|
|
37
|
+
* anything else can be. `stalled` (a quota park, or proof that aged out) is
|
|
38
|
+
* the opposite: it clears by itself, so it stays eligible and simply sinks.
|
|
39
|
+
* 3. **Never dead-end.** This module never REMOVES a candidate — it orders them
|
|
40
|
+
* (`orderByEntitlement` is a stable partition). If every provider refuses the
|
|
41
|
+
* model, the refused pairs are still there, in their old relative order, and
|
|
42
|
+
* the router can still try them. "Use every model we can actually call;
|
|
43
|
+
* reject only when nothing is left" survives.
|
|
44
|
+
* 4. **Ties go to the funded twin.** The user's rule, verbatim: "the rank of a
|
|
45
|
+
* model can be the same across providers, but the agent should only pick the
|
|
46
|
+
* one which has genuine token budget available". Because the ordering is a
|
|
47
|
+
* partition applied AFTER scoring, a funded twin outranks a refused twin even
|
|
48
|
+
* when the refused twin scored higher — a rank advantage cannot buy a call
|
|
49
|
+
* that is certain to fail.
|
|
50
|
+
*
|
|
51
|
+
* The labels below are printed (`model explain`, the fallback chain), so an
|
|
52
|
+
* operator can see WHY a twin was passed over instead of having to guess.
|
|
53
|
+
*/
|
|
54
|
+
/**
|
|
55
|
+
* What the registry says about ONE provider × model pair's right to be called.
|
|
56
|
+
*
|
|
57
|
+
* Four states, not a boolean, because they need OPPOSITE handling and a
|
|
58
|
+
* two-valued answer would flatten them into one: `refused` is a permanent no
|
|
59
|
+
* (skip it), `stalled` is a temporary no (it may recover, so keep it), `unknown`
|
|
60
|
+
* is not a failure at all (never tried), and `funded` is a proven yes.
|
|
61
|
+
*/
|
|
62
|
+
export type PairEntitlement =
|
|
63
|
+
/** Verified and usable right now — a real call proved THIS ACCOUNT serves THIS model. */
|
|
64
|
+
'funded'
|
|
65
|
+
/** No entry, or an unverified one. Nothing has ever been tried: an unknown, not a failure. */
|
|
66
|
+
| 'unknown'
|
|
67
|
+
/** Provably served before, but not right now, for a reason that clears by itself (quota park, stale proof, a transient failure). */
|
|
68
|
+
| 'stalled'
|
|
69
|
+
/** The account was REFUSED this pairing: credit-exhausted / auth / billing / 40x, or the id does not exist on that endpoint. */
|
|
70
|
+
| 'refused';
|
|
71
|
+
/** The fields of a registry row this classifier reads. Deliberately minimal. */
|
|
72
|
+
export interface EntitlementInput {
|
|
73
|
+
status?: string;
|
|
74
|
+
lastError?: string;
|
|
75
|
+
deadPair?: boolean;
|
|
76
|
+
quotaParkedUntil?: number;
|
|
77
|
+
providerParked?: boolean;
|
|
78
|
+
lastVerifiedAt?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Classify one pair. Pure and total — never throws, never returns undefined.
|
|
82
|
+
*
|
|
83
|
+
* CLAUSE ORDER IS LOAD-BEARING, and `status` comes FIRST — exactly as in
|
|
84
|
+
* `classifyReachability`. That is not cosmetic; getting it backwards creates a
|
|
85
|
+
* brand-new false refusal:
|
|
86
|
+
*
|
|
87
|
+
* - `verified` is a LATCH. Two different writes can leave a row `verified`
|
|
88
|
+
* while an old refusal still sits in `lastError`: `markVerified`
|
|
89
|
+
* deliberately PRESERVES `lastError` across a success (it rebuilds the entry
|
|
90
|
+
* field by field and keeps `existing?.lastError`), and `recordCall` succeeds
|
|
91
|
+
* through `markVerified`. So after a user tops up their credits and the next
|
|
92
|
+
* call works, the row is `verified` + `"credit-exhausted (…)"` — the model is
|
|
93
|
+
* being served RIGHT NOW.
|
|
94
|
+
* - Checking `isEntitlementFailure(lastError)` before `status` would call that
|
|
95
|
+
* pair refused and skip the funded account we just proved works. It is the
|
|
96
|
+
* same mistake in the other direction (a stale verdict outranking fresh
|
|
97
|
+
* evidence), so an entitlement refusal only counts while the entry is still
|
|
98
|
+
* sitting in the state that refusal produced — the registry's own guard,
|
|
99
|
+
* `existing?.status === 'unavailable' && isEntitlementFailure(...)` in
|
|
100
|
+
* `markListed`.
|
|
101
|
+
*
|
|
102
|
+
* The clauses:
|
|
103
|
+
*
|
|
104
|
+
* 1. A NONEXISTENT pair is refused whatever the status says: `deadPair` is an
|
|
105
|
+
* explicit "this id does not exist on this endpoint" and the provider's own
|
|
106
|
+
* model list is what clears it. (`isNonexistentPair` also covers an
|
|
107
|
+
* `unavailable` row whose recorded reason is a not-found — legacy data.)
|
|
108
|
+
* 2. `unverified` / absent is `unknown` — never a failure. Most of any registry
|
|
109
|
+
* is here, and treating "never tried" as "cannot work" would empty the pool.
|
|
110
|
+
* 3. `unavailable` + an entitlement reason is `refused` (credit-exhausted /
|
|
111
|
+
* auth / billing / 40x — what run D hit). Any other `unavailable` reason is
|
|
112
|
+
* `stalled`: rate limits, timeouts and 5xx are transient by the registry's
|
|
113
|
+
* own doctrine and must not be treated as a permanent no.
|
|
114
|
+
* 4. A `verified` entry is `funded` unless a MODEL-level park or a stale proof
|
|
115
|
+
* holds it back. A PROVIDER-level park does not count — that is the Gemini
|
|
116
|
+
* parking bug, and `isUsable()` skips it for proven models too.
|
|
117
|
+
*/
|
|
118
|
+
export declare function classifyPairEntitlement(entry: EntitlementInput | undefined, now?: number): PairEntitlement;
|
|
119
|
+
/**
|
|
120
|
+
* The pick order: funded, then never-tried, then stalled, then refused.
|
|
121
|
+
*
|
|
122
|
+
* `unknown` deliberately outranks `stalled`: `stalled` is "no budget right
|
|
123
|
+
* now" (the exact thing this module exists to avoid spending a round on), while
|
|
124
|
+
* `unknown` may simply work. This also matches how the model scorer already
|
|
125
|
+
* weights the two (`quotaAvailability` 0.6 for unverified vs 0.0 for parked).
|
|
126
|
+
*/
|
|
127
|
+
export declare const ENTITLEMENT_ORDER: Record<PairEntitlement, number>;
|
|
128
|
+
/**
|
|
129
|
+
* Stable partition of candidates by entitlement — funded pairs first, refused
|
|
130
|
+
* pairs last, everything else untouched inside its group (and the input array
|
|
131
|
+
* never mutated). A PARTITION and not a filter: see doctrine 3 (never dead-end).
|
|
132
|
+
*/
|
|
133
|
+
export declare function orderByEntitlement<T>(items: readonly T[], of: (item: T) => PairEntitlement): T[];
|
|
134
|
+
/** Short chip for a verdict — CLI/dashboard labels. */
|
|
135
|
+
export declare const ENTITLEMENT_LABEL: Record<PairEntitlement, string>;
|
|
136
|
+
/**
|
|
137
|
+
* One sentence naming the EVIDENCE, not just the verdict — an operator reading
|
|
138
|
+
* `model explain` has to be able to tell a refused account from an untried one.
|
|
139
|
+
*/
|
|
140
|
+
export declare function entitlementNote(entitlement: PairEntitlement, entry?: EntitlementInput): string;
|
|
141
|
+
/**
|
|
142
|
+
* The model id two rows must share before they are treated as the same model
|
|
143
|
+
* offered by different providers — the "twins" the user's rule is about.
|
|
144
|
+
*
|
|
145
|
+
* A1 (2026-10-07): the rule is now `learning/model-identity.ts` — an EXACT
|
|
146
|
+
* comparison against a bare or `vendor/`-prefixed id, WIDENED by the DECLARED
|
|
147
|
+
* alias table and never by similarity. That widening is what relates
|
|
148
|
+
* `openrouter/deepseek/deepseek-v4.1-flash` to `deepseek/deepseek-flash` (the two
|
|
149
|
+
* rows a run-D 402 pin needed related), while `deepseek-flash` and
|
|
150
|
+
* `deepseek-v4-flash` stay separate because no declaration relates them.
|
|
151
|
+
*
|
|
152
|
+
* Grouping is the only thing identity does here. A verdict is still read from
|
|
153
|
+
* each twin's OWN row — see the doctrine at the top of this file.
|
|
154
|
+
*/
|
|
155
|
+
export declare function twinKey(model: string): string;
|
|
156
|
+
/** Do these two model ids name the same model served by different providers? */
|
|
157
|
+
export declare function areTwins(a: string, b: string): boolean;
|
|
158
|
+
/** One twin in a same-model group, with the verdict read from ITS OWN row. */
|
|
159
|
+
export interface TwinVerdict<T> {
|
|
160
|
+
item: T;
|
|
161
|
+
provider: string;
|
|
162
|
+
model: string;
|
|
163
|
+
entitlement: PairEntitlement;
|
|
164
|
+
note: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolve a group of SAME-MODEL twins to the one the router may call, and say
|
|
168
|
+
* what was passed over and why.
|
|
169
|
+
*
|
|
170
|
+
* This is the user's requirement as a function: identical ranks, one funded
|
|
171
|
+
* twin, so the funded twin is the only acceptable pick — and each twin's verdict
|
|
172
|
+
* comes from its own registry row (doctrine 1). The refused ones come back in
|
|
173
|
+
* `passedOver` so the caller can PRINT them ("`openrouter` refuses this model —
|
|
174
|
+
* credit-exhausted") instead of silently pretending they were never there.
|
|
175
|
+
*
|
|
176
|
+
* Never returns nothing when the group is non-empty: if EVERY twin is refused,
|
|
177
|
+
* the first is still chosen (doctrine 3 — a certain failure beats no attempt at
|
|
178
|
+
* all only when there is genuinely nothing else, and the caller decides).
|
|
179
|
+
*/
|
|
180
|
+
export declare function resolveFundedTwin<T>(twins: readonly TwinVerdict<T>[]): {
|
|
181
|
+
chosen?: TwinVerdict<T>;
|
|
182
|
+
passedOver: TwinVerdict<T>[];
|
|
183
|
+
};
|
|
184
|
+
//# sourceMappingURL=pair-entitlement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pair-entitlement.d.ts","sourceRoot":"","sources":["../../src/learning/pair-entitlement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAKH;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe;AACzB,yFAAyF;AACvF,QAAQ;AACV,8FAA8F;GAC5F,SAAS;AACX,oIAAoI;GAClI,SAAS;AACX,gIAAgI;GAC9H,SAAS,CAAC;AAEd,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,gBAAgB,GAAG,SAAS,EACnC,GAAG,GAAE,MAAmB,GACvB,eAAe,CAgBjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAK7D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,eAAe,GAAG,CAAC,EAAE,CAIhG;AAED,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAK7D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAmB9F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,KAAK,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,GAC/B;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,CAO3D"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PAIR ENTITLEMENT — of two providers that both list the same model, which one
|
|
3
|
+
* can actually serve it RIGHT NOW?
|
|
4
|
+
*
|
|
5
|
+
* THE DEFECT THIS CLOSES (reported 2026-10-07). Four providers list a DeepSeek
|
|
6
|
+
* model. One key genuinely has access to it; on the others the account has no
|
|
7
|
+
* model access and no free tokens. Ranking is per MODEL, so all four twins
|
|
8
|
+
* present the same capability rank — and the router, ordering on rank (and, on
|
|
9
|
+
* a tie, on whichever provider it happened to score first), could spend the
|
|
10
|
+
* turn's first call on a pair the registry had ALREADY recorded as refused:
|
|
11
|
+
* a `402 Insufficient credits` / `403` / `credit-exhausted` round trip, then a
|
|
12
|
+
* failover, then the turn finally starts. Measured in run D of this programme:
|
|
13
|
+
* a strict pin at `openrouter/deepseek/deepseek-v4.1-flash` failed in 6 SECONDS
|
|
14
|
+
* with `402 Insufficient credits` — while `deepseek/deepseek-flash`, the same
|
|
15
|
+
* model on a funded account, sat in the pool.
|
|
16
|
+
*
|
|
17
|
+
* The registry already knew. `ModelRegistryEntry` carries `status`,
|
|
18
|
+
* `lastError`, `deadPair` and `quotaParkedUntil` for every provider × model
|
|
19
|
+
* pair, and two predicates in `model-registry.ts` interpret them
|
|
20
|
+
* (`isEntitlementFailure`, `isNonexistentPair`). What did not exist was a single
|
|
21
|
+
* answer to "may the router call THIS PAIR", asked before the call instead of
|
|
22
|
+
* after it.
|
|
23
|
+
*
|
|
24
|
+
* ─── DOCTRINE (read before changing the order below) ───────────────────────
|
|
25
|
+
*
|
|
26
|
+
* 1. **The verdict is per PAIR, never per model.** `openrouter`'s exhausted
|
|
27
|
+
* credit balance and `deepseek`'s funded account are facts about two
|
|
28
|
+
* different ACCOUNTS. Two twins may share a canonical model id and still
|
|
29
|
+
* have opposite verdicts, and each verdict is read from ITS OWN registry row.
|
|
30
|
+
* Nothing here ever infers "this provider is funded because its twin is" —
|
|
31
|
+
* that is the F6 defect (an availability verdict erased by unrelated
|
|
32
|
+
* evidence) wearing a new hat.
|
|
33
|
+
* 2. **A refusal is a NO, and it is FINAL while a funded alternative exists.**
|
|
34
|
+
* `refused` means the account cannot serve this pairing: no credits, no
|
|
35
|
+
* billing, a rejected key, or the id does not exist on that endpoint. None
|
|
36
|
+
* of those are repaired by retrying, so a refused pair is never picked while
|
|
37
|
+
* anything else can be. `stalled` (a quota park, or proof that aged out) is
|
|
38
|
+
* the opposite: it clears by itself, so it stays eligible and simply sinks.
|
|
39
|
+
* 3. **Never dead-end.** This module never REMOVES a candidate — it orders them
|
|
40
|
+
* (`orderByEntitlement` is a stable partition). If every provider refuses the
|
|
41
|
+
* model, the refused pairs are still there, in their old relative order, and
|
|
42
|
+
* the router can still try them. "Use every model we can actually call;
|
|
43
|
+
* reject only when nothing is left" survives.
|
|
44
|
+
* 4. **Ties go to the funded twin.** The user's rule, verbatim: "the rank of a
|
|
45
|
+
* model can be the same across providers, but the agent should only pick the
|
|
46
|
+
* one which has genuine token budget available". Because the ordering is a
|
|
47
|
+
* partition applied AFTER scoring, a funded twin outranks a refused twin even
|
|
48
|
+
* when the refused twin scored higher — a rank advantage cannot buy a call
|
|
49
|
+
* that is certain to fail.
|
|
50
|
+
*
|
|
51
|
+
* The labels below are printed (`model explain`, the fallback chain), so an
|
|
52
|
+
* operator can see WHY a twin was passed over instead of having to guess.
|
|
53
|
+
*/
|
|
54
|
+
import { DEFAULT_STALE_MS, isEntitlementFailure, isNonexistentPair } from './model-registry.js';
|
|
55
|
+
import { identityKey, sameModel } from './model-identity.js';
|
|
56
|
+
/**
|
|
57
|
+
* Classify one pair. Pure and total — never throws, never returns undefined.
|
|
58
|
+
*
|
|
59
|
+
* CLAUSE ORDER IS LOAD-BEARING, and `status` comes FIRST — exactly as in
|
|
60
|
+
* `classifyReachability`. That is not cosmetic; getting it backwards creates a
|
|
61
|
+
* brand-new false refusal:
|
|
62
|
+
*
|
|
63
|
+
* - `verified` is a LATCH. Two different writes can leave a row `verified`
|
|
64
|
+
* while an old refusal still sits in `lastError`: `markVerified`
|
|
65
|
+
* deliberately PRESERVES `lastError` across a success (it rebuilds the entry
|
|
66
|
+
* field by field and keeps `existing?.lastError`), and `recordCall` succeeds
|
|
67
|
+
* through `markVerified`. So after a user tops up their credits and the next
|
|
68
|
+
* call works, the row is `verified` + `"credit-exhausted (…)"` — the model is
|
|
69
|
+
* being served RIGHT NOW.
|
|
70
|
+
* - Checking `isEntitlementFailure(lastError)` before `status` would call that
|
|
71
|
+
* pair refused and skip the funded account we just proved works. It is the
|
|
72
|
+
* same mistake in the other direction (a stale verdict outranking fresh
|
|
73
|
+
* evidence), so an entitlement refusal only counts while the entry is still
|
|
74
|
+
* sitting in the state that refusal produced — the registry's own guard,
|
|
75
|
+
* `existing?.status === 'unavailable' && isEntitlementFailure(...)` in
|
|
76
|
+
* `markListed`.
|
|
77
|
+
*
|
|
78
|
+
* The clauses:
|
|
79
|
+
*
|
|
80
|
+
* 1. A NONEXISTENT pair is refused whatever the status says: `deadPair` is an
|
|
81
|
+
* explicit "this id does not exist on this endpoint" and the provider's own
|
|
82
|
+
* model list is what clears it. (`isNonexistentPair` also covers an
|
|
83
|
+
* `unavailable` row whose recorded reason is a not-found — legacy data.)
|
|
84
|
+
* 2. `unverified` / absent is `unknown` — never a failure. Most of any registry
|
|
85
|
+
* is here, and treating "never tried" as "cannot work" would empty the pool.
|
|
86
|
+
* 3. `unavailable` + an entitlement reason is `refused` (credit-exhausted /
|
|
87
|
+
* auth / billing / 40x — what run D hit). Any other `unavailable` reason is
|
|
88
|
+
* `stalled`: rate limits, timeouts and 5xx are transient by the registry's
|
|
89
|
+
* own doctrine and must not be treated as a permanent no.
|
|
90
|
+
* 4. A `verified` entry is `funded` unless a MODEL-level park or a stale proof
|
|
91
|
+
* holds it back. A PROVIDER-level park does not count — that is the Gemini
|
|
92
|
+
* parking bug, and `isUsable()` skips it for proven models too.
|
|
93
|
+
*/
|
|
94
|
+
export function classifyPairEntitlement(entry, now = Date.now()) {
|
|
95
|
+
if (!entry)
|
|
96
|
+
return 'unknown';
|
|
97
|
+
// 1. "This model does not exist here" — provider-declared, status-independent.
|
|
98
|
+
if (isNonexistentPair(entry))
|
|
99
|
+
return 'refused';
|
|
100
|
+
const status = entry.status ?? 'unverified';
|
|
101
|
+
// 2. Never tried — an unknown, not a refusal.
|
|
102
|
+
if (status === 'unverified')
|
|
103
|
+
return 'unknown';
|
|
104
|
+
// 3. Unavailable: refused if the ACCOUNT was refused, otherwise a no for now.
|
|
105
|
+
if (status !== 'verified') {
|
|
106
|
+
return isEntitlementFailure(entry.lastError) ? 'refused' : 'stalled';
|
|
107
|
+
}
|
|
108
|
+
// 4. Verified: only a MODEL-level park or an aged-out proof holds it back.
|
|
109
|
+
const parkedUntil = entry.quotaParkedUntil ?? 0;
|
|
110
|
+
if (parkedUntil > now && entry.providerParked === false)
|
|
111
|
+
return 'stalled';
|
|
112
|
+
if (now - (entry.lastVerifiedAt ?? 0) > DEFAULT_STALE_MS)
|
|
113
|
+
return 'stalled';
|
|
114
|
+
return 'funded';
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The pick order: funded, then never-tried, then stalled, then refused.
|
|
118
|
+
*
|
|
119
|
+
* `unknown` deliberately outranks `stalled`: `stalled` is "no budget right
|
|
120
|
+
* now" (the exact thing this module exists to avoid spending a round on), while
|
|
121
|
+
* `unknown` may simply work. This also matches how the model scorer already
|
|
122
|
+
* weights the two (`quotaAvailability` 0.6 for unverified vs 0.0 for parked).
|
|
123
|
+
*/
|
|
124
|
+
export const ENTITLEMENT_ORDER = {
|
|
125
|
+
funded: 0,
|
|
126
|
+
unknown: 1,
|
|
127
|
+
stalled: 2,
|
|
128
|
+
refused: 3,
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Stable partition of candidates by entitlement — funded pairs first, refused
|
|
132
|
+
* pairs last, everything else untouched inside its group (and the input array
|
|
133
|
+
* never mutated). A PARTITION and not a filter: see doctrine 3 (never dead-end).
|
|
134
|
+
*/
|
|
135
|
+
export function orderByEntitlement(items, of) {
|
|
136
|
+
const buckets = { funded: [], unknown: [], stalled: [], refused: [] };
|
|
137
|
+
for (const item of items)
|
|
138
|
+
buckets[of(item)].push(item);
|
|
139
|
+
return [...buckets.funded, ...buckets.unknown, ...buckets.stalled, ...buckets.refused];
|
|
140
|
+
}
|
|
141
|
+
/** Short chip for a verdict — CLI/dashboard labels. */
|
|
142
|
+
export const ENTITLEMENT_LABEL = {
|
|
143
|
+
funded: '✅ funded',
|
|
144
|
+
unknown: '❔ untried',
|
|
145
|
+
stalled: '⏸ stalled',
|
|
146
|
+
refused: '⛔ refused',
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* One sentence naming the EVIDENCE, not just the verdict — an operator reading
|
|
150
|
+
* `model explain` has to be able to tell a refused account from an untried one.
|
|
151
|
+
*/
|
|
152
|
+
export function entitlementNote(entitlement, entry) {
|
|
153
|
+
switch (entitlement) {
|
|
154
|
+
case 'funded':
|
|
155
|
+
return 'proven to work on this account, and nothing is blocking it right now';
|
|
156
|
+
case 'unknown':
|
|
157
|
+
return 'never tried on this provider — no evidence either way (not a failure)';
|
|
158
|
+
case 'stalled': {
|
|
159
|
+
const parkedUntil = entry?.quotaParkedUntil ?? 0;
|
|
160
|
+
if (parkedUntil > Date.now()) {
|
|
161
|
+
const mins = Math.max(1, Math.round((parkedUntil - Date.now()) / 60_000));
|
|
162
|
+
return `proven to work, but parked on its own quota window — free again in ~${mins}m`;
|
|
163
|
+
}
|
|
164
|
+
return 'proven to work once, but not provably servable right now (stale proof or a transient failure)';
|
|
165
|
+
}
|
|
166
|
+
case 'refused':
|
|
167
|
+
return isNonexistentPair(entry ?? {})
|
|
168
|
+
? 'the provider says this model does not exist on this endpoint'
|
|
169
|
+
: `this account was refused: ${entry?.lastError ?? 'no reason recorded'}`;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The model id two rows must share before they are treated as the same model
|
|
174
|
+
* offered by different providers — the "twins" the user's rule is about.
|
|
175
|
+
*
|
|
176
|
+
* A1 (2026-10-07): the rule is now `learning/model-identity.ts` — an EXACT
|
|
177
|
+
* comparison against a bare or `vendor/`-prefixed id, WIDENED by the DECLARED
|
|
178
|
+
* alias table and never by similarity. That widening is what relates
|
|
179
|
+
* `openrouter/deepseek/deepseek-v4.1-flash` to `deepseek/deepseek-flash` (the two
|
|
180
|
+
* rows a run-D 402 pin needed related), while `deepseek-flash` and
|
|
181
|
+
* `deepseek-v4-flash` stay separate because no declaration relates them.
|
|
182
|
+
*
|
|
183
|
+
* Grouping is the only thing identity does here. A verdict is still read from
|
|
184
|
+
* each twin's OWN row — see the doctrine at the top of this file.
|
|
185
|
+
*/
|
|
186
|
+
export function twinKey(model) {
|
|
187
|
+
return identityKey(model);
|
|
188
|
+
}
|
|
189
|
+
/** Do these two model ids name the same model served by different providers? */
|
|
190
|
+
export function areTwins(a, b) {
|
|
191
|
+
return sameModel(a, b);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Resolve a group of SAME-MODEL twins to the one the router may call, and say
|
|
195
|
+
* what was passed over and why.
|
|
196
|
+
*
|
|
197
|
+
* This is the user's requirement as a function: identical ranks, one funded
|
|
198
|
+
* twin, so the funded twin is the only acceptable pick — and each twin's verdict
|
|
199
|
+
* comes from its own registry row (doctrine 1). The refused ones come back in
|
|
200
|
+
* `passedOver` so the caller can PRINT them ("`openrouter` refuses this model —
|
|
201
|
+
* credit-exhausted") instead of silently pretending they were never there.
|
|
202
|
+
*
|
|
203
|
+
* Never returns nothing when the group is non-empty: if EVERY twin is refused,
|
|
204
|
+
* the first is still chosen (doctrine 3 — a certain failure beats no attempt at
|
|
205
|
+
* all only when there is genuinely nothing else, and the caller decides).
|
|
206
|
+
*/
|
|
207
|
+
export function resolveFundedTwin(twins) {
|
|
208
|
+
if (twins.length === 0)
|
|
209
|
+
return { passedOver: [] };
|
|
210
|
+
const ordered = [...twins].sort((a, b) => ENTITLEMENT_ORDER[a.entitlement] - ENTITLEMENT_ORDER[b.entitlement]);
|
|
211
|
+
const [chosen, ...passedOver] = ordered;
|
|
212
|
+
return { chosen, passedOver };
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=pair-entitlement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pair-entitlement.js","sourceRoot":"","sources":["../../src/learning/pair-entitlement.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PROJECT DOCUMENTATION (software deliverables).
|
|
3
|
+
*
|
|
4
|
+
* The gap this closes: a software build produced CODE and stopped. The
|
|
5
|
+
* documents a real project ships — a README, a changelog that grows with each
|
|
6
|
+
* change, a short architecture note with a diagram, and (for a library/service)
|
|
7
|
+
* usage + API docs — were only produced when the user named them, which is
|
|
8
|
+
* exactly backwards: a user should not have to ask a "world-class developer" to
|
|
9
|
+
* write down what it built.
|
|
10
|
+
*
|
|
11
|
+
* Two rules keep this from becoming noise:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Software only.** This module is consulted ONLY for a `code` deliverable
|
|
14
|
+
* that is not authored (`deliverable-class.ts` already separates a poem
|
|
15
|
+
* from a program). Nobody wants a README and an ARCHITECTURE.md for
|
|
16
|
+
* "write me a poem about rain" — the classifier decides, and this guidance
|
|
17
|
+
* is never appended to an authored ask.
|
|
18
|
+
* 2. **Proportionate.** A README and a CHANGELOG are expected of every
|
|
19
|
+
* software deliverable; the heavier documents (architecture, API reference,
|
|
20
|
+
* contributing guide) are asked for only when the shape warrants them —
|
|
21
|
+
* a multi-component or library/service build, or an explicit request for
|
|
22
|
+
* docs. A one-file script still gets a README; it is not asked to invent an
|
|
23
|
+
* architecture diagram.
|
|
24
|
+
*
|
|
25
|
+
* It also encodes the maintenance rule the user cares about: an EXISTING
|
|
26
|
+
* document is UPDATED in place (CHANGELOG gets a new entry at the top), never
|
|
27
|
+
* shadowed by a second file — a project with two changelogs is worse than one
|
|
28
|
+
* with none.
|
|
29
|
+
*
|
|
30
|
+
* Pure and side-effect free: every input is data, so it is unit-testable and can
|
|
31
|
+
* be appended to any prompt without touching the filesystem.
|
|
32
|
+
*/
|
|
33
|
+
/** The canonical documents a software project ships, in priority order. */
|
|
34
|
+
export interface ProjectDocArtifact {
|
|
35
|
+
/** Project-relative path the document lives at. */
|
|
36
|
+
path: string;
|
|
37
|
+
/** What it is FOR — handed to the model so the document has a job. */
|
|
38
|
+
purpose: string;
|
|
39
|
+
/** Required of every software deliverable (README, CHANGELOG). */
|
|
40
|
+
always: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare const PROJECT_DOC_ARTIFACTS: readonly ProjectDocArtifact[];
|
|
43
|
+
/** What we know about the deliverable, from the goal + project assessment. */
|
|
44
|
+
export interface ProjectDocShape {
|
|
45
|
+
/**
|
|
46
|
+
* True when the workspace has no project yet (a scaffold). A greenfield build
|
|
47
|
+
* gets the full proportionate set rather than only the always-on pair.
|
|
48
|
+
*/
|
|
49
|
+
greenfield?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* A library, package, SDK or service — a thing other code CONSUMES — rather
|
|
52
|
+
* than an end-user app. Its public surface must be documented.
|
|
53
|
+
*/
|
|
54
|
+
isLibraryOrService?: boolean;
|
|
55
|
+
/** The project already exposes tests (or the agent is expected to write them). */
|
|
56
|
+
hasTests?: boolean;
|
|
57
|
+
/** Names the user explicitly asked for docs ("with documentation", "API docs"). */
|
|
58
|
+
docsRequested?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Documents that ALREADY exist in the workspace (project-relative paths).
|
|
61
|
+
* These are UPDATED in place, never duplicated.
|
|
62
|
+
*/
|
|
63
|
+
existingDocs?: readonly string[];
|
|
64
|
+
}
|
|
65
|
+
/** The always-on pair, plus the heavier docs a bigger build warrants. */
|
|
66
|
+
export declare function requiredProjectDocs(shape?: ProjectDocShape): string[];
|
|
67
|
+
/**
|
|
68
|
+
* Does the goal name something other code CONSUMES (a library, package, SDK,
|
|
69
|
+
* CLI, service, plugin) rather than an end-user app? A consumed surface has a
|
|
70
|
+
* public API worth documenting; an app does not need an API reference.
|
|
71
|
+
*/
|
|
72
|
+
export declare function looksLikeLibraryOrService(goal: string): boolean;
|
|
73
|
+
/** The required docs that do NOT yet exist on disk (the ones to CREATE). */
|
|
74
|
+
export declare function missingProjectDocs(shape?: ProjectDocShape): string[];
|
|
75
|
+
/** The required docs that already exist (the ones to UPDATE, not recreate). */
|
|
76
|
+
export declare function existingProjectDocs(shape?: ProjectDocShape): string[];
|
|
77
|
+
/**
|
|
78
|
+
* The instruction appended to the reasoner/planner prompt for a SOFTWARE
|
|
79
|
+
* deliverable. Returns `''` for a non-software (authored) ask, so callers can
|
|
80
|
+
* append it unconditionally without a poem ever being asked for a CHANGELOG.
|
|
81
|
+
*/
|
|
82
|
+
export declare function softwareProjectGuidance(verdictClass: string, authored: boolean, shape?: ProjectDocShape): string;
|
|
83
|
+
//# sourceMappingURL=project-docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-docs.d.ts","sourceRoot":"","sources":["../../src/learning/project-docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAqC9D,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,eAAoB,GAAG,MAAM,EAAE,CAOzE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAU/D;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,eAAoB,GAAG,MAAM,EAAE,CAGxE;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,eAAoB,GAAG,MAAM,EAAE,CAGzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,OAAO,EACjB,KAAK,GAAE,eAAoB,GAC1B,MAAM,CAmCR"}
|