open-multi-agent-kit 0.99.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -1
- package/README.md +3 -3
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +1 -0
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/register-bundled-coding-agent.d.ts +10 -0
- package/dist/bun/register-bundled-coding-agent.d.ts.map +1 -0
- package/dist/bun/register-bundled-coding-agent.js +12 -0
- package/dist/bun/register-bundled-coding-agent.js.map +1 -0
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +2 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/neo-cli.d.ts +9 -0
- package/dist/commands/neo-cli.d.ts.map +1 -0
- package/dist/commands/neo-cli.js +61 -0
- package/dist/commands/neo-cli.js.map +1 -0
- package/dist/coordination/awareness.d.ts +32 -0
- package/dist/coordination/awareness.d.ts.map +1 -0
- package/dist/coordination/awareness.js +55 -0
- package/dist/coordination/awareness.js.map +1 -0
- package/dist/coordination/broker.d.ts +79 -0
- package/dist/coordination/broker.d.ts.map +1 -0
- package/dist/coordination/broker.js +195 -0
- package/dist/coordination/broker.js.map +1 -0
- package/dist/coordination/index.d.ts +16 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +16 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/integration.d.ts +59 -0
- package/dist/coordination/integration.d.ts.map +1 -0
- package/dist/coordination/integration.js +126 -0
- package/dist/coordination/integration.js.map +1 -0
- package/dist/coordination/operation.d.ts +106 -0
- package/dist/coordination/operation.d.ts.map +1 -0
- package/dist/coordination/operation.js +179 -0
- package/dist/coordination/operation.js.map +1 -0
- package/dist/coordination/resource.d.ts +33 -0
- package/dist/coordination/resource.d.ts.map +1 -0
- package/dist/coordination/resource.js +89 -0
- package/dist/coordination/resource.js.map +1 -0
- package/dist/coordination/session.d.ts +74 -0
- package/dist/coordination/session.d.ts.map +1 -0
- package/dist/coordination/session.js +143 -0
- package/dist/coordination/session.js.map +1 -0
- package/dist/coordination/types.d.ts +68 -0
- package/dist/coordination/types.d.ts.map +1 -0
- package/dist/coordination/types.js +26 -0
- package/dist/coordination/types.js.map +1 -0
- package/dist/core/agent-session.d.ts +29 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +135 -37
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bundled-skills.d.ts +4 -0
- package/dist/core/bundled-skills.d.ts.map +1 -0
- package/dist/core/bundled-skills.js +32 -0
- package/dist/core/bundled-skills.js.map +1 -0
- package/dist/core/cli-diagnostics.d.ts +6 -0
- package/dist/core/cli-diagnostics.d.ts.map +1 -0
- package/dist/core/cli-diagnostics.js +20 -0
- package/dist/core/cli-diagnostics.js.map +1 -0
- package/dist/core/compaction/control-state.d.ts +41 -0
- package/dist/core/compaction/control-state.d.ts.map +1 -0
- package/dist/core/compaction/control-state.js +85 -0
- package/dist/core/compaction/control-state.js.map +1 -0
- package/dist/core/compaction/fallback.d.ts +60 -0
- package/dist/core/compaction/fallback.d.ts.map +1 -0
- package/dist/core/compaction/fallback.js +117 -0
- package/dist/core/compaction/fallback.js.map +1 -0
- package/dist/core/compaction/index.d.ts +2 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +2 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/context-budget-headroom-candidates.d.ts +16 -1
- package/dist/core/context-budget-headroom-candidates.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-candidates.js +31 -13
- package/dist/core/context-budget-headroom-candidates.js.map +1 -1
- package/dist/core/context-budget-headroom-types.d.ts +7 -1
- package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-types.js +0 -1
- package/dist/core/context-budget-headroom-types.js.map +1 -1
- package/dist/core/context-budget-headroom.d.ts +22 -0
- package/dist/core/context-budget-headroom.d.ts.map +1 -1
- package/dist/core/context-budget-headroom.js +46 -2
- package/dist/core/context-budget-headroom.js.map +1 -1
- package/dist/core/context-budget-v2-global-pass.d.ts +21 -0
- package/dist/core/context-budget-v2-global-pass.d.ts.map +1 -0
- package/dist/core/context-budget-v2-global-pass.js +203 -0
- package/dist/core/context-budget-v2-global-pass.js.map +1 -0
- package/dist/core/context-budget-v2-input-validation.d.ts +4 -0
- package/dist/core/context-budget-v2-input-validation.d.ts.map +1 -0
- package/dist/core/context-budget-v2-input-validation.js +79 -0
- package/dist/core/context-budget-v2-input-validation.js.map +1 -0
- package/dist/core/context-budget-v2-observability.d.ts +15 -0
- package/dist/core/context-budget-v2-observability.d.ts.map +1 -0
- package/dist/core/context-budget-v2-observability.js +35 -0
- package/dist/core/context-budget-v2-observability.js.map +1 -0
- package/dist/core/context-budget-v2-planned-items.d.ts +17 -0
- package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -0
- package/dist/core/context-budget-v2-planned-items.js +59 -0
- package/dist/core/context-budget-v2-planned-items.js.map +1 -0
- package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planner.js +69 -51
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-scoring.d.ts +7 -1
- package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
- package/dist/core/context-budget-v2-scoring.js.map +1 -1
- package/dist/core/context-budget-v2-selection.d.ts +22 -3
- package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
- package/dist/core/context-budget-v2-selection.js +41 -59
- package/dist/core/context-budget-v2-selection.js.map +1 -1
- package/dist/core/context-budget-v2-tiers.d.ts.map +1 -1
- package/dist/core/context-budget-v2-tiers.js +9 -42
- package/dist/core/context-budget-v2-tiers.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +14 -2
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js +6 -1
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/extensions/bundled-virtual-modules.d.ts +15 -0
- package/dist/core/extensions/bundled-virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/bundled-virtual-modules.js +63 -0
- package/dist/core/extensions/bundled-virtual-modules.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -42
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +10 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/loadout-runtime.d.ts +2 -8
- package/dist/core/loadout-runtime.d.ts.map +1 -1
- package/dist/core/loadout-runtime.js.map +1 -1
- package/dist/core/mcp/client.d.ts +27 -6
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +80 -20
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/manager.d.ts +10 -1
- package/dist/core/mcp/manager.d.ts.map +1 -1
- package/dist/core/mcp/manager.js +68 -9
- package/dist/core/mcp/manager.js.map +1 -1
- package/dist/core/mcp/protocol.d.ts +9 -3
- package/dist/core/mcp/protocol.d.ts.map +1 -1
- package/dist/core/mcp/protocol.js +61 -15
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/mcp/stdio-transport.d.ts +12 -1
- package/dist/core/mcp/stdio-transport.d.ts.map +1 -1
- package/dist/core/mcp/stdio-transport.js +30 -2
- package/dist/core/mcp/stdio-transport.js.map +1 -1
- package/dist/core/mcp-descriptor-injection.d.ts +26 -0
- package/dist/core/mcp-descriptor-injection.d.ts.map +1 -0
- package/dist/core/mcp-descriptor-injection.js +25 -0
- package/dist/core/mcp-descriptor-injection.js.map +1 -0
- package/dist/core/mcp-public-presets.d.ts +1 -3
- package/dist/core/mcp-public-presets.d.ts.map +1 -1
- package/dist/core/mcp-public-presets.js +3 -15
- package/dist/core/mcp-public-presets.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +24 -3
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/neo/catalog.d.ts +20 -0
- package/dist/core/neo/catalog.d.ts.map +1 -0
- package/dist/core/neo/catalog.js +50 -0
- package/dist/core/neo/catalog.js.map +1 -0
- package/dist/core/neo/setup.d.ts +3 -0
- package/dist/core/neo/setup.d.ts.map +1 -0
- package/dist/core/neo/setup.js +47 -0
- package/dist/core/neo/setup.js.map +1 -0
- package/dist/core/provider-default-models.d.ts +2 -0
- package/dist/core/provider-default-models.d.ts.map +1 -1
- package/dist/core/provider-default-models.js +2 -0
- package/dist/core/provider-default-models.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +2 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/provider-error-classification.d.ts +57 -0
- package/dist/core/provider-error-classification.d.ts.map +1 -0
- package/dist/core/provider-error-classification.js +103 -0
- package/dist/core/provider-error-classification.js.map +1 -0
- package/dist/core/provider-resilience.d.ts +10 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +36 -3
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/provider-usage-commandcode.d.ts +9 -0
- package/dist/core/provider-usage-commandcode.d.ts.map +1 -0
- package/dist/core/provider-usage-commandcode.js +198 -0
- package/dist/core/provider-usage-commandcode.js.map +1 -0
- package/dist/core/provider-usage-devin.d.ts +5 -3
- package/dist/core/provider-usage-devin.d.ts.map +1 -1
- package/dist/core/provider-usage-devin.js +15 -5
- package/dist/core/provider-usage-devin.js.map +1 -1
- package/dist/core/provider-usage-types.d.ts +1 -1
- package/dist/core/provider-usage-types.d.ts.map +1 -1
- package/dist/core/provider-usage-types.js.map +1 -1
- package/dist/core/provider-usage.d.ts.map +1 -1
- package/dist/core/provider-usage.js +6 -0
- package/dist/core/provider-usage.js.map +1 -1
- package/dist/core/reasoning-router-resolver.d.ts +7 -0
- package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
- package/dist/core/reasoning-router-resolver.js +21 -3
- package/dist/core/reasoning-router-resolver.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts +8 -5
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js +8 -5
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/resource-admission.d.ts +36 -0
- package/dist/core/resource-admission.d.ts.map +1 -1
- package/dist/core/resource-admission.js +59 -0
- package/dist/core/resource-admission.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +2 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/run-usage-ledger.d.ts +47 -0
- package/dist/core/run-usage-ledger.d.ts.map +1 -0
- package/dist/core/run-usage-ledger.js +162 -0
- package/dist/core/run-usage-ledger.js.map +1 -0
- package/dist/core/run-usage-operation.d.ts +8 -0
- package/dist/core/run-usage-operation.d.ts.map +1 -0
- package/dist/core/run-usage-operation.js +12 -0
- package/dist/core/run-usage-operation.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -6
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-compaction-service.d.ts +15 -0
- package/dist/core/session-compaction-service.d.ts.map +1 -1
- package/dist/core/session-compaction-service.js +17 -4
- package/dist/core/session-compaction-service.js.map +1 -1
- package/dist/core/session-failure-cause.d.ts.map +1 -1
- package/dist/core/session-failure-cause.js +14 -5
- package/dist/core/session-failure-cause.js.map +1 -1
- package/dist/core/session-prompt-lifecycle.d.ts +6 -0
- package/dist/core/session-prompt-lifecycle.d.ts.map +1 -1
- package/dist/core/session-prompt-lifecycle.js +47 -2
- package/dist/core/session-prompt-lifecycle.js.map +1 -1
- package/dist/core/session-termination.d.ts.map +1 -1
- package/dist/core/session-termination.js +4 -2
- package/dist/core/session-termination.js.map +1 -1
- package/dist/core/subagent-lane-authority.d.ts +28 -0
- package/dist/core/subagent-lane-authority.d.ts.map +1 -0
- package/dist/core/subagent-lane-authority.js +119 -0
- package/dist/core/subagent-lane-authority.js.map +1 -0
- package/dist/core/subagent-lane-contract.d.ts +114 -0
- package/dist/core/subagent-lane-contract.d.ts.map +1 -0
- package/dist/core/subagent-lane-contract.js +18 -0
- package/dist/core/subagent-lane-contract.js.map +1 -0
- package/dist/core/subagent-lane-launcher.d.ts +3 -6
- package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
- package/dist/core/subagent-lane-launcher.js +53 -12
- package/dist/core/subagent-lane-launcher.js.map +1 -1
- package/dist/core/subagent-orchestration.d.ts +4 -17
- package/dist/core/subagent-orchestration.d.ts.map +1 -1
- package/dist/core/subagent-orchestration.js.map +1 -1
- package/dist/core/todo-runtime-state.d.ts +12 -0
- package/dist/core/todo-runtime-state.d.ts.map +1 -1
- package/dist/core/todo-runtime-state.js +23 -0
- package/dist/core/todo-runtime-state.js.map +1 -1
- package/dist/core/verified-run/broker.d.ts.map +1 -1
- package/dist/core/verified-run/broker.js +4 -1
- package/dist/core/verified-run/broker.js.map +1 -1
- package/dist/core/workload-permit-pool.d.ts +1 -1
- package/dist/core/workload-permit-pool.d.ts.map +1 -1
- package/dist/core/workload-permit-pool.js +3 -0
- package/dist/core/workload-permit-pool.js.map +1 -1
- package/dist/guardrails/strict-evidence-approval-adapter.d.ts +34 -0
- package/dist/guardrails/strict-evidence-approval-adapter.d.ts.map +1 -0
- package/dist/guardrails/strict-evidence-approval-adapter.js +70 -0
- package/dist/guardrails/strict-evidence-approval-adapter.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +11 -18
- package/dist/main.js.map +1 -1
- package/dist/metacognition/calibration-selective.d.ts +78 -0
- package/dist/metacognition/calibration-selective.d.ts.map +1 -0
- package/dist/metacognition/calibration-selective.js +161 -0
- package/dist/metacognition/calibration-selective.js.map +1 -0
- package/dist/metacognition/calibration.d.ts +62 -0
- package/dist/metacognition/calibration.d.ts.map +1 -0
- package/dist/metacognition/calibration.js +122 -0
- package/dist/metacognition/calibration.js.map +1 -0
- package/dist/metacognition/checkpoint.d.ts +60 -0
- package/dist/metacognition/checkpoint.d.ts.map +1 -0
- package/dist/metacognition/checkpoint.js +57 -0
- package/dist/metacognition/checkpoint.js.map +1 -0
- package/dist/metacognition/context7.d.ts +48 -0
- package/dist/metacognition/context7.d.ts.map +1 -0
- package/dist/metacognition/context7.js +154 -0
- package/dist/metacognition/context7.js.map +1 -0
- package/dist/metacognition/decision.d.ts +44 -0
- package/dist/metacognition/decision.d.ts.map +1 -0
- package/dist/metacognition/decision.js +111 -0
- package/dist/metacognition/decision.js.map +1 -0
- package/dist/metacognition/evaluation.d.ts +73 -0
- package/dist/metacognition/evaluation.d.ts.map +1 -0
- package/dist/metacognition/evaluation.js +97 -0
- package/dist/metacognition/evaluation.js.map +1 -0
- package/dist/metacognition/index.d.ts +31 -0
- package/dist/metacognition/index.d.ts.map +1 -0
- package/dist/metacognition/index.js +31 -0
- package/dist/metacognition/index.js.map +1 -0
- package/dist/metacognition/knowledge-action.d.ts +43 -0
- package/dist/metacognition/knowledge-action.d.ts.map +1 -0
- package/dist/metacognition/knowledge-action.js +60 -0
- package/dist/metacognition/knowledge-action.js.map +1 -0
- package/dist/metacognition/knowledge.d.ts +84 -0
- package/dist/metacognition/knowledge.d.ts.map +1 -0
- package/dist/metacognition/knowledge.js +165 -0
- package/dist/metacognition/knowledge.js.map +1 -0
- package/dist/metacognition/obligations.d.ts +82 -0
- package/dist/metacognition/obligations.d.ts.map +1 -0
- package/dist/metacognition/obligations.js +139 -0
- package/dist/metacognition/obligations.js.map +1 -0
- package/dist/metacognition/observation-validity.d.ts +83 -0
- package/dist/metacognition/observation-validity.d.ts.map +1 -0
- package/dist/metacognition/observation-validity.js +118 -0
- package/dist/metacognition/observation-validity.js.map +1 -0
- package/dist/metacognition/observe.d.ts +45 -0
- package/dist/metacognition/observe.d.ts.map +1 -0
- package/dist/metacognition/observe.js +59 -0
- package/dist/metacognition/observe.js.map +1 -0
- package/dist/metacognition/policy.d.ts +53 -0
- package/dist/metacognition/policy.d.ts.map +1 -0
- package/dist/metacognition/policy.js +155 -0
- package/dist/metacognition/policy.js.map +1 -0
- package/dist/metacognition/predictions.d.ts +78 -0
- package/dist/metacognition/predictions.d.ts.map +1 -0
- package/dist/metacognition/predictions.js +181 -0
- package/dist/metacognition/predictions.js.map +1 -0
- package/dist/metacognition/retrieval.d.ts +53 -0
- package/dist/metacognition/retrieval.d.ts.map +1 -0
- package/dist/metacognition/retrieval.js +170 -0
- package/dist/metacognition/retrieval.js.map +1 -0
- package/dist/metacognition/risk.d.ts +48 -0
- package/dist/metacognition/risk.d.ts.map +1 -0
- package/dist/metacognition/risk.js +165 -0
- package/dist/metacognition/risk.js.map +1 -0
- package/dist/metacognition/route-economics.d.ts +95 -0
- package/dist/metacognition/route-economics.d.ts.map +1 -0
- package/dist/metacognition/route-economics.js +110 -0
- package/dist/metacognition/route-economics.js.map +1 -0
- package/dist/metacognition/runtime-bridge.d.ts +54 -0
- package/dist/metacognition/runtime-bridge.d.ts.map +1 -0
- package/dist/metacognition/runtime-bridge.js +140 -0
- package/dist/metacognition/runtime-bridge.js.map +1 -0
- package/dist/metacognition/skills.d.ts +42 -0
- package/dist/metacognition/skills.d.ts.map +1 -0
- package/dist/metacognition/skills.js +220 -0
- package/dist/metacognition/skills.js.map +1 -0
- package/dist/metacognition/state.d.ts +110 -0
- package/dist/metacognition/state.d.ts.map +1 -0
- package/dist/metacognition/state.js +52 -0
- package/dist/metacognition/state.js.map +1 -0
- package/dist/metacognition/validation.d.ts +19 -0
- package/dist/metacognition/validation.d.ts.map +1 -0
- package/dist/metacognition/validation.js +58 -0
- package/dist/metacognition/validation.js.map +1 -0
- package/dist/metacognition/verification.d.ts +93 -0
- package/dist/metacognition/verification.d.ts.map +1 -0
- package/dist/metacognition/verification.js +132 -0
- package/dist/metacognition/verification.js.map +1 -0
- package/dist/metacognition/verifier.d.ts +49 -0
- package/dist/metacognition/verifier.d.ts.map +1 -0
- package/dist/metacognition/verifier.js +88 -0
- package/dist/metacognition/verifier.js.map +1 -0
- package/dist/modes/acp/acp-agent.d.ts +24 -0
- package/dist/modes/acp/acp-agent.d.ts.map +1 -0
- package/dist/modes/acp/acp-agent.js +133 -0
- package/dist/modes/acp/acp-agent.js.map +1 -0
- package/dist/modes/acp/acp-mode.d.ts +4 -0
- package/dist/modes/acp/acp-mode.d.ts.map +1 -0
- package/dist/modes/acp/acp-mode.js +34 -0
- package/dist/modes/acp/acp-mode.js.map +1 -0
- package/dist/modes/acp/acp-session.d.ts +4 -0
- package/dist/modes/acp/acp-session.d.ts.map +1 -0
- package/dist/modes/acp/acp-session.js +76 -0
- package/dist/modes/acp/acp-session.js.map +1 -0
- package/dist/modes/acp/acp-transport.d.ts +5 -0
- package/dist/modes/acp/acp-transport.d.ts.map +1 -0
- package/dist/modes/acp/acp-transport.js +90 -0
- package/dist/modes/acp/acp-transport.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/observation/identity.d.ts +14 -0
- package/dist/observation/identity.d.ts.map +1 -0
- package/dist/observation/identity.js +29 -0
- package/dist/observation/identity.js.map +1 -0
- package/dist/observation/index.d.ts +13 -0
- package/dist/observation/index.d.ts.map +1 -0
- package/dist/observation/index.js +13 -0
- package/dist/observation/index.js.map +1 -0
- package/dist/observation/observe-mode.d.ts +46 -0
- package/dist/observation/observe-mode.d.ts.map +1 -0
- package/dist/observation/observe-mode.js +83 -0
- package/dist/observation/observe-mode.js.map +1 -0
- package/dist/observation/store.d.ts +53 -0
- package/dist/observation/store.d.ts.map +1 -0
- package/dist/observation/store.js +126 -0
- package/dist/observation/store.js.map +1 -0
- package/dist/observation/types.d.ts +72 -0
- package/dist/observation/types.d.ts.map +1 -0
- package/dist/observation/types.js +9 -0
- package/dist/observation/types.js.map +1 -0
- package/dist/observation/view.d.ts +39 -0
- package/dist/observation/view.d.ts.map +1 -0
- package/dist/observation/view.js +173 -0
- package/dist/observation/view.js.map +1 -0
- package/docs/audit-revalidation-2026-09-17.md +77 -0
- package/docs/devin-harness.md +33 -4
- package/docs/ecraf-normalization.md +83 -0
- package/docs/metacognition.md +51 -0
- package/docs/model-catalog-refresh.md +110 -1
- package/docs/models.md +1 -1
- package/docs/neo.md +134 -0
- package/docs/providers.md +125 -6
- package/docs/run-usage-ledger.md +56 -0
- package/docs/runtime-algorithms.md +151 -3
- package/docs/skills.md +1 -1
- package/docs/usage.md +2 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/adaptive-agent-runtime.ts +14 -1
- package/examples/extensions/subagent/graph-result.ts +48 -0
- package/examples/extensions/subagent/index.ts +246 -111
- package/examples/extensions/subagent/managed-process-tree.ts +42 -0
- package/examples/extensions/subagent/managed-process.test.ts +24 -0
- package/examples/extensions/subagent/managed-process.ts +93 -112
- package/examples/extensions/subagent/subagent-runtime-types.ts +17 -1
- package/examples/extensions/subagent/subagent-stream.ts +161 -0
- package/examples/extensions/terminal-browser/README.md +54 -0
- package/examples/extensions/terminal-browser/bridge-protocol.ts +29 -0
- package/examples/extensions/terminal-browser/bridge.ts +219 -0
- package/examples/extensions/terminal-browser/browser-surface.ts +288 -0
- package/examples/extensions/terminal-browser/index.ts +215 -0
- package/examples/extensions/terminal-browser/placeholders.ts +49 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +8 -7
- package/resources/neo/skills/omk-browser/SKILL.md +32 -0
- package/resources/neo/skills/omk-code-review/SKILL.md +24 -0
- package/resources/neo/skills/omk-computeruse/SKILL.md +34 -0
- package/resources/neo/skills/omk-mcp-setup/SKILL.md +48 -0
- package/resources/neo/skills/omk-research/SKILL.md +24 -0
- package/resources/neo/skills/omk-site/SKILL.md +28 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time-aware independent verification (Jev audit algorithm A7, finding F07).
|
|
3
|
+
*
|
|
4
|
+
* F07 is the confusion between "each condition was satisfied at some point"
|
|
5
|
+
* and "they hold together now". Keeping `CompleteCurrent` and `CompleteEver`
|
|
6
|
+
* apart resolves it without throwing away valid history.
|
|
7
|
+
*
|
|
8
|
+
* `unknown` is a third value, not a synonym for `false`. A missing field or an
|
|
9
|
+
* incomplete collection scope means the evidence is absent; any binary rule
|
|
10
|
+
* that negates it into `true` manufactures a verification that never happened.
|
|
11
|
+
*
|
|
12
|
+
* Evidence strength is ordered but deliberately not a universal trust score:
|
|
13
|
+
* a backend response still has to be matched to the right account and request.
|
|
14
|
+
* The point is to hold a verification signal that does not share the executing
|
|
15
|
+
* model's uncertainty.
|
|
16
|
+
*/
|
|
17
|
+
export type ConditionValue = "true" | "false" | "unknown";
|
|
18
|
+
export interface ConditionObservation {
|
|
19
|
+
readonly snapshotId: string;
|
|
20
|
+
/** Target generation this snapshot belongs to. */
|
|
21
|
+
readonly generation: number;
|
|
22
|
+
readonly values: Readonly<Record<string, ConditionValue>>;
|
|
23
|
+
}
|
|
24
|
+
export interface UnsatisfiedCondition {
|
|
25
|
+
readonly condition: string;
|
|
26
|
+
readonly value: ConditionValue;
|
|
27
|
+
}
|
|
28
|
+
export type CompletionResult = {
|
|
29
|
+
readonly complete: true;
|
|
30
|
+
} | {
|
|
31
|
+
readonly complete: false;
|
|
32
|
+
readonly unsatisfied: readonly UnsatisfiedCondition[];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Every current condition must hold in the *same* snapshot.
|
|
36
|
+
*
|
|
37
|
+
* Evaluating them across snapshots would let a condition that has since
|
|
38
|
+
* flipped keep satisfying the gate.
|
|
39
|
+
*/
|
|
40
|
+
export declare function completeCurrent(conditions: readonly string[], snapshot: ConditionObservation): CompletionResult;
|
|
41
|
+
/**
|
|
42
|
+
* Each historical condition must have been observed true at least once in the
|
|
43
|
+
* supplied evidence set, which the caller scopes to the current task.
|
|
44
|
+
*/
|
|
45
|
+
export declare function completeEver(conditions: readonly string[], history: readonly ConditionObservation[]): CompletionResult;
|
|
46
|
+
export type EvidenceKind = "authoritative-query" | "structured-remote-linked" | "independent-ui" | "page-success-text" | "model-completion-claim";
|
|
47
|
+
export declare function evidenceStrength(kind: EvidenceKind): number;
|
|
48
|
+
export type VerificationLevel = "REMOTE_EFFECT_VERIFIED" | "UI_VERIFIED" | "CLAIMED_ONLY";
|
|
49
|
+
/**
|
|
50
|
+
* Label a result by the strongest evidence actually held.
|
|
51
|
+
*
|
|
52
|
+
* A UI observation is reported as `UI_VERIFIED`, never as
|
|
53
|
+
* `REMOTE_EFFECT_VERIFIED`: if the target system offers no authoritative
|
|
54
|
+
* query, the honest move is to lower the claimed level, not to borrow one.
|
|
55
|
+
*/
|
|
56
|
+
export declare function strongestEvidence(kinds: readonly EvidenceKind[]): VerificationLevel;
|
|
57
|
+
export interface EvidenceItem {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
/** Common-cause group, e.g. one DOM snapshot that many readings derive from. */
|
|
60
|
+
readonly sourceGroup: string;
|
|
61
|
+
}
|
|
62
|
+
export interface EvidenceGrouping {
|
|
63
|
+
readonly independentCount: number;
|
|
64
|
+
readonly byGroup: Readonly<Record<string, number>>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Collapse correlated readings into their source groups.
|
|
68
|
+
*
|
|
69
|
+
* Fifty screenshots of one screen are one witness. Text, accessibility names
|
|
70
|
+
* and rendered copy from the same DOM share a common cause, so counting them
|
|
71
|
+
* separately inflates apparent independent confirmation.
|
|
72
|
+
*/
|
|
73
|
+
export declare function independentEvidenceGroups(items: readonly EvidenceItem[]): EvidenceGrouping;
|
|
74
|
+
export interface VerifierSample {
|
|
75
|
+
readonly verdict: ConditionValue;
|
|
76
|
+
/** Externally established truth, not another model's opinion. */
|
|
77
|
+
readonly truth: "true" | "false";
|
|
78
|
+
}
|
|
79
|
+
export interface VerifierQuality {
|
|
80
|
+
/** Undefined when no negative case was sampled; that is absent evidence. */
|
|
81
|
+
readonly falsePositiveRate: number | undefined;
|
|
82
|
+
readonly falseNegativeRate: number | undefined;
|
|
83
|
+
readonly unknownRate: number;
|
|
84
|
+
readonly samples: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Measure the verifier before reporting any success rate.
|
|
88
|
+
*
|
|
89
|
+
* A mislabelling verifier contaminates every downstream selector and bandit
|
|
90
|
+
* trained on its labels, so its error rates are the prior question.
|
|
91
|
+
*/
|
|
92
|
+
export declare function verifierQuality(samples: readonly VerifierSample[]): VerifierQuality;
|
|
93
|
+
//# sourceMappingURL=verification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../../src/metacognition/verification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAC/B;AAED,MAAM,MAAM,gBAAgB,GACzB;IAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAAE,CAAC;AAEvF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,oBAAoB,GAAG,gBAAgB,CAS/G;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,OAAO,EAAE,SAAS,oBAAoB,EAAE,GACtC,gBAAgB,CAWlB;AAED,MAAM,MAAM,YAAY,GACrB,qBAAqB,GACrB,0BAA0B,GAC1B,gBAAgB,GAChB,mBAAmB,GACnB,wBAAwB,CAAC;AAU5B,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAI3D;AAED,MAAM,MAAM,iBAAiB,GAAG,wBAAwB,GAAG,aAAa,GAAG,cAAc,CAAC;AAE1F;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,iBAAiB,CAOnF;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,gBAAgB,CAW1F;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,eAAe,CAuBnF","sourcesContent":["/**\n * Time-aware independent verification (Jev audit algorithm A7, finding F07).\n *\n * F07 is the confusion between \"each condition was satisfied at some point\"\n * and \"they hold together now\". Keeping `CompleteCurrent` and `CompleteEver`\n * apart resolves it without throwing away valid history.\n *\n * `unknown` is a third value, not a synonym for `false`. A missing field or an\n * incomplete collection scope means the evidence is absent; any binary rule\n * that negates it into `true` manufactures a verification that never happened.\n *\n * Evidence strength is ordered but deliberately not a universal trust score:\n * a backend response still has to be matched to the right account and request.\n * The point is to hold a verification signal that does not share the executing\n * model's uncertainty.\n */\n\nimport { ensure } from \"./validation.ts\";\n\nexport type ConditionValue = \"true\" | \"false\" | \"unknown\";\n\nexport interface ConditionObservation {\n\treadonly snapshotId: string;\n\t/** Target generation this snapshot belongs to. */\n\treadonly generation: number;\n\treadonly values: Readonly<Record<string, ConditionValue>>;\n}\n\nexport interface UnsatisfiedCondition {\n\treadonly condition: string;\n\treadonly value: ConditionValue;\n}\n\nexport type CompletionResult =\n\t| { readonly complete: true }\n\t| { readonly complete: false; readonly unsatisfied: readonly UnsatisfiedCondition[] };\n\n/**\n * Every current condition must hold in the *same* snapshot.\n *\n * Evaluating them across snapshots would let a condition that has since\n * flipped keep satisfying the gate.\n */\nexport function completeCurrent(conditions: readonly string[], snapshot: ConditionObservation): CompletionResult {\n\tensure(Array.isArray(conditions) && conditions.length > 0, \"current conditions must be non-empty\");\n\tconst unsatisfied: UnsatisfiedCondition[] = [];\n\tfor (const condition of conditions) {\n\t\t// An absent field is unknown, never false.\n\t\tconst value = snapshot.values[condition] ?? \"unknown\";\n\t\tif (value !== \"true\") unsatisfied.push({ condition, value });\n\t}\n\treturn unsatisfied.length === 0 ? { complete: true } : { complete: false, unsatisfied };\n}\n\n/**\n * Each historical condition must have been observed true at least once in the\n * supplied evidence set, which the caller scopes to the current task.\n */\nexport function completeEver(\n\tconditions: readonly string[],\n\thistory: readonly ConditionObservation[],\n): CompletionResult {\n\tensure(Array.isArray(conditions) && conditions.length > 0, \"ever conditions must be non-empty\");\n\tensure(Array.isArray(history) && history.length > 0, \"history must be non-empty to judge an ever condition\");\n\tconst unsatisfied: UnsatisfiedCondition[] = [];\n\tfor (const condition of conditions) {\n\t\tconst seenTrue = history.some((snapshot) => snapshot.values[condition] === \"true\");\n\t\tif (seenTrue) continue;\n\t\tconst anyKnown = history.some((snapshot) => snapshot.values[condition] === \"false\");\n\t\tunsatisfied.push({ condition, value: anyKnown ? \"false\" : \"unknown\" });\n\t}\n\treturn unsatisfied.length === 0 ? { complete: true } : { complete: false, unsatisfied };\n}\n\nexport type EvidenceKind =\n\t| \"authoritative-query\"\n\t| \"structured-remote-linked\"\n\t| \"independent-ui\"\n\t| \"page-success-text\"\n\t| \"model-completion-claim\";\n\nconst EVIDENCE_RANK: Readonly<Record<EvidenceKind, number>> = {\n\t\"authoritative-query\": 4,\n\t\"structured-remote-linked\": 3,\n\t\"independent-ui\": 2,\n\t\"page-success-text\": 1,\n\t\"model-completion-claim\": 0,\n};\n\nexport function evidenceStrength(kind: EvidenceKind): number {\n\tconst rank = EVIDENCE_RANK[kind];\n\tensure(rank !== undefined, `unknown evidence kind: ${String(kind)}`);\n\treturn rank;\n}\n\nexport type VerificationLevel = \"REMOTE_EFFECT_VERIFIED\" | \"UI_VERIFIED\" | \"CLAIMED_ONLY\";\n\n/**\n * Label a result by the strongest evidence actually held.\n *\n * A UI observation is reported as `UI_VERIFIED`, never as\n * `REMOTE_EFFECT_VERIFIED`: if the target system offers no authoritative\n * query, the honest move is to lower the claimed level, not to borrow one.\n */\nexport function strongestEvidence(kinds: readonly EvidenceKind[]): VerificationLevel {\n\tensure(Array.isArray(kinds) && kinds.length > 0, \"evidence set must be non-empty\");\n\tlet best = -1;\n\tfor (const kind of kinds) best = Math.max(best, evidenceStrength(kind));\n\tif (best >= EVIDENCE_RANK[\"structured-remote-linked\"]) return \"REMOTE_EFFECT_VERIFIED\";\n\tif (best >= EVIDENCE_RANK[\"independent-ui\"]) return \"UI_VERIFIED\";\n\treturn \"CLAIMED_ONLY\";\n}\n\nexport interface EvidenceItem {\n\treadonly id: string;\n\t/** Common-cause group, e.g. one DOM snapshot that many readings derive from. */\n\treadonly sourceGroup: string;\n}\n\nexport interface EvidenceGrouping {\n\treadonly independentCount: number;\n\treadonly byGroup: Readonly<Record<string, number>>;\n}\n\n/**\n * Collapse correlated readings into their source groups.\n *\n * Fifty screenshots of one screen are one witness. Text, accessibility names\n * and rendered copy from the same DOM share a common cause, so counting them\n * separately inflates apparent independent confirmation.\n */\nexport function independentEvidenceGroups(items: readonly EvidenceItem[]): EvidenceGrouping {\n\tensure(Array.isArray(items) && items.length > 0, \"evidence items must be non-empty\");\n\tconst byGroup: Record<string, number> = {};\n\tfor (const item of items) {\n\t\tensure(\n\t\t\ttypeof item.sourceGroup === \"string\" && item.sourceGroup.length > 0,\n\t\t\t\"each evidence item needs a declared sourceGroup\",\n\t\t);\n\t\tbyGroup[item.sourceGroup] = (byGroup[item.sourceGroup] ?? 0) + 1;\n\t}\n\treturn { independentCount: Object.keys(byGroup).length, byGroup };\n}\n\nexport interface VerifierSample {\n\treadonly verdict: ConditionValue;\n\t/** Externally established truth, not another model's opinion. */\n\treadonly truth: \"true\" | \"false\";\n}\n\nexport interface VerifierQuality {\n\t/** Undefined when no negative case was sampled; that is absent evidence. */\n\treadonly falsePositiveRate: number | undefined;\n\treadonly falseNegativeRate: number | undefined;\n\treadonly unknownRate: number;\n\treadonly samples: number;\n}\n\n/**\n * Measure the verifier before reporting any success rate.\n *\n * A mislabelling verifier contaminates every downstream selector and bandit\n * trained on its labels, so its error rates are the prior question.\n */\nexport function verifierQuality(samples: readonly VerifierSample[]): VerifierQuality {\n\tensure(Array.isArray(samples) && samples.length > 0, \"verifier samples must be non-empty\");\n\tlet positives = 0;\n\tlet negatives = 0;\n\tlet falsePositives = 0;\n\tlet falseNegatives = 0;\n\tlet unknowns = 0;\n\tfor (const sample of samples) {\n\t\tif (sample.verdict === \"unknown\") unknowns += 1;\n\t\tif (sample.truth === \"true\") {\n\t\t\tpositives += 1;\n\t\t\tif (sample.verdict === \"false\") falseNegatives += 1;\n\t\t} else {\n\t\t\tnegatives += 1;\n\t\t\tif (sample.verdict === \"true\") falsePositives += 1;\n\t\t}\n\t}\n\treturn {\n\t\tfalsePositiveRate: negatives > 0 ? falsePositives / negatives : undefined,\n\t\tfalseNegativeRate: positives > 0 ? falseNegatives / positives : undefined,\n\t\tunknownRate: unknowns / samples.length,\n\t\tsamples: samples.length,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time-aware independent verification (Jev audit algorithm A7, finding F07).
|
|
3
|
+
*
|
|
4
|
+
* F07 is the confusion between "each condition was satisfied at some point"
|
|
5
|
+
* and "they hold together now". Keeping `CompleteCurrent` and `CompleteEver`
|
|
6
|
+
* apart resolves it without throwing away valid history.
|
|
7
|
+
*
|
|
8
|
+
* `unknown` is a third value, not a synonym for `false`. A missing field or an
|
|
9
|
+
* incomplete collection scope means the evidence is absent; any binary rule
|
|
10
|
+
* that negates it into `true` manufactures a verification that never happened.
|
|
11
|
+
*
|
|
12
|
+
* Evidence strength is ordered but deliberately not a universal trust score:
|
|
13
|
+
* a backend response still has to be matched to the right account and request.
|
|
14
|
+
* The point is to hold a verification signal that does not share the executing
|
|
15
|
+
* model's uncertainty.
|
|
16
|
+
*/
|
|
17
|
+
import { ensure } from "./validation.js";
|
|
18
|
+
/**
|
|
19
|
+
* Every current condition must hold in the *same* snapshot.
|
|
20
|
+
*
|
|
21
|
+
* Evaluating them across snapshots would let a condition that has since
|
|
22
|
+
* flipped keep satisfying the gate.
|
|
23
|
+
*/
|
|
24
|
+
export function completeCurrent(conditions, snapshot) {
|
|
25
|
+
ensure(Array.isArray(conditions) && conditions.length > 0, "current conditions must be non-empty");
|
|
26
|
+
const unsatisfied = [];
|
|
27
|
+
for (const condition of conditions) {
|
|
28
|
+
// An absent field is unknown, never false.
|
|
29
|
+
const value = snapshot.values[condition] ?? "unknown";
|
|
30
|
+
if (value !== "true")
|
|
31
|
+
unsatisfied.push({ condition, value });
|
|
32
|
+
}
|
|
33
|
+
return unsatisfied.length === 0 ? { complete: true } : { complete: false, unsatisfied };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Each historical condition must have been observed true at least once in the
|
|
37
|
+
* supplied evidence set, which the caller scopes to the current task.
|
|
38
|
+
*/
|
|
39
|
+
export function completeEver(conditions, history) {
|
|
40
|
+
ensure(Array.isArray(conditions) && conditions.length > 0, "ever conditions must be non-empty");
|
|
41
|
+
ensure(Array.isArray(history) && history.length > 0, "history must be non-empty to judge an ever condition");
|
|
42
|
+
const unsatisfied = [];
|
|
43
|
+
for (const condition of conditions) {
|
|
44
|
+
const seenTrue = history.some((snapshot) => snapshot.values[condition] === "true");
|
|
45
|
+
if (seenTrue)
|
|
46
|
+
continue;
|
|
47
|
+
const anyKnown = history.some((snapshot) => snapshot.values[condition] === "false");
|
|
48
|
+
unsatisfied.push({ condition, value: anyKnown ? "false" : "unknown" });
|
|
49
|
+
}
|
|
50
|
+
return unsatisfied.length === 0 ? { complete: true } : { complete: false, unsatisfied };
|
|
51
|
+
}
|
|
52
|
+
const EVIDENCE_RANK = {
|
|
53
|
+
"authoritative-query": 4,
|
|
54
|
+
"structured-remote-linked": 3,
|
|
55
|
+
"independent-ui": 2,
|
|
56
|
+
"page-success-text": 1,
|
|
57
|
+
"model-completion-claim": 0,
|
|
58
|
+
};
|
|
59
|
+
export function evidenceStrength(kind) {
|
|
60
|
+
const rank = EVIDENCE_RANK[kind];
|
|
61
|
+
ensure(rank !== undefined, `unknown evidence kind: ${String(kind)}`);
|
|
62
|
+
return rank;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Label a result by the strongest evidence actually held.
|
|
66
|
+
*
|
|
67
|
+
* A UI observation is reported as `UI_VERIFIED`, never as
|
|
68
|
+
* `REMOTE_EFFECT_VERIFIED`: if the target system offers no authoritative
|
|
69
|
+
* query, the honest move is to lower the claimed level, not to borrow one.
|
|
70
|
+
*/
|
|
71
|
+
export function strongestEvidence(kinds) {
|
|
72
|
+
ensure(Array.isArray(kinds) && kinds.length > 0, "evidence set must be non-empty");
|
|
73
|
+
let best = -1;
|
|
74
|
+
for (const kind of kinds)
|
|
75
|
+
best = Math.max(best, evidenceStrength(kind));
|
|
76
|
+
if (best >= EVIDENCE_RANK["structured-remote-linked"])
|
|
77
|
+
return "REMOTE_EFFECT_VERIFIED";
|
|
78
|
+
if (best >= EVIDENCE_RANK["independent-ui"])
|
|
79
|
+
return "UI_VERIFIED";
|
|
80
|
+
return "CLAIMED_ONLY";
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Collapse correlated readings into their source groups.
|
|
84
|
+
*
|
|
85
|
+
* Fifty screenshots of one screen are one witness. Text, accessibility names
|
|
86
|
+
* and rendered copy from the same DOM share a common cause, so counting them
|
|
87
|
+
* separately inflates apparent independent confirmation.
|
|
88
|
+
*/
|
|
89
|
+
export function independentEvidenceGroups(items) {
|
|
90
|
+
ensure(Array.isArray(items) && items.length > 0, "evidence items must be non-empty");
|
|
91
|
+
const byGroup = {};
|
|
92
|
+
for (const item of items) {
|
|
93
|
+
ensure(typeof item.sourceGroup === "string" && item.sourceGroup.length > 0, "each evidence item needs a declared sourceGroup");
|
|
94
|
+
byGroup[item.sourceGroup] = (byGroup[item.sourceGroup] ?? 0) + 1;
|
|
95
|
+
}
|
|
96
|
+
return { independentCount: Object.keys(byGroup).length, byGroup };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Measure the verifier before reporting any success rate.
|
|
100
|
+
*
|
|
101
|
+
* A mislabelling verifier contaminates every downstream selector and bandit
|
|
102
|
+
* trained on its labels, so its error rates are the prior question.
|
|
103
|
+
*/
|
|
104
|
+
export function verifierQuality(samples) {
|
|
105
|
+
ensure(Array.isArray(samples) && samples.length > 0, "verifier samples must be non-empty");
|
|
106
|
+
let positives = 0;
|
|
107
|
+
let negatives = 0;
|
|
108
|
+
let falsePositives = 0;
|
|
109
|
+
let falseNegatives = 0;
|
|
110
|
+
let unknowns = 0;
|
|
111
|
+
for (const sample of samples) {
|
|
112
|
+
if (sample.verdict === "unknown")
|
|
113
|
+
unknowns += 1;
|
|
114
|
+
if (sample.truth === "true") {
|
|
115
|
+
positives += 1;
|
|
116
|
+
if (sample.verdict === "false")
|
|
117
|
+
falseNegatives += 1;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
negatives += 1;
|
|
121
|
+
if (sample.verdict === "true")
|
|
122
|
+
falsePositives += 1;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
falsePositiveRate: negatives > 0 ? falsePositives / negatives : undefined,
|
|
127
|
+
falseNegativeRate: positives > 0 ? falseNegatives / positives : undefined,
|
|
128
|
+
unknownRate: unknowns / samples.length,
|
|
129
|
+
samples: samples.length,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/metacognition/verification.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Time-aware independent verification (Jev audit algorithm A7, finding F07).\n *\n * F07 is the confusion between \"each condition was satisfied at some point\"\n * and \"they hold together now\". Keeping `CompleteCurrent` and `CompleteEver`\n * apart resolves it without throwing away valid history.\n *\n * `unknown` is a third value, not a synonym for `false`. A missing field or an\n * incomplete collection scope means the evidence is absent; any binary rule\n * that negates it into `true` manufactures a verification that never happened.\n *\n * Evidence strength is ordered but deliberately not a universal trust score:\n * a backend response still has to be matched to the right account and request.\n * The point is to hold a verification signal that does not share the executing\n * model's uncertainty.\n */\n\nimport { ensure } from \"./validation.ts\";\n\nexport type ConditionValue = \"true\" | \"false\" | \"unknown\";\n\nexport interface ConditionObservation {\n\treadonly snapshotId: string;\n\t/** Target generation this snapshot belongs to. */\n\treadonly generation: number;\n\treadonly values: Readonly<Record<string, ConditionValue>>;\n}\n\nexport interface UnsatisfiedCondition {\n\treadonly condition: string;\n\treadonly value: ConditionValue;\n}\n\nexport type CompletionResult =\n\t| { readonly complete: true }\n\t| { readonly complete: false; readonly unsatisfied: readonly UnsatisfiedCondition[] };\n\n/**\n * Every current condition must hold in the *same* snapshot.\n *\n * Evaluating them across snapshots would let a condition that has since\n * flipped keep satisfying the gate.\n */\nexport function completeCurrent(conditions: readonly string[], snapshot: ConditionObservation): CompletionResult {\n\tensure(Array.isArray(conditions) && conditions.length > 0, \"current conditions must be non-empty\");\n\tconst unsatisfied: UnsatisfiedCondition[] = [];\n\tfor (const condition of conditions) {\n\t\t// An absent field is unknown, never false.\n\t\tconst value = snapshot.values[condition] ?? \"unknown\";\n\t\tif (value !== \"true\") unsatisfied.push({ condition, value });\n\t}\n\treturn unsatisfied.length === 0 ? { complete: true } : { complete: false, unsatisfied };\n}\n\n/**\n * Each historical condition must have been observed true at least once in the\n * supplied evidence set, which the caller scopes to the current task.\n */\nexport function completeEver(\n\tconditions: readonly string[],\n\thistory: readonly ConditionObservation[],\n): CompletionResult {\n\tensure(Array.isArray(conditions) && conditions.length > 0, \"ever conditions must be non-empty\");\n\tensure(Array.isArray(history) && history.length > 0, \"history must be non-empty to judge an ever condition\");\n\tconst unsatisfied: UnsatisfiedCondition[] = [];\n\tfor (const condition of conditions) {\n\t\tconst seenTrue = history.some((snapshot) => snapshot.values[condition] === \"true\");\n\t\tif (seenTrue) continue;\n\t\tconst anyKnown = history.some((snapshot) => snapshot.values[condition] === \"false\");\n\t\tunsatisfied.push({ condition, value: anyKnown ? \"false\" : \"unknown\" });\n\t}\n\treturn unsatisfied.length === 0 ? { complete: true } : { complete: false, unsatisfied };\n}\n\nexport type EvidenceKind =\n\t| \"authoritative-query\"\n\t| \"structured-remote-linked\"\n\t| \"independent-ui\"\n\t| \"page-success-text\"\n\t| \"model-completion-claim\";\n\nconst EVIDENCE_RANK: Readonly<Record<EvidenceKind, number>> = {\n\t\"authoritative-query\": 4,\n\t\"structured-remote-linked\": 3,\n\t\"independent-ui\": 2,\n\t\"page-success-text\": 1,\n\t\"model-completion-claim\": 0,\n};\n\nexport function evidenceStrength(kind: EvidenceKind): number {\n\tconst rank = EVIDENCE_RANK[kind];\n\tensure(rank !== undefined, `unknown evidence kind: ${String(kind)}`);\n\treturn rank;\n}\n\nexport type VerificationLevel = \"REMOTE_EFFECT_VERIFIED\" | \"UI_VERIFIED\" | \"CLAIMED_ONLY\";\n\n/**\n * Label a result by the strongest evidence actually held.\n *\n * A UI observation is reported as `UI_VERIFIED`, never as\n * `REMOTE_EFFECT_VERIFIED`: if the target system offers no authoritative\n * query, the honest move is to lower the claimed level, not to borrow one.\n */\nexport function strongestEvidence(kinds: readonly EvidenceKind[]): VerificationLevel {\n\tensure(Array.isArray(kinds) && kinds.length > 0, \"evidence set must be non-empty\");\n\tlet best = -1;\n\tfor (const kind of kinds) best = Math.max(best, evidenceStrength(kind));\n\tif (best >= EVIDENCE_RANK[\"structured-remote-linked\"]) return \"REMOTE_EFFECT_VERIFIED\";\n\tif (best >= EVIDENCE_RANK[\"independent-ui\"]) return \"UI_VERIFIED\";\n\treturn \"CLAIMED_ONLY\";\n}\n\nexport interface EvidenceItem {\n\treadonly id: string;\n\t/** Common-cause group, e.g. one DOM snapshot that many readings derive from. */\n\treadonly sourceGroup: string;\n}\n\nexport interface EvidenceGrouping {\n\treadonly independentCount: number;\n\treadonly byGroup: Readonly<Record<string, number>>;\n}\n\n/**\n * Collapse correlated readings into their source groups.\n *\n * Fifty screenshots of one screen are one witness. Text, accessibility names\n * and rendered copy from the same DOM share a common cause, so counting them\n * separately inflates apparent independent confirmation.\n */\nexport function independentEvidenceGroups(items: readonly EvidenceItem[]): EvidenceGrouping {\n\tensure(Array.isArray(items) && items.length > 0, \"evidence items must be non-empty\");\n\tconst byGroup: Record<string, number> = {};\n\tfor (const item of items) {\n\t\tensure(\n\t\t\ttypeof item.sourceGroup === \"string\" && item.sourceGroup.length > 0,\n\t\t\t\"each evidence item needs a declared sourceGroup\",\n\t\t);\n\t\tbyGroup[item.sourceGroup] = (byGroup[item.sourceGroup] ?? 0) + 1;\n\t}\n\treturn { independentCount: Object.keys(byGroup).length, byGroup };\n}\n\nexport interface VerifierSample {\n\treadonly verdict: ConditionValue;\n\t/** Externally established truth, not another model's opinion. */\n\treadonly truth: \"true\" | \"false\";\n}\n\nexport interface VerifierQuality {\n\t/** Undefined when no negative case was sampled; that is absent evidence. */\n\treadonly falsePositiveRate: number | undefined;\n\treadonly falseNegativeRate: number | undefined;\n\treadonly unknownRate: number;\n\treadonly samples: number;\n}\n\n/**\n * Measure the verifier before reporting any success rate.\n *\n * A mislabelling verifier contaminates every downstream selector and bandit\n * trained on its labels, so its error rates are the prior question.\n */\nexport function verifierQuality(samples: readonly VerifierSample[]): VerifierQuality {\n\tensure(Array.isArray(samples) && samples.length > 0, \"verifier samples must be non-empty\");\n\tlet positives = 0;\n\tlet negatives = 0;\n\tlet falsePositives = 0;\n\tlet falseNegatives = 0;\n\tlet unknowns = 0;\n\tfor (const sample of samples) {\n\t\tif (sample.verdict === \"unknown\") unknowns += 1;\n\t\tif (sample.truth === \"true\") {\n\t\t\tpositives += 1;\n\t\t\tif (sample.verdict === \"false\") falseNegatives += 1;\n\t\t} else {\n\t\t\tnegatives += 1;\n\t\t\tif (sample.verdict === \"true\") falsePositives += 1;\n\t\t}\n\t}\n\treturn {\n\t\tfalsePositiveRate: negatives > 0 ? falsePositives / negatives : undefined,\n\t\tfalseNegativeRate: positives > 0 ? falseNegatives / positives : undefined,\n\t\tunknownRate: unknowns / samples.length,\n\t\tsamples: samples.length,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type MutantClass = "killed-intended" | "survived" | "equivalent" | "invalid-compile" | "environment-failure" | "timeout" | "killed-unintended";
|
|
2
|
+
export interface MutantRecord {
|
|
3
|
+
readonly mutantId: string;
|
|
4
|
+
readonly obligationId: string;
|
|
5
|
+
/** The host classifies the outcome; this module never guesses. */
|
|
6
|
+
readonly classification: MutantClass;
|
|
7
|
+
/** Whether the intended obligation violation was what the check caught. */
|
|
8
|
+
readonly intendedViolation: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface VerifierEvaluation {
|
|
11
|
+
readonly obligationId: string;
|
|
12
|
+
/** D_v over valid non-equivalent mutants; "unknown" when empty. */
|
|
13
|
+
readonly detectionRate: number | "unknown";
|
|
14
|
+
readonly evaluated: number;
|
|
15
|
+
readonly excluded: Readonly<Record<Exclude<MutantClass, "killed-intended" | "survived">, number>>;
|
|
16
|
+
readonly survivingMutantIds: readonly string[];
|
|
17
|
+
readonly blindSpots: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function evaluateVerifier(obligationId: string, mutants: readonly MutantRecord[], checksValidOnHealthy: boolean): VerifierEvaluation;
|
|
20
|
+
/**
|
|
21
|
+
* §7.4 metamorphic relation: Pre(x,T) ⟹ R(f(x), f(T(x))). The relation must
|
|
22
|
+
* be a declared required property of this program — never a universal rule.
|
|
23
|
+
*/
|
|
24
|
+
export interface MetamorphicRelation {
|
|
25
|
+
readonly relationId: string;
|
|
26
|
+
readonly description: string;
|
|
27
|
+
readonly precondition: string;
|
|
28
|
+
readonly requiredProperty: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function relationApplicable(rel: MetamorphicRelation): boolean;
|
|
31
|
+
/** §10.1 progress key: same key + no new adopted evidence = repetition. */
|
|
32
|
+
export interface ProgressKey {
|
|
33
|
+
readonly goalScope: string;
|
|
34
|
+
readonly candidateFamily: string;
|
|
35
|
+
readonly errorClass: string;
|
|
36
|
+
readonly approach: string;
|
|
37
|
+
readonly checkMethod: string;
|
|
38
|
+
readonly sourceFamily: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function progressKey(k: ProgressKey): string;
|
|
41
|
+
export declare function isStagnant(current: ProgressKey, history: readonly {
|
|
42
|
+
key: string;
|
|
43
|
+
newEvidence: boolean;
|
|
44
|
+
resolvedObligations: number;
|
|
45
|
+
newValidChecks: number;
|
|
46
|
+
}[], maxRepetitions: number): boolean;
|
|
47
|
+
/** §10.2 net strategy-switch score with hysteresis margin. */
|
|
48
|
+
export declare function netSwitchValue(estimatedLossDelta: number, cost: number, switchCost: number): number;
|
|
49
|
+
//# sourceMappingURL=verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../src/metacognition/verifier.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,WAAW,GACpB,iBAAiB,GACjB,UAAU,GACV,YAAY,GACZ,iBAAiB,GACjB,qBAAqB,GACrB,SAAS,GACT,mBAAmB,CAAC;AACvB,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;CACpC;AACD,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,iBAAiB,GAAG,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAClG,QAAQ,CAAC,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAID,wBAAgB,gBAAgB,CAC/B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,oBAAoB,EAAE,OAAO,GAC3B,kBAAkB,CAsDpB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AACD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAEpE;AAED,4EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AACD,wBAAgB,WAAW,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAElD;AACD,wBAAgB,UAAU,CACzB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,SAAS;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,EAAE,EAC9G,cAAc,EAAE,MAAM,GACpB,OAAO,CAUT;AAED,+DAA8D;AAC9D,wBAAgB,cAAc,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAKnG","sourcesContent":["/**\n * Algorithm D — meta-verification: checking that a check detects the defect\n * it claims to cover. Spec §7.\n *\n * Obligation-scoped negative controls are evaluated over VALID, non-equivalent\n * mutants only. Environment failures, compile-broken mutants, and timeouts are\n * never counted as semantic detections. An empty denominator is `unknown`,\n * never a score. This is an empirical detection rate for this mutant set,\n * not the probability the code is correct.\n */\nimport { ensure, finite, integer, lexical, member, text, unique } from \"./validation.ts\";\n\nexport type MutantClass =\n\t| \"killed-intended\"\n\t| \"survived\"\n\t| \"equivalent\"\n\t| \"invalid-compile\"\n\t| \"environment-failure\"\n\t| \"timeout\"\n\t| \"killed-unintended\";\nexport interface MutantRecord {\n\treadonly mutantId: string;\n\treadonly obligationId: string;\n\t/** The host classifies the outcome; this module never guesses. */\n\treadonly classification: MutantClass;\n\t/** Whether the intended obligation violation was what the check caught. */\n\treadonly intendedViolation: boolean;\n}\nexport interface VerifierEvaluation {\n\treadonly obligationId: string;\n\t/** D_v over valid non-equivalent mutants; \"unknown\" when empty. */\n\treadonly detectionRate: number | \"unknown\";\n\treadonly evaluated: number;\n\treadonly excluded: Readonly<Record<Exclude<MutantClass, \"killed-intended\" | \"survived\">, number>>;\n\treadonly survivingMutantIds: readonly string[];\n\treadonly blindSpots: readonly string[];\n}\n\nconst MUTANT_BOUND = 1024;\n\nexport function evaluateVerifier(\n\tobligationId: string,\n\tmutants: readonly MutantRecord[],\n\tchecksValidOnHealthy: boolean,\n): VerifierEvaluation {\n\ttext(obligationId, \"obligationId\", 256);\n\tensure(mutants.length <= MUTANT_BOUND, \"too many mutants\");\n\tunique(\n\t\tmutants.map((m) => m.mutantId),\n\t\t\"mutant ids\",\n\t);\n\tconst scoped = mutants.filter((m) => m.obligationId === obligationId);\n\tconst excluded: Record<Exclude<MutantClass, \"killed-intended\" | \"survived\">, number> = {\n\t\tequivalent: 0,\n\t\t\"invalid-compile\": 0,\n\t\t\"environment-failure\": 0,\n\t\ttimeout: 0,\n\t\t\"killed-unintended\": 0,\n\t};\n\tlet detected = 0;\n\tconst survivors: string[] = [];\n\tconst blindSpots: string[] = [];\n\tfor (const m of scoped) {\n\t\tmember(\n\t\t\tm.classification,\n\t\t\t[\n\t\t\t\t\"killed-intended\",\n\t\t\t\t\"survived\",\n\t\t\t\t\"equivalent\",\n\t\t\t\t\"invalid-compile\",\n\t\t\t\t\"environment-failure\",\n\t\t\t\t\"timeout\",\n\t\t\t\t\"killed-unintended\",\n\t\t\t],\n\t\t\t\"mutant classification\",\n\t\t);\n\t\tif (m.classification === \"killed-intended\" && m.intendedViolation) {\n\t\t\tdetected += 1;\n\t\t} else if (m.classification === \"survived\") {\n\t\t\tsurvivors.push(m.mutantId);\n\t\t\tblindSpots.push(`undetected-violation:${m.mutantId}`);\n\t\t} else {\n\t\t\texcluded[m.classification as keyof typeof excluded] += 1;\n\t\t\tif (m.classification === \"invalid-compile\" || m.classification === \"environment-failure\") {\n\t\t\t\tblindSpots.push(`uninformative-mutant:${m.mutantId}`);\n\t\t\t}\n\t\t}\n\t}\n\tif (!checksValidOnHealthy) blindSpots.push(\"check-invalid-on-healthy-candidate\");\n\tconst denominator = detected + survivors.length;\n\treturn {\n\t\tobligationId,\n\t\tdetectionRate: denominator === 0 ? \"unknown\" : detected / denominator,\n\t\tevaluated: denominator,\n\t\texcluded,\n\t\tsurvivingMutantIds: survivors.sort(lexical),\n\t\tblindSpots: blindSpots.sort(lexical),\n\t};\n}\n\n/**\n * §7.4 metamorphic relation: Pre(x,T) ⟹ R(f(x), f(T(x))). The relation must\n * be a declared required property of this program — never a universal rule.\n */\nexport interface MetamorphicRelation {\n\treadonly relationId: string;\n\treadonly description: string;\n\treadonly precondition: string;\n\treadonly requiredProperty: boolean;\n}\nexport function relationApplicable(rel: MetamorphicRelation): boolean {\n\treturn rel.requiredProperty;\n}\n\n/** §10.1 progress key: same key + no new adopted evidence = repetition. */\nexport interface ProgressKey {\n\treadonly goalScope: string;\n\treadonly candidateFamily: string;\n\treadonly errorClass: string;\n\treadonly approach: string;\n\treadonly checkMethod: string;\n\treadonly sourceFamily: string;\n}\nexport function progressKey(k: ProgressKey): string {\n\treturn [k.goalScope, k.candidateFamily, k.errorClass, k.approach, k.checkMethod, k.sourceFamily].join(\"\\u001f\");\n}\nexport function isStagnant(\n\tcurrent: ProgressKey,\n\thistory: readonly { key: string; newEvidence: boolean; resolvedObligations: number; newValidChecks: number }[],\n\tmaxRepetitions: number,\n): boolean {\n\tinteger(maxRepetitions, \"maxRepetitions\", 64);\n\tconst key = progressKey(current);\n\tlet repeats = 0;\n\tfor (const entry of history) {\n\t\tif (entry.key === key && !entry.newEvidence && entry.resolvedObligations === 0 && entry.newValidChecks === 0) {\n\t\t\trepeats += 1;\n\t\t}\n\t}\n\treturn repeats >= maxRepetitions;\n}\n\n/** §10.2 net strategy-switch score with hysteresis margin. */\nexport function netSwitchValue(estimatedLossDelta: number, cost: number, switchCost: number): number {\n\tfinite(estimatedLossDelta, \"estimatedLossDelta\");\n\tfinite(cost, \"cost\");\n\tfinite(switchCost, \"switchCost\");\n\treturn estimatedLossDelta - cost - switchCost;\n}\n"]}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Algorithm D — meta-verification: checking that a check detects the defect
|
|
3
|
+
* it claims to cover. Spec §7.
|
|
4
|
+
*
|
|
5
|
+
* Obligation-scoped negative controls are evaluated over VALID, non-equivalent
|
|
6
|
+
* mutants only. Environment failures, compile-broken mutants, and timeouts are
|
|
7
|
+
* never counted as semantic detections. An empty denominator is `unknown`,
|
|
8
|
+
* never a score. This is an empirical detection rate for this mutant set,
|
|
9
|
+
* not the probability the code is correct.
|
|
10
|
+
*/
|
|
11
|
+
import { ensure, finite, integer, lexical, member, text, unique } from "./validation.js";
|
|
12
|
+
const MUTANT_BOUND = 1024;
|
|
13
|
+
export function evaluateVerifier(obligationId, mutants, checksValidOnHealthy) {
|
|
14
|
+
text(obligationId, "obligationId", 256);
|
|
15
|
+
ensure(mutants.length <= MUTANT_BOUND, "too many mutants");
|
|
16
|
+
unique(mutants.map((m) => m.mutantId), "mutant ids");
|
|
17
|
+
const scoped = mutants.filter((m) => m.obligationId === obligationId);
|
|
18
|
+
const excluded = {
|
|
19
|
+
equivalent: 0,
|
|
20
|
+
"invalid-compile": 0,
|
|
21
|
+
"environment-failure": 0,
|
|
22
|
+
timeout: 0,
|
|
23
|
+
"killed-unintended": 0,
|
|
24
|
+
};
|
|
25
|
+
let detected = 0;
|
|
26
|
+
const survivors = [];
|
|
27
|
+
const blindSpots = [];
|
|
28
|
+
for (const m of scoped) {
|
|
29
|
+
member(m.classification, [
|
|
30
|
+
"killed-intended",
|
|
31
|
+
"survived",
|
|
32
|
+
"equivalent",
|
|
33
|
+
"invalid-compile",
|
|
34
|
+
"environment-failure",
|
|
35
|
+
"timeout",
|
|
36
|
+
"killed-unintended",
|
|
37
|
+
], "mutant classification");
|
|
38
|
+
if (m.classification === "killed-intended" && m.intendedViolation) {
|
|
39
|
+
detected += 1;
|
|
40
|
+
}
|
|
41
|
+
else if (m.classification === "survived") {
|
|
42
|
+
survivors.push(m.mutantId);
|
|
43
|
+
blindSpots.push(`undetected-violation:${m.mutantId}`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
excluded[m.classification] += 1;
|
|
47
|
+
if (m.classification === "invalid-compile" || m.classification === "environment-failure") {
|
|
48
|
+
blindSpots.push(`uninformative-mutant:${m.mutantId}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!checksValidOnHealthy)
|
|
53
|
+
blindSpots.push("check-invalid-on-healthy-candidate");
|
|
54
|
+
const denominator = detected + survivors.length;
|
|
55
|
+
return {
|
|
56
|
+
obligationId,
|
|
57
|
+
detectionRate: denominator === 0 ? "unknown" : detected / denominator,
|
|
58
|
+
evaluated: denominator,
|
|
59
|
+
excluded,
|
|
60
|
+
survivingMutantIds: survivors.sort(lexical),
|
|
61
|
+
blindSpots: blindSpots.sort(lexical),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export function relationApplicable(rel) {
|
|
65
|
+
return rel.requiredProperty;
|
|
66
|
+
}
|
|
67
|
+
export function progressKey(k) {
|
|
68
|
+
return [k.goalScope, k.candidateFamily, k.errorClass, k.approach, k.checkMethod, k.sourceFamily].join("\u001f");
|
|
69
|
+
}
|
|
70
|
+
export function isStagnant(current, history, maxRepetitions) {
|
|
71
|
+
integer(maxRepetitions, "maxRepetitions", 64);
|
|
72
|
+
const key = progressKey(current);
|
|
73
|
+
let repeats = 0;
|
|
74
|
+
for (const entry of history) {
|
|
75
|
+
if (entry.key === key && !entry.newEvidence && entry.resolvedObligations === 0 && entry.newValidChecks === 0) {
|
|
76
|
+
repeats += 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return repeats >= maxRepetitions;
|
|
80
|
+
}
|
|
81
|
+
/** §10.2 net strategy-switch score with hysteresis margin. */
|
|
82
|
+
export function netSwitchValue(estimatedLossDelta, cost, switchCost) {
|
|
83
|
+
finite(estimatedLossDelta, "estimatedLossDelta");
|
|
84
|
+
finite(cost, "cost");
|
|
85
|
+
finite(switchCost, "switchCost");
|
|
86
|
+
return estimatedLossDelta - cost - switchCost;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../src/metacognition/verifier.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Algorithm D — meta-verification: checking that a check detects the defect\n * it claims to cover. Spec §7.\n *\n * Obligation-scoped negative controls are evaluated over VALID, non-equivalent\n * mutants only. Environment failures, compile-broken mutants, and timeouts are\n * never counted as semantic detections. An empty denominator is `unknown`,\n * never a score. This is an empirical detection rate for this mutant set,\n * not the probability the code is correct.\n */\nimport { ensure, finite, integer, lexical, member, text, unique } from \"./validation.ts\";\n\nexport type MutantClass =\n\t| \"killed-intended\"\n\t| \"survived\"\n\t| \"equivalent\"\n\t| \"invalid-compile\"\n\t| \"environment-failure\"\n\t| \"timeout\"\n\t| \"killed-unintended\";\nexport interface MutantRecord {\n\treadonly mutantId: string;\n\treadonly obligationId: string;\n\t/** The host classifies the outcome; this module never guesses. */\n\treadonly classification: MutantClass;\n\t/** Whether the intended obligation violation was what the check caught. */\n\treadonly intendedViolation: boolean;\n}\nexport interface VerifierEvaluation {\n\treadonly obligationId: string;\n\t/** D_v over valid non-equivalent mutants; \"unknown\" when empty. */\n\treadonly detectionRate: number | \"unknown\";\n\treadonly evaluated: number;\n\treadonly excluded: Readonly<Record<Exclude<MutantClass, \"killed-intended\" | \"survived\">, number>>;\n\treadonly survivingMutantIds: readonly string[];\n\treadonly blindSpots: readonly string[];\n}\n\nconst MUTANT_BOUND = 1024;\n\nexport function evaluateVerifier(\n\tobligationId: string,\n\tmutants: readonly MutantRecord[],\n\tchecksValidOnHealthy: boolean,\n): VerifierEvaluation {\n\ttext(obligationId, \"obligationId\", 256);\n\tensure(mutants.length <= MUTANT_BOUND, \"too many mutants\");\n\tunique(\n\t\tmutants.map((m) => m.mutantId),\n\t\t\"mutant ids\",\n\t);\n\tconst scoped = mutants.filter((m) => m.obligationId === obligationId);\n\tconst excluded: Record<Exclude<MutantClass, \"killed-intended\" | \"survived\">, number> = {\n\t\tequivalent: 0,\n\t\t\"invalid-compile\": 0,\n\t\t\"environment-failure\": 0,\n\t\ttimeout: 0,\n\t\t\"killed-unintended\": 0,\n\t};\n\tlet detected = 0;\n\tconst survivors: string[] = [];\n\tconst blindSpots: string[] = [];\n\tfor (const m of scoped) {\n\t\tmember(\n\t\t\tm.classification,\n\t\t\t[\n\t\t\t\t\"killed-intended\",\n\t\t\t\t\"survived\",\n\t\t\t\t\"equivalent\",\n\t\t\t\t\"invalid-compile\",\n\t\t\t\t\"environment-failure\",\n\t\t\t\t\"timeout\",\n\t\t\t\t\"killed-unintended\",\n\t\t\t],\n\t\t\t\"mutant classification\",\n\t\t);\n\t\tif (m.classification === \"killed-intended\" && m.intendedViolation) {\n\t\t\tdetected += 1;\n\t\t} else if (m.classification === \"survived\") {\n\t\t\tsurvivors.push(m.mutantId);\n\t\t\tblindSpots.push(`undetected-violation:${m.mutantId}`);\n\t\t} else {\n\t\t\texcluded[m.classification as keyof typeof excluded] += 1;\n\t\t\tif (m.classification === \"invalid-compile\" || m.classification === \"environment-failure\") {\n\t\t\t\tblindSpots.push(`uninformative-mutant:${m.mutantId}`);\n\t\t\t}\n\t\t}\n\t}\n\tif (!checksValidOnHealthy) blindSpots.push(\"check-invalid-on-healthy-candidate\");\n\tconst denominator = detected + survivors.length;\n\treturn {\n\t\tobligationId,\n\t\tdetectionRate: denominator === 0 ? \"unknown\" : detected / denominator,\n\t\tevaluated: denominator,\n\t\texcluded,\n\t\tsurvivingMutantIds: survivors.sort(lexical),\n\t\tblindSpots: blindSpots.sort(lexical),\n\t};\n}\n\n/**\n * §7.4 metamorphic relation: Pre(x,T) ⟹ R(f(x), f(T(x))). The relation must\n * be a declared required property of this program — never a universal rule.\n */\nexport interface MetamorphicRelation {\n\treadonly relationId: string;\n\treadonly description: string;\n\treadonly precondition: string;\n\treadonly requiredProperty: boolean;\n}\nexport function relationApplicable(rel: MetamorphicRelation): boolean {\n\treturn rel.requiredProperty;\n}\n\n/** §10.1 progress key: same key + no new adopted evidence = repetition. */\nexport interface ProgressKey {\n\treadonly goalScope: string;\n\treadonly candidateFamily: string;\n\treadonly errorClass: string;\n\treadonly approach: string;\n\treadonly checkMethod: string;\n\treadonly sourceFamily: string;\n}\nexport function progressKey(k: ProgressKey): string {\n\treturn [k.goalScope, k.candidateFamily, k.errorClass, k.approach, k.checkMethod, k.sourceFamily].join(\"\\u001f\");\n}\nexport function isStagnant(\n\tcurrent: ProgressKey,\n\thistory: readonly { key: string; newEvidence: boolean; resolvedObligations: number; newValidChecks: number }[],\n\tmaxRepetitions: number,\n): boolean {\n\tinteger(maxRepetitions, \"maxRepetitions\", 64);\n\tconst key = progressKey(current);\n\tlet repeats = 0;\n\tfor (const entry of history) {\n\t\tif (entry.key === key && !entry.newEvidence && entry.resolvedObligations === 0 && entry.newValidChecks === 0) {\n\t\t\trepeats += 1;\n\t\t}\n\t}\n\treturn repeats >= maxRepetitions;\n}\n\n/** §10.2 net strategy-switch score with hysteresis margin. */\nexport function netSwitchValue(estimatedLossDelta: number, cost: number, switchCost: number): number {\n\tfinite(estimatedLossDelta, \"estimatedLossDelta\");\n\tfinite(cost, \"cost\");\n\tfinite(switchCost, \"switchCost\");\n\treturn estimatedLossDelta - cost - switchCost;\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class AcpError extends Error {
|
|
2
|
+
readonly code: number;
|
|
3
|
+
constructor(code: number, message: string);
|
|
4
|
+
}
|
|
5
|
+
export interface AcpSession {
|
|
6
|
+
prompt(text: string, emit: (text: string) => void): Promise<"end_turn" | "cancelled" | "max_tokens">;
|
|
7
|
+
cancel(): Promise<void>;
|
|
8
|
+
dispose(): void;
|
|
9
|
+
}
|
|
10
|
+
export type AcpSessionFactory = (cwd: string) => Promise<AcpSession>;
|
|
11
|
+
/** Restricted ACP v1 conversation profile. Does not grant tools or launch client MCP commands. */
|
|
12
|
+
export declare class AcpAgent {
|
|
13
|
+
private initialized;
|
|
14
|
+
private closed;
|
|
15
|
+
private creating;
|
|
16
|
+
private readonly sessions;
|
|
17
|
+
private readonly createSession;
|
|
18
|
+
private readonly version;
|
|
19
|
+
private readonly notify;
|
|
20
|
+
constructor(createSession: AcpSessionFactory, version: string, notify: (message: object) => void);
|
|
21
|
+
dispatch(method: string, rawParams: unknown): Promise<object>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=acp-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-agent.d.ts","sourceRoot":"","sources":["../../../src/modes/acp/acp-agent.ts"],"names":[],"mappings":"AAGA,qBAAa,QAAS,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGxC;CACD;AAED,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,WAAW,GAAG,YAAY,CAAC,CAAC;IACrG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,IAAI,IAAI,CAAC;CAChB;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAwBrE,kGAAkG;AAClG,qBAAa,QAAQ;IACpB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAE5D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,YAAY,aAAa,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EAI/F;IAEK,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAqElE;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAU3B;CACD","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { isAbsolute } from \"node:path\";\n\nexport class AcpError extends Error {\n\treadonly code: number;\n\tconstructor(code: number, message: string) {\n\t\tsuper(message);\n\t\tthis.code = code;\n\t}\n}\n\nexport interface AcpSession {\n\tprompt(text: string, emit: (text: string) => void): Promise<\"end_turn\" | \"cancelled\" | \"max_tokens\">;\n\tcancel(): Promise<void>;\n\tdispose(): void;\n}\n\nexport type AcpSessionFactory = (cwd: string) => Promise<AcpSession>;\n\ntype SessionState = { session: AcpSession; running: boolean };\n\nfunction object(value: unknown): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new AcpError(-32602, \"Expected object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction promptText(value: unknown): string {\n\tif (!Array.isArray(value) || value.length === 0) throw new AcpError(-32602, \"Expected nonempty prompt\");\n\treturn value\n\t\t.map((item) => {\n\t\t\tconst block = object(item);\n\t\t\tif (block.type === \"text\" && typeof block.text === \"string\") return block.text;\n\t\t\tif (block.type === \"resource_link\" && typeof block.uri === \"string\" && typeof block.name === \"string\") {\n\t\t\t\t// Links are context, never permission to retrieve files or URLs.\n\t\t\t\treturn JSON.stringify({ resource_link: { name: block.name, uri: block.uri } });\n\t\t\t}\n\t\t\tthrow new AcpError(-32602, \"Unsupported prompt content\");\n\t\t})\n\t\t.join(\"\\n\");\n}\n\n/** Restricted ACP v1 conversation profile. Does not grant tools or launch client MCP commands. */\nexport class AcpAgent {\n\tprivate initialized = false;\n\tprivate closed = false;\n\tprivate creating = 0;\n\tprivate readonly sessions = new Map<string, SessionState>();\n\n\tprivate readonly createSession: AcpSessionFactory;\n\tprivate readonly version: string;\n\tprivate readonly notify: (message: object) => void;\n\tconstructor(createSession: AcpSessionFactory, version: string, notify: (message: object) => void) {\n\t\tthis.createSession = createSession;\n\t\tthis.version = version;\n\t\tthis.notify = notify;\n\t}\n\n\tasync dispatch(method: string, rawParams: unknown): Promise<object> {\n\t\tif (this.closed) throw new AcpError(-32000, \"Connection closed\");\n\t\tconst params = object(rawParams);\n\t\tif (method === \"initialize\") {\n\t\t\tif (this.initialized) throw new AcpError(-32600, \"Already initialized\");\n\t\t\tif (!Number.isSafeInteger(params.protocolVersion) || Number(params.protocolVersion) < 1) {\n\t\t\t\tthrow new AcpError(-32602, \"Invalid protocolVersion\");\n\t\t\t}\n\t\t\tthis.initialized = true;\n\t\t\treturn {\n\t\t\t\tprotocolVersion: 1,\n\t\t\t\tagentInfo: { name: \"omk\", title: \"OMK\", version: this.version },\n\t\t\t\tagentCapabilities: {\n\t\t\t\t\tloadSession: false,\n\t\t\t\t\tpromptCapabilities: { image: false, audio: false, embeddedContext: false },\n\t\t\t\t\tmcpCapabilities: { http: false, sse: false },\n\t\t\t\t\t_meta: { \"omk/profile\": \"conversation-only\", \"omk/client-mcp\": false },\n\t\t\t\t},\n\t\t\t\tauthMethods: [],\n\t\t\t};\n\t\t}\n\t\tif (!this.initialized) throw new AcpError(-32000, \"Initialize first\");\n\t\tif (method === \"session/new\") {\n\t\t\tif (typeof params.cwd !== \"string\" || !isAbsolute(params.cwd))\n\t\t\t\tthrow new AcpError(-32602, \"cwd must be absolute\");\n\t\t\tif (!Array.isArray(params.mcpServers) || params.mcpServers.length !== 0) {\n\t\t\t\tthrow new AcpError(-32602, \"This restricted profile requires an empty mcpServers list\");\n\t\t\t}\n\t\t\tif (params.additionalDirectories !== undefined) throw new AcpError(-32602, \"Additional roots unsupported\");\n\t\t\tif (this.sessions.size + this.creating >= 8) throw new AcpError(-32000, \"Session limit reached\");\n\t\t\tthis.creating++;\n\t\t\ttry {\n\t\t\t\tconst session = await this.createSession(params.cwd);\n\t\t\t\tif (this.closed) {\n\t\t\t\t\tsession.dispose();\n\t\t\t\t\tthrow new AcpError(-32000, \"Connection closed\");\n\t\t\t\t}\n\t\t\t\tconst sessionId = randomUUID();\n\t\t\t\tthis.sessions.set(sessionId, { session, running: false });\n\t\t\t\treturn { sessionId };\n\t\t\t} finally {\n\t\t\t\tthis.creating--;\n\t\t\t}\n\t\t}\n\t\tif (method !== \"session/prompt\" && method !== \"session/cancel\") throw new AcpError(-32601, \"Method not found\");\n\t\tconst state = typeof params.sessionId === \"string\" ? this.sessions.get(params.sessionId) : undefined;\n\t\tif (!state) throw new AcpError(-32602, \"Unknown session\");\n\t\tif (method === \"session/cancel\") {\n\t\t\tawait state.session.cancel();\n\t\t\treturn {};\n\t\t}\n\t\tif (state.running) throw new AcpError(-32000, \"Session busy\");\n\t\tconst text = promptText(params.prompt);\n\t\tstate.running = true;\n\t\ttry {\n\t\t\tconst stopReason = await state.session.prompt(text, (delta) =>\n\t\t\t\tthis.notify({\n\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\tmethod: \"session/update\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tsessionId: params.sessionId,\n\t\t\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text: delta } },\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn { stopReason };\n\t\t} finally {\n\t\t\tstate.running = false;\n\t\t}\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true;\n\t\tawait Promise.all(\n\t\t\t[...this.sessions.values()].map(async ({ session }) => {\n\t\t\t\tawait session.cancel();\n\t\t\t\tsession.dispose();\n\t\t\t\treturn undefined;\n\t\t\t}),\n\t\t);\n\t\tthis.sessions.clear();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
3
|
+
export class AcpError extends Error {
|
|
4
|
+
code;
|
|
5
|
+
constructor(code, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function object(value) {
|
|
11
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
12
|
+
throw new AcpError(-32602, "Expected object");
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function promptText(value) {
|
|
16
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
17
|
+
throw new AcpError(-32602, "Expected nonempty prompt");
|
|
18
|
+
return value
|
|
19
|
+
.map((item) => {
|
|
20
|
+
const block = object(item);
|
|
21
|
+
if (block.type === "text" && typeof block.text === "string")
|
|
22
|
+
return block.text;
|
|
23
|
+
if (block.type === "resource_link" && typeof block.uri === "string" && typeof block.name === "string") {
|
|
24
|
+
// Links are context, never permission to retrieve files or URLs.
|
|
25
|
+
return JSON.stringify({ resource_link: { name: block.name, uri: block.uri } });
|
|
26
|
+
}
|
|
27
|
+
throw new AcpError(-32602, "Unsupported prompt content");
|
|
28
|
+
})
|
|
29
|
+
.join("\n");
|
|
30
|
+
}
|
|
31
|
+
/** Restricted ACP v1 conversation profile. Does not grant tools or launch client MCP commands. */
|
|
32
|
+
export class AcpAgent {
|
|
33
|
+
initialized = false;
|
|
34
|
+
closed = false;
|
|
35
|
+
creating = 0;
|
|
36
|
+
sessions = new Map();
|
|
37
|
+
createSession;
|
|
38
|
+
version;
|
|
39
|
+
notify;
|
|
40
|
+
constructor(createSession, version, notify) {
|
|
41
|
+
this.createSession = createSession;
|
|
42
|
+
this.version = version;
|
|
43
|
+
this.notify = notify;
|
|
44
|
+
}
|
|
45
|
+
async dispatch(method, rawParams) {
|
|
46
|
+
if (this.closed)
|
|
47
|
+
throw new AcpError(-32000, "Connection closed");
|
|
48
|
+
const params = object(rawParams);
|
|
49
|
+
if (method === "initialize") {
|
|
50
|
+
if (this.initialized)
|
|
51
|
+
throw new AcpError(-32600, "Already initialized");
|
|
52
|
+
if (!Number.isSafeInteger(params.protocolVersion) || Number(params.protocolVersion) < 1) {
|
|
53
|
+
throw new AcpError(-32602, "Invalid protocolVersion");
|
|
54
|
+
}
|
|
55
|
+
this.initialized = true;
|
|
56
|
+
return {
|
|
57
|
+
protocolVersion: 1,
|
|
58
|
+
agentInfo: { name: "omk", title: "OMK", version: this.version },
|
|
59
|
+
agentCapabilities: {
|
|
60
|
+
loadSession: false,
|
|
61
|
+
promptCapabilities: { image: false, audio: false, embeddedContext: false },
|
|
62
|
+
mcpCapabilities: { http: false, sse: false },
|
|
63
|
+
_meta: { "omk/profile": "conversation-only", "omk/client-mcp": false },
|
|
64
|
+
},
|
|
65
|
+
authMethods: [],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (!this.initialized)
|
|
69
|
+
throw new AcpError(-32000, "Initialize first");
|
|
70
|
+
if (method === "session/new") {
|
|
71
|
+
if (typeof params.cwd !== "string" || !isAbsolute(params.cwd))
|
|
72
|
+
throw new AcpError(-32602, "cwd must be absolute");
|
|
73
|
+
if (!Array.isArray(params.mcpServers) || params.mcpServers.length !== 0) {
|
|
74
|
+
throw new AcpError(-32602, "This restricted profile requires an empty mcpServers list");
|
|
75
|
+
}
|
|
76
|
+
if (params.additionalDirectories !== undefined)
|
|
77
|
+
throw new AcpError(-32602, "Additional roots unsupported");
|
|
78
|
+
if (this.sessions.size + this.creating >= 8)
|
|
79
|
+
throw new AcpError(-32000, "Session limit reached");
|
|
80
|
+
this.creating++;
|
|
81
|
+
try {
|
|
82
|
+
const session = await this.createSession(params.cwd);
|
|
83
|
+
if (this.closed) {
|
|
84
|
+
session.dispose();
|
|
85
|
+
throw new AcpError(-32000, "Connection closed");
|
|
86
|
+
}
|
|
87
|
+
const sessionId = randomUUID();
|
|
88
|
+
this.sessions.set(sessionId, { session, running: false });
|
|
89
|
+
return { sessionId };
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
this.creating--;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (method !== "session/prompt" && method !== "session/cancel")
|
|
96
|
+
throw new AcpError(-32601, "Method not found");
|
|
97
|
+
const state = typeof params.sessionId === "string" ? this.sessions.get(params.sessionId) : undefined;
|
|
98
|
+
if (!state)
|
|
99
|
+
throw new AcpError(-32602, "Unknown session");
|
|
100
|
+
if (method === "session/cancel") {
|
|
101
|
+
await state.session.cancel();
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
if (state.running)
|
|
105
|
+
throw new AcpError(-32000, "Session busy");
|
|
106
|
+
const text = promptText(params.prompt);
|
|
107
|
+
state.running = true;
|
|
108
|
+
try {
|
|
109
|
+
const stopReason = await state.session.prompt(text, (delta) => this.notify({
|
|
110
|
+
jsonrpc: "2.0",
|
|
111
|
+
method: "session/update",
|
|
112
|
+
params: {
|
|
113
|
+
sessionId: params.sessionId,
|
|
114
|
+
update: { sessionUpdate: "agent_message_chunk", content: { type: "text", text: delta } },
|
|
115
|
+
},
|
|
116
|
+
}));
|
|
117
|
+
return { stopReason };
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
state.running = false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async close() {
|
|
124
|
+
this.closed = true;
|
|
125
|
+
await Promise.all([...this.sessions.values()].map(async ({ session }) => {
|
|
126
|
+
await session.cancel();
|
|
127
|
+
session.dispose();
|
|
128
|
+
return undefined;
|
|
129
|
+
}));
|
|
130
|
+
this.sessions.clear();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=acp-agent.js.map
|