@vauban-org/agent-sdk 1.0.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/CONTRACT.md +6401 -813
- package/dist/adapters/llm/anthropic-direct.d.ts +1 -0
- package/dist/adapters/llm/anthropic-direct.d.ts.map +1 -1
- package/dist/adapters/llm/anthropic-direct.js +43 -0
- package/dist/adapters/llm/anthropic-direct.js.map +1 -1
- package/dist/adapters/llm/cascade.d.ts.map +1 -1
- package/dist/adapters/llm/cascade.js +57 -14
- package/dist/adapters/llm/cascade.js.map +1 -1
- package/dist/adapters/llm/litellm.d.ts +2 -0
- package/dist/adapters/llm/litellm.d.ts.map +1 -1
- package/dist/adapters/llm/litellm.js +44 -0
- package/dist/adapters/llm/litellm.js.map +1 -1
- package/dist/compute/difficulty-estimator.d.ts +53 -0
- package/dist/compute/difficulty-estimator.d.ts.map +1 -0
- package/dist/compute/difficulty-estimator.js +82 -0
- package/dist/compute/difficulty-estimator.js.map +1 -0
- package/dist/compute/strategies/mixture-of-agents.d.ts +40 -0
- package/dist/compute/strategies/mixture-of-agents.d.ts.map +1 -0
- package/dist/compute/strategies/mixture-of-agents.js +110 -0
- package/dist/compute/strategies/mixture-of-agents.js.map +1 -0
- package/dist/compute/strategies/tree-of-thoughts.d.ts +48 -0
- package/dist/compute/strategies/tree-of-thoughts.d.ts.map +1 -0
- package/dist/compute/strategies/tree-of-thoughts.js +242 -0
- package/dist/compute/strategies/tree-of-thoughts.js.map +1 -0
- package/dist/compute/strategies/two-phase-orient.d.ts +72 -0
- package/dist/compute/strategies/two-phase-orient.d.ts.map +1 -0
- package/dist/compute/strategies/two-phase-orient.js +85 -0
- package/dist/compute/strategies/two-phase-orient.js.map +1 -0
- package/dist/constitution/types.d.ts +10 -10
- package/dist/container/protocol.d.ts +134 -0
- package/dist/container/protocol.d.ts.map +1 -0
- package/dist/container/protocol.js +157 -0
- package/dist/container/protocol.js.map +1 -0
- package/dist/container/runtime.d.ts +140 -0
- package/dist/container/runtime.d.ts.map +1 -0
- package/dist/container/runtime.js +256 -0
- package/dist/container/runtime.js.map +1 -0
- package/dist/events/catalogue.d.ts +46 -46
- package/dist/events/schemas/agent.completed.v1.d.ts +4 -4
- package/dist/events/schemas/agent.failed.v1.d.ts +2 -2
- package/dist/events/schemas/agent.hitl_resolved.v1.d.ts +2 -2
- package/dist/events/schemas/agent.started.v1.d.ts +2 -2
- package/dist/events/schemas/brain.skill.extracted.v1.d.ts +4 -4
- package/dist/events/schemas/cc.cost.anomaly_detected.v1.d.ts +2 -2
- package/dist/events/schemas/cc.cost.recorded.v1.d.ts +4 -4
- package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts +6 -6
- package/dist/events/schemas/citadel.sprint.closed.v1.d.ts +2 -2
- package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts +6 -6
- package/dist/events/schemas/forge.lead.qualified.v1.d.ts +2 -2
- package/dist/events/schemas/forge.outreach.sent.v1.d.ts +4 -4
- package/dist/events/schemas/incident.detected.v1.d.ts +2 -2
- package/dist/events/schemas/vauban.goal.checked.v1.d.ts +2 -2
- package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts +2 -2
- package/dist/events/schemas/vauban.tax.checked.v1.d.ts +2 -2
- package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts +6 -6
- package/dist/identity/agent-persona.d.ts +73 -0
- package/dist/identity/agent-persona.d.ts.map +1 -0
- package/dist/identity/agent-persona.js +165 -0
- package/dist/identity/agent-persona.js.map +1 -0
- package/dist/identity/persona-prompt.d.ts +25 -0
- package/dist/identity/persona-prompt.d.ts.map +1 -0
- package/dist/identity/persona-prompt.js +71 -0
- package/dist/identity/persona-prompt.js.map +1 -0
- package/dist/identity/persona-schema.d.ts +120 -0
- package/dist/identity/persona-schema.d.ts.map +1 -0
- package/dist/identity/persona-schema.js +103 -0
- package/dist/identity/persona-schema.js.map +1 -0
- package/dist/index.d.ts +37 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/loop/minimal-loop.js +293 -287
- package/dist/memory/episodic-rrf.d.ts +114 -0
- package/dist/memory/episodic-rrf.d.ts.map +1 -0
- package/dist/memory/episodic-rrf.js +148 -0
- package/dist/memory/episodic-rrf.js.map +1 -0
- package/dist/mesh/attenuation.d.ts +78 -0
- package/dist/mesh/attenuation.d.ts.map +1 -0
- package/dist/mesh/attenuation.js +141 -0
- package/dist/mesh/attenuation.js.map +1 -0
- package/dist/mesh/delegate.d.ts +96 -0
- package/dist/mesh/delegate.d.ts.map +1 -0
- package/dist/mesh/delegate.js +172 -0
- package/dist/mesh/delegate.js.map +1 -0
- package/dist/mesh/dispatcher.d.ts +119 -0
- package/dist/mesh/dispatcher.d.ts.map +1 -0
- package/dist/mesh/dispatcher.js +207 -0
- package/dist/mesh/dispatcher.js.map +1 -0
- package/dist/mesh/index.d.ts +12 -0
- package/dist/mesh/index.d.ts.map +1 -0
- package/dist/mesh/index.js +11 -0
- package/dist/mesh/index.js.map +1 -0
- package/dist/mesh/types.d.ts +30 -0
- package/dist/mesh/types.d.ts.map +1 -0
- package/dist/mesh/types.js +11 -0
- package/dist/mesh/types.js.map +1 -0
- package/dist/orchestration/ooda/skills.d.ts +104 -0
- package/dist/orchestration/ooda/skills.d.ts.map +1 -1
- package/dist/orchestration/ooda/skills.js +106 -0
- package/dist/orchestration/ooda/skills.js.map +1 -1
- package/dist/ports/bastion-action.contract.test.d.ts +11 -0
- package/dist/ports/bastion-action.contract.test.d.ts.map +1 -0
- package/dist/ports/bastion-action.contract.test.js +238 -0
- package/dist/ports/bastion-action.contract.test.js.map +1 -0
- package/dist/ports/bastion-action.d.ts +133 -0
- package/dist/ports/bastion-action.d.ts.map +1 -0
- package/dist/ports/bastion-action.js +73 -0
- package/dist/ports/bastion-action.js.map +1 -0
- package/dist/ports/brain.d.ts +31 -0
- package/dist/ports/brain.d.ts.map +1 -1
- package/dist/ports/brain.js +115 -1
- package/dist/ports/brain.js.map +1 -1
- package/dist/ports/citadel-action.contract.test.d.ts +11 -0
- package/dist/ports/citadel-action.contract.test.d.ts.map +1 -0
- package/dist/ports/citadel-action.contract.test.js +317 -0
- package/dist/ports/citadel-action.contract.test.js.map +1 -0
- package/dist/ports/citadel-action.d.ts +111 -0
- package/dist/ports/citadel-action.d.ts.map +1 -0
- package/dist/ports/citadel-action.js +62 -0
- package/dist/ports/citadel-action.js.map +1 -0
- package/dist/ports/compliance-contract.d.ts +123 -0
- package/dist/ports/compliance-contract.d.ts.map +1 -0
- package/dist/ports/compliance-contract.js +35 -0
- package/dist/ports/compliance-contract.js.map +1 -0
- package/dist/ports/db.d.ts +38 -0
- package/dist/ports/db.d.ts.map +1 -1
- package/dist/ports/db.js +88 -1
- package/dist/ports/db.js.map +1 -1
- package/dist/ports/delegation.contract.test.d.ts +9 -0
- package/dist/ports/delegation.contract.test.d.ts.map +1 -0
- package/dist/ports/delegation.contract.test.js +337 -0
- package/dist/ports/delegation.contract.test.js.map +1 -0
- package/dist/ports/delegation.d.ts +134 -0
- package/dist/ports/delegation.d.ts.map +1 -0
- package/dist/ports/delegation.js +105 -0
- package/dist/ports/delegation.js.map +1 -0
- package/dist/ports/event-bus.d.ts +29 -0
- package/dist/ports/event-bus.d.ts.map +1 -1
- package/dist/ports/event-bus.js +106 -1
- package/dist/ports/event-bus.js.map +1 -1
- package/dist/ports/federation.contract.test.d.ts +9 -0
- package/dist/ports/federation.contract.test.d.ts.map +1 -0
- package/dist/ports/federation.contract.test.js +279 -0
- package/dist/ports/federation.contract.test.js.map +1 -0
- package/dist/ports/federation.d.ts +140 -0
- package/dist/ports/federation.d.ts.map +1 -0
- package/dist/ports/federation.js +57 -0
- package/dist/ports/federation.js.map +1 -0
- package/dist/ports/index.d.ts +28 -2
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +17 -2
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/llm-provider.d.ts +37 -0
- package/dist/ports/llm-provider.d.ts.map +1 -1
- package/dist/ports/llm-provider.js +99 -1
- package/dist/ports/llm-provider.js.map +1 -1
- package/dist/ports/logger.d.ts +27 -0
- package/dist/ports/logger.d.ts.map +1 -1
- package/dist/ports/logger.js +87 -0
- package/dist/ports/logger.js.map +1 -1
- package/dist/ports/manifest-registry.contract.test.d.ts +9 -0
- package/dist/ports/manifest-registry.contract.test.d.ts.map +1 -0
- package/dist/ports/manifest-registry.contract.test.js +246 -0
- package/dist/ports/manifest-registry.contract.test.js.map +1 -0
- package/dist/ports/manifest-registry.d.ts +116 -0
- package/dist/ports/manifest-registry.d.ts.map +1 -0
- package/dist/ports/manifest-registry.js +79 -0
- package/dist/ports/manifest-registry.js.map +1 -0
- package/dist/ports/observability.contract.test.d.ts +12 -0
- package/dist/ports/observability.contract.test.d.ts.map +1 -0
- package/dist/ports/observability.contract.test.js +260 -0
- package/dist/ports/observability.contract.test.js.map +1 -0
- package/dist/ports/observability.d.ts +98 -0
- package/dist/ports/observability.d.ts.map +1 -0
- package/dist/ports/observability.js +59 -0
- package/dist/ports/observability.js.map +1 -0
- package/dist/ports/outcome.d.ts +26 -0
- package/dist/ports/outcome.d.ts.map +1 -1
- package/dist/ports/outcome.js +62 -1
- package/dist/ports/outcome.js.map +1 -1
- package/dist/ports/privacy.contract.test.d.ts +12 -0
- package/dist/ports/privacy.contract.test.d.ts.map +1 -0
- package/dist/ports/privacy.contract.test.js +325 -0
- package/dist/ports/privacy.contract.test.js.map +1 -0
- package/dist/ports/privacy.d.ts +132 -0
- package/dist/ports/privacy.d.ts.map +1 -0
- package/dist/ports/privacy.js +83 -0
- package/dist/ports/privacy.js.map +1 -0
- package/dist/ports/tenant-context.contract.test.d.ts +14 -0
- package/dist/ports/tenant-context.contract.test.d.ts.map +1 -0
- package/dist/ports/tenant-context.contract.test.js +352 -0
- package/dist/ports/tenant-context.contract.test.js.map +1 -0
- package/dist/ports/tenant-context.d.ts +103 -0
- package/dist/ports/tenant-context.d.ts.map +1 -0
- package/dist/ports/tenant-context.js +48 -0
- package/dist/ports/tenant-context.js.map +1 -0
- package/dist/ports/vauban-finance-action.contract.test.d.ts +11 -0
- package/dist/ports/vauban-finance-action.contract.test.d.ts.map +1 -0
- package/dist/ports/vauban-finance-action.contract.test.js +260 -0
- package/dist/ports/vauban-finance-action.contract.test.js.map +1 -0
- package/dist/ports/vauban-finance-action.d.ts +106 -0
- package/dist/ports/vauban-finance-action.d.ts.map +1 -0
- package/dist/ports/vauban-finance-action.js +60 -0
- package/dist/ports/vauban-finance-action.js.map +1 -0
- package/dist/ports/workflow-runtime.d.ts +204 -0
- package/dist/ports/workflow-runtime.d.ts.map +1 -0
- package/dist/ports/workflow-runtime.js +72 -0
- package/dist/ports/workflow-runtime.js.map +1 -0
- package/dist/proof/cert-verify.d.ts +80 -0
- package/dist/proof/cert-verify.d.ts.map +1 -0
- package/dist/proof/cert-verify.js +178 -0
- package/dist/proof/cert-verify.js.map +1 -0
- package/dist/replay/replay.d.ts.map +1 -1
- package/dist/replay/replay.js +5 -1
- package/dist/replay/replay.js.map +1 -1
- package/dist/retry/index.d.ts +129 -0
- package/dist/retry/index.d.ts.map +1 -0
- package/dist/retry/index.js +156 -0
- package/dist/retry/index.js.map +1 -0
- package/dist/retry/presets.d.ts +39 -0
- package/dist/retry/presets.d.ts.map +1 -0
- package/dist/retry/presets.js +69 -0
- package/dist/retry/presets.js.map +1 -0
- package/dist/skill-loop/ab-runner.d.ts +67 -0
- package/dist/skill-loop/ab-runner.d.ts.map +1 -0
- package/dist/skill-loop/ab-runner.js +160 -0
- package/dist/skill-loop/ab-runner.js.map +1 -0
- package/dist/skill-loop/adoption.d.ts +67 -0
- package/dist/skill-loop/adoption.d.ts.map +1 -0
- package/dist/skill-loop/adoption.js +126 -0
- package/dist/skill-loop/adoption.js.map +1 -0
- package/dist/skill-loop/candidate.d.ts +45 -0
- package/dist/skill-loop/candidate.d.ts.map +1 -0
- package/dist/skill-loop/candidate.js +43 -0
- package/dist/skill-loop/candidate.js.map +1 -0
- package/dist/skill-loop/evaluator.d.ts +42 -0
- package/dist/skill-loop/evaluator.d.ts.map +1 -0
- package/dist/skill-loop/evaluator.js +184 -0
- package/dist/skill-loop/evaluator.js.map +1 -0
- package/dist/skill-loop/index.d.ts +27 -0
- package/dist/skill-loop/index.d.ts.map +1 -0
- package/dist/skill-loop/index.js +27 -0
- package/dist/skill-loop/index.js.map +1 -0
- package/dist/skill-loop/reflexion-replay.d.ts +87 -0
- package/dist/skill-loop/reflexion-replay.d.ts.map +1 -0
- package/dist/skill-loop/reflexion-replay.js +110 -0
- package/dist/skill-loop/reflexion-replay.js.map +1 -0
- package/dist/skill-loop/sign-off.d.ts +88 -0
- package/dist/skill-loop/sign-off.d.ts.map +1 -0
- package/dist/skill-loop/sign-off.js +146 -0
- package/dist/skill-loop/sign-off.js.map +1 -0
- package/dist/skill-loop/value-metric.d.ts +55 -0
- package/dist/skill-loop/value-metric.d.ts.map +1 -0
- package/dist/skill-loop/value-metric.js +69 -0
- package/dist/skill-loop/value-metric.js.map +1 -0
- package/dist/skill-loop/versioning.d.ts +36 -0
- package/dist/skill-loop/versioning.d.ts.map +1 -0
- package/dist/skill-loop/versioning.js +47 -0
- package/dist/skill-loop/versioning.js.map +1 -0
- package/dist/skill-manifest/anchor.d.ts +91 -0
- package/dist/skill-manifest/anchor.d.ts.map +1 -0
- package/dist/skill-manifest/anchor.js +331 -0
- package/dist/skill-manifest/anchor.js.map +1 -0
- package/dist/skill-manifest/builder.d.ts +47 -0
- package/dist/skill-manifest/builder.d.ts.map +1 -0
- package/dist/skill-manifest/builder.js +93 -0
- package/dist/skill-manifest/builder.js.map +1 -0
- package/dist/skill-manifest/index.d.ts +13 -0
- package/dist/skill-manifest/index.d.ts.map +1 -0
- package/dist/skill-manifest/index.js +9 -0
- package/dist/skill-manifest/index.js.map +1 -0
- package/dist/skill-manifest/types.d.ts +67 -0
- package/dist/skill-manifest/types.d.ts.map +1 -0
- package/dist/skill-manifest/types.js +16 -0
- package/dist/skill-manifest/types.js.map +1 -0
- package/dist/skill-manifest/verifier.d.ts +42 -0
- package/dist/skill-manifest/verifier.d.ts.map +1 -0
- package/dist/skill-manifest/verifier.js +136 -0
- package/dist/skill-manifest/verifier.js.map +1 -0
- package/dist/skills/brain-query.d.ts +4 -4
- package/dist/skills/brain-store.d.ts +6 -6
- package/dist/skills/errors.d.ts +15 -0
- package/dist/skills/errors.d.ts.map +1 -1
- package/dist/skills/errors.js +21 -0
- package/dist/skills/errors.js.map +1 -1
- package/dist/skills/hitl-request.d.ts +2 -2
- package/dist/skills/index.d.ts +3 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +4 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/markdown/loader.d.ts +52 -0
- package/dist/skills/markdown/loader.d.ts.map +1 -0
- package/dist/skills/markdown/loader.js +93 -0
- package/dist/skills/markdown/loader.js.map +1 -0
- package/dist/skills/markdown/schema.d.ts +432 -0
- package/dist/skills/markdown/schema.d.ts.map +1 -0
- package/dist/skills/markdown/schema.js +121 -0
- package/dist/skills/markdown/schema.js.map +1 -0
- package/dist/skills/poc-md-loader/markdown-loader.d.ts +77 -0
- package/dist/skills/poc-md-loader/markdown-loader.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/markdown-loader.js +125 -0
- package/dist/skills/poc-md-loader/markdown-loader.js.map +1 -0
- package/dist/skills/poc-md-loader/runner.d.ts +24 -0
- package/dist/skills/poc-md-loader/runner.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/runner.js +57 -0
- package/dist/skills/poc-md-loader/runner.js.map +1 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.d.ts +3 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.js +13 -0
- package/dist/skills/poc-md-loader/vitest.poc.config.js.map +1 -0
- package/dist/skills/poc-md-loader/web-search/script.d.ts +33 -0
- package/dist/skills/poc-md-loader/web-search/script.d.ts.map +1 -0
- package/dist/skills/poc-md-loader/web-search/script.js +75 -0
- package/dist/skills/poc-md-loader/web-search/script.js.map +1 -0
- package/dist/skills/record-outcome.d.ts +4 -4
- package/dist/skills/send-email.d.ts.map +1 -1
- package/dist/skills/send-email.js +15 -3
- package/dist/skills/send-email.js.map +1 -1
- package/dist/skills/slack-notify.d.ts +4 -4
- package/dist/skills/starknet-balance.d.ts +1 -1
- package/dist/skills/telegram-notify.d.ts +4 -4
- package/dist/skills/web-search.d.ts +1 -1
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/test-brain-port.d.ts +4 -0
- package/dist/testing/test-brain-port.d.ts.map +1 -1
- package/dist/testing/test-brain-port.js +75 -20
- package/dist/testing/test-brain-port.js.map +1 -1
- package/dist/testing/test-event-bus.d.ts.map +1 -1
- package/dist/testing/test-event-bus.js +89 -36
- package/dist/testing/test-event-bus.js.map +1 -1
- package/dist/trace/schema.d.ts +1 -1
- package/dist/trace/schema.d.ts.map +1 -1
- package/dist/trace/schema.js +1 -1
- package/dist/trace/schema.js.map +1 -1
- package/dist/verify/formal/index.d.ts +44 -0
- package/dist/verify/formal/index.d.ts.map +1 -0
- package/dist/verify/formal/index.js +98 -0
- package/dist/verify/formal/index.js.map +1 -0
- package/dist/verify/formal/policy.d.ts +105 -0
- package/dist/verify/formal/policy.d.ts.map +1 -0
- package/dist/verify/formal/policy.js +159 -0
- package/dist/verify/formal/policy.js.map +1 -0
- package/dist/verify/formal/result.d.ts +50 -0
- package/dist/verify/formal/result.d.ts.map +1 -0
- package/dist/verify/formal/result.js +21 -0
- package/dist/verify/formal/result.js.map +1 -0
- package/dist/verify/formal/solver.d.ts +67 -0
- package/dist/verify/formal/solver.d.ts.map +1 -0
- package/dist/verify/formal/solver.js +184 -0
- package/dist/verify/formal/solver.js.map +1 -0
- package/dist/verify/formal/spec-language.d.ts +80 -0
- package/dist/verify/formal/spec-language.d.ts.map +1 -0
- package/dist/verify/formal/spec-language.js +219 -0
- package/dist/verify/formal/spec-language.js.map +1 -0
- package/docs/attestation.md +199 -0
- package/docs/identity.md +193 -0
- package/package.json +34 -17
- package/src/adapters/llm/anthropic-direct.ts +51 -0
- package/src/adapters/llm/cascade.ts +64 -19
- package/src/adapters/llm/litellm.ts +49 -0
- package/src/compute/difficulty-estimator.ts +111 -0
- package/src/compute/strategies/mixture-of-agents.ts +150 -0
- package/src/compute/strategies/tree-of-thoughts.ts +293 -0
- package/src/compute/strategies/two-phase-orient.ts +147 -0
- package/src/container/protocol.ts +243 -0
- package/src/container/runtime.ts +424 -0
- package/src/db/migrations/026_formal_verify_results.sql +30 -0
- package/src/identity/agent-persona.ts +203 -0
- package/src/identity/persona-prompt.ts +84 -0
- package/src/identity/persona-schema.ts +127 -0
- package/src/index.ts +338 -1
- package/src/memory/episodic-rrf.ts +224 -0
- package/src/mesh/attenuation.ts +190 -0
- package/src/mesh/delegate.ts +254 -0
- package/src/mesh/dispatcher.ts +301 -0
- package/src/mesh/index.ts +39 -0
- package/src/mesh/types.ts +31 -0
- package/src/orchestration/ooda/skills.ts +177 -0
- package/src/ports/bastion-action.contract.test.ts +355 -0
- package/src/ports/bastion-action.ts +198 -0
- package/src/ports/brain.ts +177 -15
- package/src/ports/citadel-action.contract.test.ts +430 -0
- package/src/ports/citadel-action.ts +174 -0
- package/src/ports/compliance-contract.ts +191 -0
- package/src/ports/db.ts +98 -0
- package/src/ports/delegation.contract.test.ts +428 -0
- package/src/ports/delegation.ts +211 -0
- package/src/ports/event-bus.ts +133 -0
- package/src/ports/federation.contract.test.ts +355 -0
- package/src/ports/federation.ts +190 -0
- package/src/ports/index.ts +186 -1
- package/src/ports/llm-provider.ts +123 -0
- package/src/ports/logger.ts +104 -0
- package/src/ports/manifest-registry.contract.test.ts +324 -0
- package/src/ports/manifest-registry.ts +188 -0
- package/src/ports/observability.contract.test.ts +315 -0
- package/src/ports/observability.ts +150 -0
- package/src/ports/outcome.ts +69 -0
- package/src/ports/privacy.contract.test.ts +413 -0
- package/src/ports/privacy.ts +207 -0
- package/src/ports/tenant-context.contract.test.ts +454 -0
- package/src/ports/tenant-context.ts +150 -0
- package/src/ports/vauban-finance-action.contract.test.ts +335 -0
- package/src/ports/vauban-finance-action.ts +166 -0
- package/src/ports/workflow-runtime.ts +327 -0
- package/src/proof/cert-verify.ts +249 -0
- package/src/replay/replay.ts +11 -8
- package/src/retry/index.ts +227 -0
- package/src/retry/presets.ts +75 -0
- package/src/skill-loop/ab-runner.ts +196 -0
- package/src/skill-loop/adoption.ts +188 -0
- package/src/skill-loop/candidate.ts +75 -0
- package/src/skill-loop/evaluator.ts +238 -0
- package/src/skill-loop/index.ts +51 -0
- package/src/skill-loop/reflexion-replay.ts +173 -0
- package/src/skill-loop/sign-off.ts +247 -0
- package/src/skill-loop/value-metric.ts +120 -0
- package/src/skill-loop/versioning.ts +75 -0
- package/src/skill-manifest/anchor.ts +401 -0
- package/src/skill-manifest/builder.ts +129 -0
- package/src/skill-manifest/index.ts +18 -0
- package/src/skill-manifest/types.ts +72 -0
- package/src/skill-manifest/verifier.ts +198 -0
- package/src/skills/errors.ts +30 -2
- package/src/skills/index.ts +19 -0
- package/src/skills/markdown/loader.ts +129 -0
- package/src/skills/markdown/schema.ts +144 -0
- package/src/skills/poc-md-loader/e2e-parity.test.ts +237 -0
- package/src/skills/poc-md-loader/markdown-loader.ts +161 -0
- package/src/skills/poc-md-loader/runner.ts +82 -0
- package/src/skills/poc-md-loader/vitest.poc.config.ts +13 -0
- package/src/skills/poc-md-loader/web-search/SKILL.md +42 -0
- package/src/skills/poc-md-loader/web-search/script.ts +109 -0
- package/src/skills/send-email.ts +15 -3
- package/src/testing/test-brain-port.ts +98 -24
- package/src/testing/test-event-bus.ts +104 -43
- package/src/trace/schema.ts +1 -1
- package/src/verify/formal/index.ts +154 -0
- package/src/verify/formal/policy.ts +253 -0
- package/src/verify/formal/result.ts +52 -0
- package/src/verify/formal/solver.ts +235 -0
- package/src/verify/formal/spec-language.ts +274 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/skill-loop/sign-off.ts
|
|
3
|
+
*
|
|
4
|
+
* Article 14 human oversight mechanism for skill promotion.
|
|
5
|
+
*
|
|
6
|
+
* Invariants:
|
|
7
|
+
* - Audit trail: { approver_id, timestamp, decision, rationale, signed_hash }
|
|
8
|
+
* - signed_hash = SHA-256(candidateId + decision + rationale + isoTimestamp)
|
|
9
|
+
* - Escalation: approver unavailable >72h → auto-REJECTED (never auto-approved)
|
|
10
|
+
* - Multiple approvers possible; one sign-off is sufficient for promotion.
|
|
11
|
+
*
|
|
12
|
+
* @module skill-loop/sign-off
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { createHash } from "node:crypto";
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Types
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
export type SignOffDecision = "approved" | "rejected";
|
|
22
|
+
|
|
23
|
+
export interface SignOffRecord {
|
|
24
|
+
/** Candidate ID this sign-off covers. */
|
|
25
|
+
candidateId: string;
|
|
26
|
+
/** Identifier of the human approver (e.g. user UUID or username). */
|
|
27
|
+
approverId: string;
|
|
28
|
+
/** ISO-8601 timestamp at which the decision was recorded. */
|
|
29
|
+
timestamp: string;
|
|
30
|
+
/** Human decision. */
|
|
31
|
+
decision: SignOffDecision;
|
|
32
|
+
/** Human-provided rationale (non-empty required). */
|
|
33
|
+
rationale: string;
|
|
34
|
+
/**
|
|
35
|
+
* Integrity hash: SHA-256(candidateId + decision + rationale + timestamp).
|
|
36
|
+
* Detects tampering in the audit trail.
|
|
37
|
+
*/
|
|
38
|
+
signedHash: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface PendingRequest {
|
|
42
|
+
candidateId: string;
|
|
43
|
+
requestedAt: string;
|
|
44
|
+
/** Approver ID if a specific approver is designated. Null = any approver. */
|
|
45
|
+
approverId: string | null;
|
|
46
|
+
/** Deadline beyond which the request is auto-rejected (72h from requestedAt). */
|
|
47
|
+
deadlineAt: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Internal helpers
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
function sha256Hex(input: string): string {
|
|
55
|
+
return createHash("sha256").update(input, "utf8").digest("hex");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isoNow(overrideDate?: Date): string {
|
|
59
|
+
return (overrideDate ?? new Date()).toISOString();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Compute the signed hash per the canonical formula. */
|
|
63
|
+
function computeSignedHash(
|
|
64
|
+
candidateId: string,
|
|
65
|
+
decision: SignOffDecision,
|
|
66
|
+
rationale: string,
|
|
67
|
+
timestamp: string
|
|
68
|
+
): string {
|
|
69
|
+
return sha256Hex(`${candidateId}${decision}${rationale}${timestamp}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// SignOffManager
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Manages pending approval requests and sign-off records.
|
|
78
|
+
*
|
|
79
|
+
* In production, records should be persisted to the DB. This implementation
|
|
80
|
+
* is in-memory and suitable for tests and single-process environments.
|
|
81
|
+
*/
|
|
82
|
+
export class SignOffManager {
|
|
83
|
+
private readonly records = new Map<string, SignOffRecord[]>();
|
|
84
|
+
private readonly pending = new Map<string, PendingRequest>();
|
|
85
|
+
|
|
86
|
+
/** 72-hour escalation deadline in milliseconds. */
|
|
87
|
+
static readonly ESCALATION_DEADLINE_MS = 72 * 60 * 60 * 1_000;
|
|
88
|
+
|
|
89
|
+
// ── Request ─────────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create a pending approval request for a candidate.
|
|
93
|
+
*
|
|
94
|
+
* If a request already exists and is not expired, returns the existing one.
|
|
95
|
+
*/
|
|
96
|
+
requestSignOff(
|
|
97
|
+
candidateId: string,
|
|
98
|
+
approverId: string | null = null,
|
|
99
|
+
nowDate?: Date
|
|
100
|
+
): PendingRequest {
|
|
101
|
+
const existing = this.pending.get(candidateId);
|
|
102
|
+
if (existing && !this.isExpired(existing, nowDate)) {
|
|
103
|
+
return existing;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const requestedAt = isoNow(nowDate);
|
|
107
|
+
const deadline = new Date(
|
|
108
|
+
(nowDate ?? new Date()).getTime() + SignOffManager.ESCALATION_DEADLINE_MS
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const request: PendingRequest = {
|
|
112
|
+
candidateId,
|
|
113
|
+
requestedAt,
|
|
114
|
+
approverId,
|
|
115
|
+
deadlineAt: deadline.toISOString(),
|
|
116
|
+
};
|
|
117
|
+
this.pending.set(candidateId, request);
|
|
118
|
+
return request;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ── Approve / Reject ────────────────────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Record a sign-off decision (approved or rejected).
|
|
125
|
+
*
|
|
126
|
+
* @throws If rationale is empty or candidateId is missing.
|
|
127
|
+
*/
|
|
128
|
+
recordDecision(
|
|
129
|
+
candidateId: string,
|
|
130
|
+
approverId: string,
|
|
131
|
+
decision: SignOffDecision,
|
|
132
|
+
rationale: string,
|
|
133
|
+
nowDate?: Date
|
|
134
|
+
): SignOffRecord {
|
|
135
|
+
if (!rationale || rationale.trim().length === 0) {
|
|
136
|
+
throw new Error(
|
|
137
|
+
`sign-off: rationale is required for decision "${decision}" on candidate "${candidateId}"`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const timestamp = isoNow(nowDate);
|
|
142
|
+
const signedHash = computeSignedHash(
|
|
143
|
+
candidateId,
|
|
144
|
+
decision,
|
|
145
|
+
rationale,
|
|
146
|
+
timestamp
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const record: SignOffRecord = {
|
|
150
|
+
candidateId,
|
|
151
|
+
approverId,
|
|
152
|
+
timestamp,
|
|
153
|
+
decision,
|
|
154
|
+
rationale,
|
|
155
|
+
signedHash,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const existing = this.records.get(candidateId) ?? [];
|
|
159
|
+
existing.push(record);
|
|
160
|
+
this.records.set(candidateId, existing);
|
|
161
|
+
|
|
162
|
+
// Remove the pending request once a decision is recorded.
|
|
163
|
+
this.pending.delete(candidateId);
|
|
164
|
+
|
|
165
|
+
return record;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ── Escalation ──────────────────────────────────────────────────────────────
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Check all pending requests and auto-reject any that have exceeded the 72h deadline.
|
|
172
|
+
*
|
|
173
|
+
* @returns Array of auto-rejection records created.
|
|
174
|
+
*/
|
|
175
|
+
escalateExpired(nowDate?: Date): SignOffRecord[] {
|
|
176
|
+
const rejections: SignOffRecord[] = [];
|
|
177
|
+
|
|
178
|
+
for (const [candidateId, request] of this.pending.entries()) {
|
|
179
|
+
if (this.isExpired(request, nowDate)) {
|
|
180
|
+
const record = this.recordDecision(
|
|
181
|
+
candidateId,
|
|
182
|
+
"system:escalation",
|
|
183
|
+
"rejected",
|
|
184
|
+
"Auto-rejected: approver unavailable >72h (Art. 14 escalation — never auto-approved)",
|
|
185
|
+
nowDate
|
|
186
|
+
);
|
|
187
|
+
rejections.push(record);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return rejections;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ── Queries ─────────────────────────────────────────────────────────────────
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Returns the first approved sign-off for a candidate, or null if none exists.
|
|
198
|
+
* One sign-off is sufficient for promotion.
|
|
199
|
+
*/
|
|
200
|
+
getApproval(candidateId: string): SignOffRecord | null {
|
|
201
|
+
const records = this.records.get(candidateId) ?? [];
|
|
202
|
+
return (
|
|
203
|
+
records.find(
|
|
204
|
+
(r) => r.decision === "approved" && r.approverId !== "system:escalation"
|
|
205
|
+
) ?? null
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Returns all sign-off records for a candidate (audit trail).
|
|
211
|
+
*/
|
|
212
|
+
getAuditTrail(candidateId: string): SignOffRecord[] {
|
|
213
|
+
return this.records.get(candidateId) ?? [];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Returns true if a pending request exists and has not expired.
|
|
218
|
+
*/
|
|
219
|
+
hasPending(candidateId: string, nowDate?: Date): boolean {
|
|
220
|
+
const request = this.pending.get(candidateId);
|
|
221
|
+
if (!request) return false;
|
|
222
|
+
return !this.isExpired(request, nowDate);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ── Verification ────────────────────────────────────────────────────────────
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Verify the integrity of a sign-off record by recomputing its hash.
|
|
229
|
+
*/
|
|
230
|
+
verifyRecord(record: SignOffRecord): boolean {
|
|
231
|
+
const expected = computeSignedHash(
|
|
232
|
+
record.candidateId,
|
|
233
|
+
record.decision,
|
|
234
|
+
record.rationale,
|
|
235
|
+
record.timestamp
|
|
236
|
+
);
|
|
237
|
+
return expected === record.signedHash;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ── Private ─────────────────────────────────────────────────────────────────
|
|
241
|
+
|
|
242
|
+
private isExpired(request: PendingRequest, nowDate?: Date): boolean {
|
|
243
|
+
const deadline = new Date(request.deadlineAt).getTime();
|
|
244
|
+
const now = (nowDate ?? new Date()).getTime();
|
|
245
|
+
return now > deadline;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/skill-loop/value-metric.ts
|
|
3
|
+
*
|
|
4
|
+
* skill_value formula: cumulative weekly metric.
|
|
5
|
+
*
|
|
6
|
+
* skill_value = Σ(usage_count × outcome_delta_vs_baseline)
|
|
7
|
+
*
|
|
8
|
+
* Consumer provides an outcomeDeltaCalculator function that returns the
|
|
9
|
+
* outcome delta for a given usage event. The metric is cumulative over a
|
|
10
|
+
* sliding 7-day window.
|
|
11
|
+
*
|
|
12
|
+
* @module skill-loop/value-metric
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Types
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
export interface UsageEvent {
|
|
20
|
+
/** Skill ID this event belongs to. */
|
|
21
|
+
skillId: string;
|
|
22
|
+
/** ISO-8601 timestamp of the usage event. */
|
|
23
|
+
timestamp: string;
|
|
24
|
+
/** Arbitrary context passed to the outcomeDeltaCalculator. */
|
|
25
|
+
context: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SkillValueResult {
|
|
29
|
+
skillId: string;
|
|
30
|
+
/** Sum of (usage × outcome_delta) over the window. */
|
|
31
|
+
skillValue: number;
|
|
32
|
+
/** Number of usage events included. */
|
|
33
|
+
usageCount: number;
|
|
34
|
+
/** Sum of all individual outcome deltas (raw). */
|
|
35
|
+
totalOutcomeDelta: number;
|
|
36
|
+
/** Start of the 7-day window (ISO-8601). */
|
|
37
|
+
windowStart: string;
|
|
38
|
+
/** End of the 7-day window (ISO-8601). */
|
|
39
|
+
windowEnd: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// 7-day sliding window constant
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
const WEEK_MS = 7 * 24 * 60 * 60 * 1_000;
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// computeSkillValue
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Compute skill_value = Σ(usage × outcome_delta_vs_baseline).
|
|
54
|
+
*
|
|
55
|
+
* Each usage event is weighted by the outcome delta it produced vs the
|
|
56
|
+
* baseline skill. Events outside the 7-day window are excluded.
|
|
57
|
+
*
|
|
58
|
+
* @param skillId - The skill being measured.
|
|
59
|
+
* @param usageEvents - All usage events for this skill.
|
|
60
|
+
* @param outcomeDeltaCalculator - Consumer-provided function: event → delta.
|
|
61
|
+
* @param nowDate - Optional override for "now" (deterministic tests).
|
|
62
|
+
*/
|
|
63
|
+
export function computeSkillValue(
|
|
64
|
+
skillId: string,
|
|
65
|
+
usageEvents: UsageEvent[],
|
|
66
|
+
outcomeDeltaCalculator: (event: UsageEvent) => number,
|
|
67
|
+
nowDate?: Date
|
|
68
|
+
): SkillValueResult {
|
|
69
|
+
const now = nowDate ?? new Date();
|
|
70
|
+
const windowEnd = now.toISOString();
|
|
71
|
+
const windowStart = new Date(now.getTime() - WEEK_MS).toISOString();
|
|
72
|
+
|
|
73
|
+
// Filter to events within the 7-day window
|
|
74
|
+
const windowEvents = usageEvents.filter((e) => {
|
|
75
|
+
const ts = e.timestamp;
|
|
76
|
+
return ts >= windowStart && ts <= windowEnd;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// skill_value = Σ(usage × outcome_delta)
|
|
80
|
+
// Each event counts as 1 usage unit.
|
|
81
|
+
let skillValue = 0;
|
|
82
|
+
let totalOutcomeDelta = 0;
|
|
83
|
+
|
|
84
|
+
for (const event of windowEvents) {
|
|
85
|
+
const delta = outcomeDeltaCalculator(event);
|
|
86
|
+
skillValue += 1 * delta; // usage_count per event = 1
|
|
87
|
+
totalOutcomeDelta += delta;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
skillId,
|
|
92
|
+
skillValue,
|
|
93
|
+
usageCount: windowEvents.length,
|
|
94
|
+
totalOutcomeDelta,
|
|
95
|
+
windowStart,
|
|
96
|
+
windowEnd,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// computeAggregateSkillValue (multi-skill comparison helper)
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Compute skill_value for multiple skills and rank them descending.
|
|
106
|
+
*/
|
|
107
|
+
export function rankSkillsByValue(
|
|
108
|
+
skills: Array<{
|
|
109
|
+
skillId: string;
|
|
110
|
+
usageEvents: UsageEvent[];
|
|
111
|
+
outcomeDeltaCalculator: (event: UsageEvent) => number;
|
|
112
|
+
}>,
|
|
113
|
+
nowDate?: Date
|
|
114
|
+
): SkillValueResult[] {
|
|
115
|
+
const results = skills.map(
|
|
116
|
+
({ skillId, usageEvents, outcomeDeltaCalculator }) =>
|
|
117
|
+
computeSkillValue(skillId, usageEvents, outcomeDeltaCalculator, nowDate)
|
|
118
|
+
);
|
|
119
|
+
return results.sort((a, b) => b.skillValue - a.skillValue);
|
|
120
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/skill-loop/versioning.ts
|
|
3
|
+
*
|
|
4
|
+
* Skill version management — semver bumping and version record type.
|
|
5
|
+
*
|
|
6
|
+
* Bump rules:
|
|
7
|
+
* - reflexion / ab_winner → minor bump (1.0.0 → 1.1.0)
|
|
8
|
+
* - manual → major bump (1.0.0 → 2.0.0)
|
|
9
|
+
* - initial → no-op (returns "1.0.0" baseline)
|
|
10
|
+
*
|
|
11
|
+
* @module skill-loop/versioning
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Types
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export interface SkillVersion {
|
|
19
|
+
skillId: string;
|
|
20
|
+
/** Semver string: "1.0.0", "1.1.0", etc. */
|
|
21
|
+
version: string;
|
|
22
|
+
parentSkillId: string | null;
|
|
23
|
+
mutationType: "initial" | "reflexion" | "ab_winner" | "manual";
|
|
24
|
+
/** SHA-256 of the source cycle trace. */
|
|
25
|
+
replayRoot: string;
|
|
26
|
+
createdAt: Date;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Version bumping
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Bump a semver string according to mutation type.
|
|
35
|
+
*
|
|
36
|
+
* - initial → returns "1.0.0" (baseline, not a bump)
|
|
37
|
+
* - reflexion → minor bump
|
|
38
|
+
* - ab_winner → minor bump
|
|
39
|
+
* - manual → major bump
|
|
40
|
+
*
|
|
41
|
+
* @param current - Current semver string e.g. "1.2.3".
|
|
42
|
+
* @param mutationType - The kind of mutation that produced the new version.
|
|
43
|
+
* @returns New semver string.
|
|
44
|
+
*/
|
|
45
|
+
export function bumpVersion(
|
|
46
|
+
current: string,
|
|
47
|
+
mutationType: SkillVersion["mutationType"]
|
|
48
|
+
): string {
|
|
49
|
+
if (mutationType === "initial") {
|
|
50
|
+
return "1.0.0";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const parts = current.split(".");
|
|
54
|
+
if (parts.length !== 3) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`bumpVersion: invalid semver "${current}" — expected "MAJOR.MINOR.PATCH"`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const major = parseInt(parts[0], 10);
|
|
61
|
+
const minor = parseInt(parts[1], 10);
|
|
62
|
+
|
|
63
|
+
if (isNaN(major) || isNaN(minor)) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`bumpVersion: non-numeric semver components in "${current}"`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (mutationType === "manual") {
|
|
70
|
+
return `${major + 1}.0.0`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// reflexion | ab_winner → minor bump
|
|
74
|
+
return `${major}.${minor + 1}.0`;
|
|
75
|
+
}
|