agent-nuvira 3.3.13 → 3.3.15
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/orchestrator.d.ts +31 -0
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +74 -126
- 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 +765 -33
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +12 -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 +86 -0
- 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/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 +9 -1
- package/dist/cli/knowledge.d.ts.map +1 -1
- package/dist/cli/knowledge.js +93 -2
- package/dist/cli/knowledge.js.map +1 -1
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +47 -12
- 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/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/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 +33 -0
- package/dist/gateway/hook-contract.d.ts.map +1 -1
- package/dist/gateway/hook-contract.js +97 -0
- package/dist/gateway/hook-contract.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 +37 -0
- package/dist/inference/interface.d.ts.map +1 -1
- 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/route-resolver.d.ts +30 -0
- package/dist/inference/route-resolver.d.ts.map +1 -1
- package/dist/inference/route-resolver.js +158 -1
- package/dist/inference/route-resolver.js.map +1 -1
- package/dist/inference/tools.d.ts +16 -1
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +51 -18
- 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 +68 -24
- package/dist/learning/auto-router.d.ts.map +1 -1
- package/dist/learning/auto-router.js +301 -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 +22 -1
- package/dist/learning/error-repair.d.ts.map +1 -1
- package/dist/learning/error-repair.js +37 -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 +229 -3
- package/dist/learning/knowledge-base.d.ts.map +1 -1
- package/dist/learning/knowledge-base.js +603 -25
- package/dist/learning/knowledge-base.js.map +1 -1
- 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.map +1 -1
- package/dist/learning/model-selection.js +41 -0
- 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/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/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/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/parity/drivers.d.ts.map +1 -1
- package/dist/parity/drivers.js +3 -0
- package/dist/parity/drivers.js.map +1 -1
- package/dist/parity/observation.d.ts +12 -0
- package/dist/parity/observation.d.ts.map +1 -1
- package/dist/parity/observation.js +14 -0
- package/dist/parity/observation.js.map +1 -1
- 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 +20 -2
- package/dist/tools/plan-store.d.ts.map +1 -1
- package/dist/tools/plan-store.js +51 -7
- 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 +486 -26
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/remediation-ladder.d.ts.map +1 -1
- package/dist/tools/remediation-ladder.js +8 -0
- package/dist/tools/remediation-ladder.js.map +1 -1
- 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 +265 -10
- package/dist/tools/run-terminal.js.map +1 -1
- package/dist/tools/tool-loop.d.ts +321 -13
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +867 -66
- package/dist/tools/tool-loop.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 +11 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +362 -11
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +170 -1
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.d.ts +11 -2
- package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
- package/dist/web-dashboard/workspace-guard.js +24 -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-zjbdJnO-.js +210 -0
- package/src/web-dashboard/public/assets/index-zjbdJnO-.js.map +1 -0
- package/src/web-dashboard/public/index.html +1 -1
- package/dist/agents/nvda-addon.d.ts +0 -14
- package/dist/agents/nvda-addon.js +0 -52
- package/dist/forwarded.d.ts +0 -2
- package/dist/forwarded.js +0 -2
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js +0 -210
- package/src/web-dashboard/public/assets/index-DhiuR4S2.js.map +0 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier-3 behavioural labels — the verdict the harness can INFER from what the
|
|
3
|
+
* user DID, without the user saying anything.
|
|
4
|
+
*
|
|
5
|
+
* WHY A THIRD TIER. An explicit verdict (`nuvira rate`, the dashboard Trace tab)
|
|
6
|
+
* is the only source of a POSITIVE label, but it only exists when the user
|
|
7
|
+
* bothers to give one. Between "the user rated it" and "the user said nothing at
|
|
8
|
+
* all" there is behaviour the harness can OBSERVE: a re-ask, a hand-edit of the
|
|
9
|
+
* delivered file, an untouched artifact the user then referenced. Those are
|
|
10
|
+
* inferences, not statements, so they carry `source: 'derived'` and a fit can
|
|
11
|
+
* weigh them BELOW a human judgement.
|
|
12
|
+
*
|
|
13
|
+
* THE RULE THAT KEEPS THIS HONEST. Silence is still NOT acceptance. An untouched
|
|
14
|
+
* artifact is not a label on its own — it becomes a (weak) acceptance only when
|
|
15
|
+
* the user's next message REFERENCES that artifact without reporting a regression.
|
|
16
|
+
* A raw untouched file the user never mentioned stays `null`, exactly like a turn
|
|
17
|
+
* nobody rated. The three signals, in priority order:
|
|
18
|
+
*
|
|
19
|
+
* 1. repeat-ask — the new ask is near-identical to the delivered ask
|
|
20
|
+
* (Jaccard similarity), so the delivery did not land. → rejected
|
|
21
|
+
* 2. hand-edit — the delivered file changed after the turn made it,
|
|
22
|
+
* so the user had to fix it. → rejected
|
|
23
|
+
* 3. unchanged-referenced — the file is untouched AND the new message names it
|
|
24
|
+
* AND no regression was reported. → accepted
|
|
25
|
+
*
|
|
26
|
+
* NOTHING ROUTES ON THIS. It labels the deliverable corpus and the turn's trace,
|
|
27
|
+
* the same two places an explicit verdict writes, and that is all.
|
|
28
|
+
*
|
|
29
|
+
* The similarity and reference tests are MEASURED (token overlap, a filename
|
|
30
|
+
* appearing in the text) — never a phrase list of "sounds like they liked it".
|
|
31
|
+
*/
|
|
32
|
+
/** Why a behavioural label was derived — kept so a reader can audit the inference. */
|
|
33
|
+
export type BehaviouralReason = 'repeat-ask' | 'hand-edit' | 'unchanged-referenced';
|
|
34
|
+
/** A derived verdict. `source` is ALWAYS `'derived'` — that is the point of the tier. */
|
|
35
|
+
export interface BehaviouralLabel {
|
|
36
|
+
verdict: 'accepted' | 'rejected';
|
|
37
|
+
source: 'derived';
|
|
38
|
+
reason: BehaviouralReason;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Token-set Jaccard at or above which two asks are the SAME request.
|
|
42
|
+
*
|
|
43
|
+
* Deliberately high: a re-ask is usually near-verbatim, and a false positive here
|
|
44
|
+
* would mark a genuinely NEW request as a rejection of the last one. Two different
|
|
45
|
+
* asks about the same subject share only their common words, which pulls the score
|
|
46
|
+
* well below this line.
|
|
47
|
+
*/
|
|
48
|
+
export declare const REPEAT_ASK_SIMILARITY = 0.9;
|
|
49
|
+
/** Alphanumeric word tokens, lowercased. No stoplist — overlap is measured, not curated. */
|
|
50
|
+
export declare function normalizeAskTokens(text: string): Set<string>;
|
|
51
|
+
/** Jaccard similarity of two asks' token sets (0 when either is empty). */
|
|
52
|
+
export declare function askSimilarity(a: string, b: string): number;
|
|
53
|
+
/** Does the message NAME the artifact — its filename (with or without extension)? */
|
|
54
|
+
export declare function referencesArtifact(newAsk: string, path: string): boolean;
|
|
55
|
+
/** True when the file exists and its mtime is AFTER the delivery (+ slack). Never throws. */
|
|
56
|
+
export declare function wasModifiedAfter(path: string, deliveredAt: number, epsilonMs?: number): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The pure decision, so the inference can be unit-tested without a filesystem.
|
|
59
|
+
* `null` means "no label is justified" — which is the common, honest answer.
|
|
60
|
+
*/
|
|
61
|
+
export declare function classifyBehaviouralLabel(input: {
|
|
62
|
+
newAsk: string;
|
|
63
|
+
previousAsk: string;
|
|
64
|
+
reportsRegression: boolean;
|
|
65
|
+
artifactPath: string | null;
|
|
66
|
+
artifactModified: boolean;
|
|
67
|
+
referencesArtifact: boolean;
|
|
68
|
+
}): BehaviouralLabel | null;
|
|
69
|
+
/**
|
|
70
|
+
* Read the newest UNLABELLED delivery, infer a behavioural label, and apply it.
|
|
71
|
+
*
|
|
72
|
+
* Returns the label that was applied, or null when nothing was justified. Every
|
|
73
|
+
* write is best-effort.
|
|
74
|
+
*/
|
|
75
|
+
export declare function deriveAndApplyBehaviouralLabel(input: {
|
|
76
|
+
newAsk: string;
|
|
77
|
+
reportsRegression: boolean;
|
|
78
|
+
now?: number;
|
|
79
|
+
}): BehaviouralLabel | null;
|
|
80
|
+
/**
|
|
81
|
+
* Write a derived label to the same two places an explicit verdict writes: the
|
|
82
|
+
* delivery's corpus row and (when the row knows its trace) the turn's trace.
|
|
83
|
+
* Best-effort — a label write must never break a turn.
|
|
84
|
+
*/
|
|
85
|
+
export declare function applyBehaviouralLabel(traceId: string | undefined, label: BehaviouralLabel, now?: number): void;
|
|
86
|
+
//# sourceMappingURL=behavioural-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavioural-labels.d.ts","sourceRoot":"","sources":["../../src/learning/behavioural-labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAWH,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,WAAW,GAAG,sBAAsB,CAAC;AAEpF,yFAAyF;AACzF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,UAAU,GAAG,UAAU,CAAC;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAKzC,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAG5D;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQxE;AAED,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,SAAwB,GAAG,OAAO,CAQ9G;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;CAC7B,GAAG,gBAAgB,GAAG,IAAI,CAkB1B;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,gBAAgB,GAAG,IAAI,CAyB1B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,KAAK,EAAE,gBAAgB,EACvB,GAAG,GAAE,MAAmB,GACvB,IAAI,CAaN"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier-3 behavioural labels — the verdict the harness can INFER from what the
|
|
3
|
+
* user DID, without the user saying anything.
|
|
4
|
+
*
|
|
5
|
+
* WHY A THIRD TIER. An explicit verdict (`nuvira rate`, the dashboard Trace tab)
|
|
6
|
+
* is the only source of a POSITIVE label, but it only exists when the user
|
|
7
|
+
* bothers to give one. Between "the user rated it" and "the user said nothing at
|
|
8
|
+
* all" there is behaviour the harness can OBSERVE: a re-ask, a hand-edit of the
|
|
9
|
+
* delivered file, an untouched artifact the user then referenced. Those are
|
|
10
|
+
* inferences, not statements, so they carry `source: 'derived'` and a fit can
|
|
11
|
+
* weigh them BELOW a human judgement.
|
|
12
|
+
*
|
|
13
|
+
* THE RULE THAT KEEPS THIS HONEST. Silence is still NOT acceptance. An untouched
|
|
14
|
+
* artifact is not a label on its own — it becomes a (weak) acceptance only when
|
|
15
|
+
* the user's next message REFERENCES that artifact without reporting a regression.
|
|
16
|
+
* A raw untouched file the user never mentioned stays `null`, exactly like a turn
|
|
17
|
+
* nobody rated. The three signals, in priority order:
|
|
18
|
+
*
|
|
19
|
+
* 1. repeat-ask — the new ask is near-identical to the delivered ask
|
|
20
|
+
* (Jaccard similarity), so the delivery did not land. → rejected
|
|
21
|
+
* 2. hand-edit — the delivered file changed after the turn made it,
|
|
22
|
+
* so the user had to fix it. → rejected
|
|
23
|
+
* 3. unchanged-referenced — the file is untouched AND the new message names it
|
|
24
|
+
* AND no regression was reported. → accepted
|
|
25
|
+
*
|
|
26
|
+
* NOTHING ROUTES ON THIS. It labels the deliverable corpus and the turn's trace,
|
|
27
|
+
* the same two places an explicit verdict writes, and that is all.
|
|
28
|
+
*
|
|
29
|
+
* The similarity and reference tests are MEASURED (token overlap, a filename
|
|
30
|
+
* appearing in the text) — never a phrase list of "sounds like they liked it".
|
|
31
|
+
*/
|
|
32
|
+
import { statSync } from 'node:fs';
|
|
33
|
+
import { basename, extname } from 'node:path';
|
|
34
|
+
import { readDeliverableCandidates, labelNewestUnlabelled, labelDeliverableByTrace, } from './deliverable-corpus.js';
|
|
35
|
+
import { recordTraceVerdict } from './reasoning-trace.js';
|
|
36
|
+
/**
|
|
37
|
+
* Token-set Jaccard at or above which two asks are the SAME request.
|
|
38
|
+
*
|
|
39
|
+
* Deliberately high: a re-ask is usually near-verbatim, and a false positive here
|
|
40
|
+
* would mark a genuinely NEW request as a rejection of the last one. Two different
|
|
41
|
+
* asks about the same subject share only their common words, which pulls the score
|
|
42
|
+
* well below this line.
|
|
43
|
+
*/
|
|
44
|
+
export const REPEAT_ASK_SIMILARITY = 0.9;
|
|
45
|
+
/** Filesystem timestamp slack: a write finishing at the same instant as delivery is not an edit. */
|
|
46
|
+
const FILE_MTIME_EPSILON_MS = 250;
|
|
47
|
+
/** Alphanumeric word tokens, lowercased. No stoplist — overlap is measured, not curated. */
|
|
48
|
+
export function normalizeAskTokens(text) {
|
|
49
|
+
const tokens = (text || '').toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
50
|
+
return new Set(tokens.filter((t) => t.length >= 2));
|
|
51
|
+
}
|
|
52
|
+
/** Jaccard similarity of two asks' token sets (0 when either is empty). */
|
|
53
|
+
export function askSimilarity(a, b) {
|
|
54
|
+
const sa = normalizeAskTokens(a);
|
|
55
|
+
const sb = normalizeAskTokens(b);
|
|
56
|
+
if (sa.size === 0 || sb.size === 0)
|
|
57
|
+
return 0;
|
|
58
|
+
let inter = 0;
|
|
59
|
+
for (const t of sa)
|
|
60
|
+
if (sb.has(t))
|
|
61
|
+
inter++;
|
|
62
|
+
const union = sa.size + sb.size - inter;
|
|
63
|
+
return union === 0 ? 0 : inter / union;
|
|
64
|
+
}
|
|
65
|
+
/** Does the message NAME the artifact — its filename (with or without extension)? */
|
|
66
|
+
export function referencesArtifact(newAsk, path) {
|
|
67
|
+
if (!path)
|
|
68
|
+
return false;
|
|
69
|
+
const text = (newAsk || '').toLowerCase();
|
|
70
|
+
const base = basename(path).toLowerCase();
|
|
71
|
+
const stem = base.slice(0, base.length - extname(base).length);
|
|
72
|
+
if (stem.length >= 2 && normalizeAskTokens(newAsk).has(stem))
|
|
73
|
+
return true;
|
|
74
|
+
// The full filename mentioned verbatim (e.g. "guide.md") also counts.
|
|
75
|
+
return base.length >= 2 && text.includes(base);
|
|
76
|
+
}
|
|
77
|
+
/** True when the file exists and its mtime is AFTER the delivery (+ slack). Never throws. */
|
|
78
|
+
export function wasModifiedAfter(path, deliveredAt, epsilonMs = FILE_MTIME_EPSILON_MS) {
|
|
79
|
+
try {
|
|
80
|
+
const st = statSync(path);
|
|
81
|
+
return st.mtimeMs > deliveredAt + epsilonMs;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// A path we cannot resolve (different cwd, deleted file) is not evidence of an edit.
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The pure decision, so the inference can be unit-tested without a filesystem.
|
|
90
|
+
* `null` means "no label is justified" — which is the common, honest answer.
|
|
91
|
+
*/
|
|
92
|
+
export function classifyBehaviouralLabel(input) {
|
|
93
|
+
// A reported regression is already labelled by the explicit correction path
|
|
94
|
+
// (`detectRegressionSignal`). Deriving a second label for it would double-count
|
|
95
|
+
// one event, so the behavioural tier stands aside.
|
|
96
|
+
if (input.reportsRegression)
|
|
97
|
+
return null;
|
|
98
|
+
if (askSimilarity(input.newAsk, input.previousAsk) >= REPEAT_ASK_SIMILARITY) {
|
|
99
|
+
return { verdict: 'rejected', source: 'derived', reason: 'repeat-ask' };
|
|
100
|
+
}
|
|
101
|
+
// An edit is checked BEFORE any acceptance: a file the user rewrote is the
|
|
102
|
+
// strongest behavioural negative, whether or not they mentioned it.
|
|
103
|
+
if (input.artifactModified) {
|
|
104
|
+
return { verdict: 'rejected', source: 'derived', reason: 'hand-edit' };
|
|
105
|
+
}
|
|
106
|
+
if (input.referencesArtifact) {
|
|
107
|
+
return { verdict: 'accepted', source: 'derived', reason: 'unchanged-referenced' };
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Read the newest UNLABELLED delivery, infer a behavioural label, and apply it.
|
|
113
|
+
*
|
|
114
|
+
* Returns the label that was applied, or null when nothing was justified. Every
|
|
115
|
+
* write is best-effort.
|
|
116
|
+
*/
|
|
117
|
+
export function deriveAndApplyBehaviouralLabel(input) {
|
|
118
|
+
if (input.reportsRegression)
|
|
119
|
+
return null;
|
|
120
|
+
let row;
|
|
121
|
+
try {
|
|
122
|
+
const rows = readDeliverableCandidates();
|
|
123
|
+
row = [...rows].reverse().find((r) => r.verdict === null);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
if (!row)
|
|
129
|
+
return null;
|
|
130
|
+
const artifactModified = row.path ? wasModifiedAfter(row.path, row.ts) : false;
|
|
131
|
+
const referenced = row.path ? referencesArtifact(input.newAsk, row.path) : false;
|
|
132
|
+
const label = classifyBehaviouralLabel({
|
|
133
|
+
newAsk: input.newAsk,
|
|
134
|
+
previousAsk: row.ask,
|
|
135
|
+
reportsRegression: false,
|
|
136
|
+
artifactPath: row.path ?? null,
|
|
137
|
+
artifactModified,
|
|
138
|
+
referencesArtifact: referenced,
|
|
139
|
+
});
|
|
140
|
+
if (!label)
|
|
141
|
+
return null;
|
|
142
|
+
applyBehaviouralLabel(row.traceId, label, input.now ?? Date.now());
|
|
143
|
+
return label;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Write a derived label to the same two places an explicit verdict writes: the
|
|
147
|
+
* delivery's corpus row and (when the row knows its trace) the turn's trace.
|
|
148
|
+
* Best-effort — a label write must never break a turn.
|
|
149
|
+
*/
|
|
150
|
+
export function applyBehaviouralLabel(traceId, label, now = Date.now()) {
|
|
151
|
+
try {
|
|
152
|
+
if (traceId) {
|
|
153
|
+
labelDeliverableByTrace(traceId, label.verdict, now);
|
|
154
|
+
recordTraceVerdict(traceId, label.verdict, label.source, now);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// No trace to hang it on: label the newest unlabelled row directly. The
|
|
158
|
+
// cue is real (we are looking at that delivery), so this is not invention.
|
|
159
|
+
labelNewestUnlabelled(label.verdict, now);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Best-effort.
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=behavioural-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavioural-labels.js","sourceRoot":"","sources":["../../src/learning/behavioural-labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CAPABILITY BY MEASUREMENT (Bundle 3, B1–B4) — the scorecard.
|
|
3
|
+
*
|
|
4
|
+
* THE DEFECT THIS REPLACES. `AutoModelRouter.getModelCapabilities()` judges a
|
|
5
|
+
* model from its NAME: `mini`/`tiny`/`flash`/`lite` each SUBTRACT 0.1 from
|
|
6
|
+
* reasoning (so `gemini-3.1-flash-lite` loses 0.2 for two words), `pro`/`large`/
|
|
7
|
+
* `opus` add, a `70b` in the id adds 0.45, and a frontier-family keyword adds
|
|
8
|
+
* 0.2. Nothing in the system had ever measured whether a model is any good, so
|
|
9
|
+
* max mode's reasoning floor was a NAME threshold, and this programme's own
|
|
10
|
+
* investigation fell into the trap it was reporting: it called DeepSeek V4.1
|
|
11
|
+
* Flash weak *because of the word "flash"* while that model served an 82-step
|
|
12
|
+
* build.
|
|
13
|
+
*
|
|
14
|
+
* THE REPLACEMENT. One record per provider × model holding five named
|
|
15
|
+
* parameters, each 0–100 with its own sample count, fed from what the harness
|
|
16
|
+
* OBSERVES while doing real work:
|
|
17
|
+
*
|
|
18
|
+
* accuracy did the work actually verify (TurnReport.verification)
|
|
19
|
+
* performance how fast it answered, per call (registry latency EMA)
|
|
20
|
+
* cost what the work cost (measured tokens × price)
|
|
21
|
+
* robustness does it hold up across many calls (errorRate / partialRate)
|
|
22
|
+
* ecosystem what the pair can do besides answer (tool-calling, window)
|
|
23
|
+
*
|
|
24
|
+
* THE PRIOR RULE (§3.2), and the one thing to read before changing anything:
|
|
25
|
+
* **0 samples returns the declared prior, byte-for-byte.** Measurement replaces
|
|
26
|
+
* the prior as samples accumulate (`PRIOR_FULL_SAMPLES`) — a wrong prior can
|
|
27
|
+
* outrank evidence for a while, but never after the record has real samples.
|
|
28
|
+
* The id-substring terms are REMOVED, not capped: a capped name hint is still a
|
|
29
|
+
* name judgement, and "the name contributes nothing" is the whole acceptance.
|
|
30
|
+
*
|
|
31
|
+
* WHAT THIS MODULE DOES NOT DO. It is pure — no registry, no I/O — so the
|
|
32
|
+
* arithmetic is testable in isolation and the storage layer decides when to call
|
|
33
|
+
* it. It never invents a sample: a turn that verified nothing contributes
|
|
34
|
+
* NOTHING (not a neutral 50), because a run that never checks its work has no
|
|
35
|
+
* accuracy evidence, and a fabricated neutral sample would dilute the real ones.
|
|
36
|
+
*/
|
|
37
|
+
/** The five named parameters, in the order `model explain` prints them. */
|
|
38
|
+
export type CapabilityParameter = 'accuracy' | 'performance' | 'cost' | 'robustness' | 'ecosystem';
|
|
39
|
+
/** How many observations a parameter needs before it is reported as MEASURED. */
|
|
40
|
+
export declare const MIN_SAMPLES_FOR_EVIDENCE = 5;
|
|
41
|
+
/**
|
|
42
|
+
* Samples at which the prior's weight reaches zero. Between 0 and here the prior
|
|
43
|
+
* decays LINEARLY (`priorWeight = 1 - samples / PRIOR_FULL_SAMPLES`), so a single
|
|
44
|
+
* lucky or unlucky turn cannot swing a ranking, and a model with a real track
|
|
45
|
+
* record is judged by it. Stated here rather than inline because §7 of the design
|
|
46
|
+
* calls the decay rate a calibration decision, not a constant to bury.
|
|
47
|
+
*/
|
|
48
|
+
export declare const PRIOR_FULL_SAMPLES: number;
|
|
49
|
+
/** EMA weight for one observation. Matches the registry's latency/token EMAs. */
|
|
50
|
+
export declare const EVIDENCE_ALPHA = 0.3;
|
|
51
|
+
/** Where a reported value came from. Printed beside every number. */
|
|
52
|
+
export type EvidenceSource = 'measured' | 'prior';
|
|
53
|
+
/** One parameter: the measured value (0–100), how many samples, and its source. */
|
|
54
|
+
export interface ParameterScore {
|
|
55
|
+
/** Measured value 0–100. Meaningless on its own — always pair it with `samples`. */
|
|
56
|
+
measured: number;
|
|
57
|
+
/** Observations folded in. 0 = nothing measured yet. */
|
|
58
|
+
samples: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The scorecard for one provider × model. Every parameter is optional: absent
|
|
62
|
+
* means "nothing measured", which reports as the prior rather than as a zero.
|
|
63
|
+
*/
|
|
64
|
+
export interface CapabilityRecord {
|
|
65
|
+
accuracy?: ParameterScore;
|
|
66
|
+
performance?: ParameterScore;
|
|
67
|
+
cost?: ParameterScore;
|
|
68
|
+
robustness?: ParameterScore;
|
|
69
|
+
ecosystem?: ParameterScore;
|
|
70
|
+
/** Epoch ms of the last fold. */
|
|
71
|
+
updatedAt: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Accuracy weights per turn verdict. `verified` is the strongest evidence the
|
|
75
|
+
* harness can produce (a change was made AND observed). `unverified` is real but
|
|
76
|
+
* weak evidence: the model answered, and its work could not be confirmed — so it
|
|
77
|
+
* pulls the score down without being scored as an outright failure, which would
|
|
78
|
+
* double-count the same event (`applyReward`'s `verificationPassed: false`
|
|
79
|
+
* already carries that penalty).
|
|
80
|
+
*
|
|
81
|
+
* A `blocked` turn is NOT here on purpose: a wall the run hit is not a verdict
|
|
82
|
+
* about the model.
|
|
83
|
+
*/
|
|
84
|
+
export declare const ACCURACY_BY_VERDICT: {
|
|
85
|
+
readonly verified: 100;
|
|
86
|
+
readonly unverified: 40;
|
|
87
|
+
};
|
|
88
|
+
/** A fresh record: nothing measured. */
|
|
89
|
+
export declare function emptyCapabilityRecord(now?: number): CapabilityRecord;
|
|
90
|
+
/**
|
|
91
|
+
* Fold a turn's verification verdict into `accuracy`. `blocked`/
|
|
92
|
+
* `not-applicable`/`delivered-and-read-back`/absent contribute nothing at all (see
|
|
93
|
+
* the header). `delivered-and-read-back` is NEUTRAL on purpose: it proves an authored
|
|
94
|
+
* document exists and was read back, not that it is correct or complete, so folding
|
|
95
|
+
* it either way would invent a quality signal the evidence does not carry.
|
|
96
|
+
*/
|
|
97
|
+
export declare function foldVerification(record: CapabilityRecord, verification: 'verified' | 'unverified' | 'blocked' | 'not-applicable' | 'delivered-and-read-back' | undefined | null, now?: number): CapabilityRecord;
|
|
98
|
+
/** Fold one measured call's outcome into `robustness` (0–100 per call). */
|
|
99
|
+
export declare function foldCallOutcome(record: CapabilityRecord, ok: boolean, now?: number): CapabilityRecord;
|
|
100
|
+
/** Fold a measured latency into `performance` (a call under 800 ms scores 100). */
|
|
101
|
+
export declare function foldLatency(record: CapabilityRecord, latencyMs: number | undefined, now?: number): CapabilityRecord;
|
|
102
|
+
/**
|
|
103
|
+
* The value to USE for a parameter, and whether it is measured or borrowed.
|
|
104
|
+
*
|
|
105
|
+
* THE ONE RULE THAT DECIDES EVERYTHING: with no samples the answer is exactly the
|
|
106
|
+
* prior passed in. That is what makes this change safe to land before the record
|
|
107
|
+
* has any data — behaviour on a cold start is unchanged — and it is what makes
|
|
108
|
+
* the acceptance test "two ids differing only by a tier word score identically"
|
|
109
|
+
* true, since the prior is provider-level and cannot see the id.
|
|
110
|
+
*/
|
|
111
|
+
export declare function effectiveParameter(record: CapabilityRecord | undefined, parameter: CapabilityParameter, priorFraction: number): {
|
|
112
|
+
value: number;
|
|
113
|
+
samples: number;
|
|
114
|
+
source: EvidenceSource;
|
|
115
|
+
};
|
|
116
|
+
/** Capability tier, DERIVED from the parameters — never parsed from an id. */
|
|
117
|
+
export type CapabilityTier = 'Frontier' | 'Balanced' | 'Utility';
|
|
118
|
+
/**
|
|
119
|
+
* Derive the tier. Deliberately coarse and stated in one place:
|
|
120
|
+
* - `Utility` — accuracy is poor, or the pair is unreliable;
|
|
121
|
+
* - `Frontier` — strong accuracy AND a wide ecosystem;
|
|
122
|
+
* - `Balanced` — everything else, which is most things.
|
|
123
|
+
* `ecosystem` participates because a strong answerer that cannot call tools is
|
|
124
|
+
* not a frontier AGENT model, and this harness only cares about agent models.
|
|
125
|
+
*/
|
|
126
|
+
export declare function deriveTier(view: {
|
|
127
|
+
accuracy: {
|
|
128
|
+
value: number;
|
|
129
|
+
samples: number;
|
|
130
|
+
};
|
|
131
|
+
robustness: {
|
|
132
|
+
value: number;
|
|
133
|
+
samples: number;
|
|
134
|
+
};
|
|
135
|
+
ecosystem: {
|
|
136
|
+
value: number;
|
|
137
|
+
samples: number;
|
|
138
|
+
};
|
|
139
|
+
}): CapabilityTier;
|
|
140
|
+
/**
|
|
141
|
+
* Declared priors for the parameters a cold start cannot supply.
|
|
142
|
+
*
|
|
143
|
+
* `accuracy` and `performance` are deliberately ABSENT: their priors are the
|
|
144
|
+
* provider's own declared baseline, which only the router knows. `cost` is
|
|
145
|
+
* absent too — pricing belongs to a provider ACCOUNT, so with no measurement the
|
|
146
|
+
* honest answer is "no prior" rather than a number that reads as free:
|
|
147
|
+
*
|
|
148
|
+
* - `robustness: 0.7` — most pairs answer most of the time; a prior, replaced
|
|
149
|
+
* by measurement as soon as calls are recorded;
|
|
150
|
+
* - `ecosystem: 0.5` — nothing is known about tool-calling until observed, and
|
|
151
|
+
* 0.5 keeps a pair OUT of the `Frontier` gate (which needs ≥ 0.7). A pair we
|
|
152
|
+
* have never watched use a tool is not a frontier agent model.
|
|
153
|
+
*/
|
|
154
|
+
export declare const DEFAULT_PRIORS: Record<CapabilityParameter, number | undefined>;
|
|
155
|
+
/**
|
|
156
|
+
* The whole scorecard as printable rows: `accuracy 78 (measured, n=14)`.
|
|
157
|
+
*
|
|
158
|
+
* The sample count is NOT optional — a score without one is exactly the
|
|
159
|
+
* plausible-looking number this programme exists to remove — and a parameter with
|
|
160
|
+
* neither a prior nor a sample prints `n/a` rather than a `0` that would read as
|
|
161
|
+
* "free" or "broken".
|
|
162
|
+
*/
|
|
163
|
+
export declare function capabilityLines(record: CapabilityRecord | undefined, priors?: Partial<Record<CapabilityParameter, number>>, priorLabels?: Partial<Record<CapabilityParameter, {
|
|
164
|
+
source: string;
|
|
165
|
+
fetchedAt: number;
|
|
166
|
+
}>>): string[];
|
|
167
|
+
//# sourceMappingURL=capability-evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-evidence.d.ts","sourceRoot":"","sources":["../../src/learning/capability-evidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CAPABILITY BY MEASUREMENT (Bundle 3, B1–B4) — the scorecard.
|
|
3
|
+
*
|
|
4
|
+
* THE DEFECT THIS REPLACES. `AutoModelRouter.getModelCapabilities()` judges a
|
|
5
|
+
* model from its NAME: `mini`/`tiny`/`flash`/`lite` each SUBTRACT 0.1 from
|
|
6
|
+
* reasoning (so `gemini-3.1-flash-lite` loses 0.2 for two words), `pro`/`large`/
|
|
7
|
+
* `opus` add, a `70b` in the id adds 0.45, and a frontier-family keyword adds
|
|
8
|
+
* 0.2. Nothing in the system had ever measured whether a model is any good, so
|
|
9
|
+
* max mode's reasoning floor was a NAME threshold, and this programme's own
|
|
10
|
+
* investigation fell into the trap it was reporting: it called DeepSeek V4.1
|
|
11
|
+
* Flash weak *because of the word "flash"* while that model served an 82-step
|
|
12
|
+
* build.
|
|
13
|
+
*
|
|
14
|
+
* THE REPLACEMENT. One record per provider × model holding five named
|
|
15
|
+
* parameters, each 0–100 with its own sample count, fed from what the harness
|
|
16
|
+
* OBSERVES while doing real work:
|
|
17
|
+
*
|
|
18
|
+
* accuracy did the work actually verify (TurnReport.verification)
|
|
19
|
+
* performance how fast it answered, per call (registry latency EMA)
|
|
20
|
+
* cost what the work cost (measured tokens × price)
|
|
21
|
+
* robustness does it hold up across many calls (errorRate / partialRate)
|
|
22
|
+
* ecosystem what the pair can do besides answer (tool-calling, window)
|
|
23
|
+
*
|
|
24
|
+
* THE PRIOR RULE (§3.2), and the one thing to read before changing anything:
|
|
25
|
+
* **0 samples returns the declared prior, byte-for-byte.** Measurement replaces
|
|
26
|
+
* the prior as samples accumulate (`PRIOR_FULL_SAMPLES`) — a wrong prior can
|
|
27
|
+
* outrank evidence for a while, but never after the record has real samples.
|
|
28
|
+
* The id-substring terms are REMOVED, not capped: a capped name hint is still a
|
|
29
|
+
* name judgement, and "the name contributes nothing" is the whole acceptance.
|
|
30
|
+
*
|
|
31
|
+
* WHAT THIS MODULE DOES NOT DO. It is pure — no registry, no I/O — so the
|
|
32
|
+
* arithmetic is testable in isolation and the storage layer decides when to call
|
|
33
|
+
* it. It never invents a sample: a turn that verified nothing contributes
|
|
34
|
+
* NOTHING (not a neutral 50), because a run that never checks its work has no
|
|
35
|
+
* accuracy evidence, and a fabricated neutral sample would dilute the real ones.
|
|
36
|
+
*/
|
|
37
|
+
/** How many observations a parameter needs before it is reported as MEASURED. */
|
|
38
|
+
export const MIN_SAMPLES_FOR_EVIDENCE = 5;
|
|
39
|
+
/**
|
|
40
|
+
* Samples at which the prior's weight reaches zero. Between 0 and here the prior
|
|
41
|
+
* decays LINEARLY (`priorWeight = 1 - samples / PRIOR_FULL_SAMPLES`), so a single
|
|
42
|
+
* lucky or unlucky turn cannot swing a ranking, and a model with a real track
|
|
43
|
+
* record is judged by it. Stated here rather than inline because §7 of the design
|
|
44
|
+
* calls the decay rate a calibration decision, not a constant to bury.
|
|
45
|
+
*/
|
|
46
|
+
export const PRIOR_FULL_SAMPLES = 2 * MIN_SAMPLES_FOR_EVIDENCE;
|
|
47
|
+
/** EMA weight for one observation. Matches the registry's latency/token EMAs. */
|
|
48
|
+
export const EVIDENCE_ALPHA = 0.3;
|
|
49
|
+
/**
|
|
50
|
+
* Accuracy weights per turn verdict. `verified` is the strongest evidence the
|
|
51
|
+
* harness can produce (a change was made AND observed). `unverified` is real but
|
|
52
|
+
* weak evidence: the model answered, and its work could not be confirmed — so it
|
|
53
|
+
* pulls the score down without being scored as an outright failure, which would
|
|
54
|
+
* double-count the same event (`applyReward`'s `verificationPassed: false`
|
|
55
|
+
* already carries that penalty).
|
|
56
|
+
*
|
|
57
|
+
* A `blocked` turn is NOT here on purpose: a wall the run hit is not a verdict
|
|
58
|
+
* about the model.
|
|
59
|
+
*/
|
|
60
|
+
export const ACCURACY_BY_VERDICT = {
|
|
61
|
+
verified: 100,
|
|
62
|
+
unverified: 40,
|
|
63
|
+
};
|
|
64
|
+
/** A fresh record: nothing measured. */
|
|
65
|
+
export function emptyCapabilityRecord(now = Date.now()) {
|
|
66
|
+
return { updatedAt: now };
|
|
67
|
+
}
|
|
68
|
+
/** Fold one 0–100 observation into a parameter's EMA (α = `EVIDENCE_ALPHA`). */
|
|
69
|
+
function foldEMA(score, observation) {
|
|
70
|
+
const obs = Math.max(0, Math.min(100, observation));
|
|
71
|
+
if (!score || score.samples <= 0)
|
|
72
|
+
return { measured: obs, samples: 1 };
|
|
73
|
+
return {
|
|
74
|
+
measured: EVIDENCE_ALPHA * obs + (1 - EVIDENCE_ALPHA) * score.measured,
|
|
75
|
+
samples: score.samples + 1,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Fold a turn's verification verdict into `accuracy`. `blocked`/
|
|
80
|
+
* `not-applicable`/`delivered-and-read-back`/absent contribute nothing at all (see
|
|
81
|
+
* the header). `delivered-and-read-back` is NEUTRAL on purpose: it proves an authored
|
|
82
|
+
* document exists and was read back, not that it is correct or complete, so folding
|
|
83
|
+
* it either way would invent a quality signal the evidence does not carry.
|
|
84
|
+
*/
|
|
85
|
+
export function foldVerification(record, verification, now = Date.now()) {
|
|
86
|
+
if (verification !== 'verified' && verification !== 'unverified')
|
|
87
|
+
return record;
|
|
88
|
+
return {
|
|
89
|
+
...record,
|
|
90
|
+
accuracy: foldEMA(record.accuracy, ACCURACY_BY_VERDICT[verification]),
|
|
91
|
+
updatedAt: now,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Fold one measured call's outcome into `robustness` (0–100 per call). */
|
|
95
|
+
export function foldCallOutcome(record, ok, now = Date.now()) {
|
|
96
|
+
return {
|
|
97
|
+
...record,
|
|
98
|
+
robustness: foldEMA(record.robustness, ok ? 100 : 0),
|
|
99
|
+
updatedAt: now,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** Fold a measured latency into `performance` (a call under 800 ms scores 100). */
|
|
103
|
+
export function foldLatency(record, latencyMs, now = Date.now()) {
|
|
104
|
+
if (!latencyMs || latencyMs <= 0)
|
|
105
|
+
return record;
|
|
106
|
+
// 800 ms or faster = 100; 10 s or slower = 0; linear between. The scale is
|
|
107
|
+
// stated, not inferred, so `model explain` can explain a number it prints.
|
|
108
|
+
const scaled = Math.max(0, Math.min(100, 100 * (1 - (latencyMs - 800) / (10_000 - 800))));
|
|
109
|
+
return {
|
|
110
|
+
...record,
|
|
111
|
+
performance: foldEMA(record.performance, scaled),
|
|
112
|
+
updatedAt: now,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The value to USE for a parameter, and whether it is measured or borrowed.
|
|
117
|
+
*
|
|
118
|
+
* THE ONE RULE THAT DECIDES EVERYTHING: with no samples the answer is exactly the
|
|
119
|
+
* prior passed in. That is what makes this change safe to land before the record
|
|
120
|
+
* has any data — behaviour on a cold start is unchanged — and it is what makes
|
|
121
|
+
* the acceptance test "two ids differing only by a tier word score identically"
|
|
122
|
+
* true, since the prior is provider-level and cannot see the id.
|
|
123
|
+
*/
|
|
124
|
+
export function effectiveParameter(record, parameter, priorFraction) {
|
|
125
|
+
const prior = Math.max(0, Math.min(1, priorFraction));
|
|
126
|
+
const score = record?.[parameter];
|
|
127
|
+
const samples = score?.samples ?? 0;
|
|
128
|
+
if (!score || samples <= 0)
|
|
129
|
+
return { value: prior, samples: 0, source: 'prior' };
|
|
130
|
+
const priorWeight = Math.max(0, 1 - samples / PRIOR_FULL_SAMPLES);
|
|
131
|
+
// Stored 0–100 (see `foldEMA`), reported 0–1 like every other capability scalar.
|
|
132
|
+
const measured = Math.max(0, Math.min(100, score.measured)) / 100;
|
|
133
|
+
const value = priorWeight * prior + (1 - priorWeight) * measured;
|
|
134
|
+
return {
|
|
135
|
+
value: Math.max(0, Math.min(1, value)),
|
|
136
|
+
samples,
|
|
137
|
+
source: samples >= MIN_SAMPLES_FOR_EVIDENCE ? 'measured' : 'prior',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Derive the tier. Deliberately coarse and stated in one place:
|
|
142
|
+
* - `Utility` — accuracy is poor, or the pair is unreliable;
|
|
143
|
+
* - `Frontier` — strong accuracy AND a wide ecosystem;
|
|
144
|
+
* - `Balanced` — everything else, which is most things.
|
|
145
|
+
* `ecosystem` participates because a strong answerer that cannot call tools is
|
|
146
|
+
* not a frontier AGENT model, and this harness only cares about agent models.
|
|
147
|
+
*/
|
|
148
|
+
export function deriveTier(view) {
|
|
149
|
+
if (view.accuracy.value < 0.5 || view.robustness.value < 0.5)
|
|
150
|
+
return 'Utility';
|
|
151
|
+
if (view.accuracy.value >= 0.8 && view.ecosystem.value >= 0.7)
|
|
152
|
+
return 'Frontier';
|
|
153
|
+
return 'Balanced';
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Declared priors for the parameters a cold start cannot supply.
|
|
157
|
+
*
|
|
158
|
+
* `accuracy` and `performance` are deliberately ABSENT: their priors are the
|
|
159
|
+
* provider's own declared baseline, which only the router knows. `cost` is
|
|
160
|
+
* absent too — pricing belongs to a provider ACCOUNT, so with no measurement the
|
|
161
|
+
* honest answer is "no prior" rather than a number that reads as free:
|
|
162
|
+
*
|
|
163
|
+
* - `robustness: 0.7` — most pairs answer most of the time; a prior, replaced
|
|
164
|
+
* by measurement as soon as calls are recorded;
|
|
165
|
+
* - `ecosystem: 0.5` — nothing is known about tool-calling until observed, and
|
|
166
|
+
* 0.5 keeps a pair OUT of the `Frontier` gate (which needs ≥ 0.7). A pair we
|
|
167
|
+
* have never watched use a tool is not a frontier agent model.
|
|
168
|
+
*/
|
|
169
|
+
export const DEFAULT_PRIORS = {
|
|
170
|
+
accuracy: undefined,
|
|
171
|
+
performance: undefined,
|
|
172
|
+
cost: undefined,
|
|
173
|
+
robustness: 0.7,
|
|
174
|
+
ecosystem: 0.5,
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* The whole scorecard as printable rows: `accuracy 78 (measured, n=14)`.
|
|
178
|
+
*
|
|
179
|
+
* The sample count is NOT optional — a score without one is exactly the
|
|
180
|
+
* plausible-looking number this programme exists to remove — and a parameter with
|
|
181
|
+
* neither a prior nor a sample prints `n/a` rather than a `0` that would read as
|
|
182
|
+
* "free" or "broken".
|
|
183
|
+
*/
|
|
184
|
+
export function capabilityLines(record, priors = {}, priorLabels = {}) {
|
|
185
|
+
return ['accuracy', 'performance', 'cost', 'robustness', 'ecosystem'].map((p) => {
|
|
186
|
+
const prior = priors[p] ?? DEFAULT_PRIORS[p];
|
|
187
|
+
if (prior === undefined) {
|
|
188
|
+
const samples = record?.[p]?.samples ?? 0;
|
|
189
|
+
return samples > 0
|
|
190
|
+
? `${p} ${Math.round((record?.[p]?.measured ?? 0))} (measured, n=${samples})`
|
|
191
|
+
: `${p} n/a (no prior declared, nothing measured)`;
|
|
192
|
+
}
|
|
193
|
+
const { value, samples, source } = effectiveParameter(record, p, prior);
|
|
194
|
+
const pct = Math.round(value * 100);
|
|
195
|
+
// §6.2 rule 4: a borrowed number must say WHERE it was borrowed from, so a reader can tell an
|
|
196
|
+
// observation from a prior. An unlabelled prior still prints the bare `prior` it always did —
|
|
197
|
+
// the label is added, never substituted.
|
|
198
|
+
const basis = source === 'measured' ? 'measured' : describePrior(p, priorLabels);
|
|
199
|
+
return `${p} ${pct} (${basis}${samples > 0 ? `, n=${samples}` : ''})`;
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/** `prior` alone, or `prior: <source>, <date>` when the prior came from somewhere nameable. */
|
|
203
|
+
function describePrior(p, labels) {
|
|
204
|
+
const label = labels[p];
|
|
205
|
+
if (!label)
|
|
206
|
+
return 'prior';
|
|
207
|
+
const day = new Date(label.fetchedAt).toISOString().slice(0, 10);
|
|
208
|
+
return `prior: ${label.source}, ${day}`;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=capability-evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-evidence.js","sourceRoot":"","sources":["../../src/learning/capability-evidence.ts"],"names":[],"mappings":"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"}
|