vassiliylakhonin/agenda-intelligence
Deterministic evidence-packet linter for claim-backed AI output, with compatibility agenda-analysis skills and MCP tools. Reports packet completeness, not factual truth.
CHANGELOG
Unreleased
1.24.0 — 2026-10-30
-
Expose a nonbinding escrow delivery-review block with independent hash/schema grades, unverified timestamps and SLO, and unverified attestation references. Support flat and legacy MCP inputs, provide a local hold-oriented client and a separately labeled hypothetical policy calculator; no payout is authorized.
-
Add multi-gate corridor orientation, a local incomplete handoff and a dated HS snapshot hint. Add a conservative dual-use reference-readiness view and Financial Guard pre-sign reason codes with a fail-closed integration example. These are evidence-review aids and never grant export or signing authority.
-
Add an optional Kazakhstan entry-model intake, grouped owner plan, scope-checked progress view and locally copyable committee memo. Add an offline agent projection helper and a labeled synthetic follow-up; none changes the gate decision or verifies evidence.
-
Add a Gulf voyage intake, explicit IMO/MMSI fields and pre-fixture reason codes for unknown cover, missing ownership, STS history, sanctions and identity. Block metadata readiness on those gaps, keep human review mandatory, and show AIS quality as unassessed. Add a labeled synthetic follow-up and maritime playbook prompts; document references do not establish authenticity or clearance.
-
Add CIS counterparty intake, local CSV/JSON batch preparation and fail-safe per-item summaries. Surface reported screening/enrichment status and a requested-scope matrix that explicitly does not assess legal applicability; keep source and trial contracts unchanged.
-
Add a Middle Corridor deal-file preparation wizard, stage-ordered suggested document owners, manual links to adjacent reviews, a pre-signature handoff example and a placeholder-resistant synthetic follow-up. Flag declared dual-use goods and electronics as review leads without implying classification or bank approval.
-
Add a minimal-input Interaction Trust client, fail-closed handoff and explicit three-stage review integration. Show a no-quota synthetic placeholder demo and clarify that the gate cannot grant action authorization.
-
Let hosted citation review check raw answers without source excerpts, with explicit unresolved references, a concise route and first step. Add an answer-first web form, a no-quota synthetic demo, an opt-in literal numeric smoke check, and a fail-closed trial client for agent handoffs; truth and semantic support remain unassessed.
-
Add an unassessed-evidence orientation and suggested gate to free-text strategic triage, with fail-closed
insufficientrouting. Include a local synthetic walkthrough and human-review integration recipe; existing detailed fields remain available. -
When an Output Verification trial allowance is exhausted, point browser and first-check MCP clients to the separate local answer/source adapter, without implying identical contracts or another hosted allowance.
-
Make the existing A2A free-trial status and evaluation examples directly discoverable in the trial extension, retaining the legacy metadata and existing quotas. Point Output Verification's agent card to a task-focused MCP/A2A quickstart and clarify the structural review boundary.
1.23.0 — 2026-10-28
- Add the local
review-revisioncommand with readable before/after claims, evidence-version changes, stable finding comparison and explicit human handoffs. Surface deleted claims and replaced sources; refuse ambiguous duplicate IDs and preserve both input files. No rewriting, network calls or action authority. - Prevent unchanged completed Output web and MCP Apps reviews from consuming another attempt in the same open form. Suppress concurrent submissions, compare edits with the submitted version, disclose changed sources and retain prior results on failed reruns. Hosted admission, other profiles and quotas are unchanged.
1.22.0 — 2026-10-28
- Add
worker-remediation.v1to all twelve primary evaluations: exact input paths and source keys, rejection reasons, blank repair templates, requirement authority and independent human checks. Preserve all existing scores/verdicts and mandatory review; service checklists are not laws. - Reject unknown closed-object fields before fallback, evaluation and attempt/payment reservation. Preserve explicit compatibility wrappers and supported metadata; close the optional text-routing input per ADR 0043.
- Disclose unavailable Financial Guard sanctions/AML and wallet-history checks, Escrow SLO limits, exact CM source keys and campaign reset semantics in discovery and trial terms. Distinguish technical failures from evidence omissions.
- Add public schema/example aliases under
/.well-known/while retaining original routes; correct static serving URLs and execute every published primary example locally. Keep the persistent legacy extension identifier. - Add a local report-with-sources → OV → caller revision adapter and synthetic before/after case that catches a quote mismatch and missing reference without deleting claims or claiming factual verification. No hosted calls, payments, new workers or cloud resources are introduced.
Research numeric and coverage checks — 2026-10-28
- Add artifact 1.1 and hosted research protocol 0.2.0 with explicit quality status, retained/withheld findings, measurement records, deterministic percentage calculations and per-part question coverage. Stored 1.0 artifacts remain valid.
- Bind quantities to source-owned values, units, annual periods and scope; withhold ambiguous table bindings, wrong scales/years, capacity-as-flow and unbound numeric prose. Keep completion separate from analytical acceptance and retain mandatory human review.
- Add route/project/indicator regressions, a replay of the actual failed live draft, and full-execution checks for retained and blocked results. Keep resources, quotas, one-call execution and core package/profile behavior unchanged.
Self-contained document deployment — 2026-10-28
- Prebundle the existing DOCX extractor dependencies, matching the PDF parser. The clean deployment job needs no project npm installation; native Workflow checks treat package imports as external to detect accidental runtime dependency leaks.
Operator documents for bounded research — 2026-10-28
- Select up to four sources from seven official providers, adding KTZ Express, Aktau and Kuryk operator material. Read bounded PDF pages and DOCX body text with existing parsers; preserve partial extraction and access failures.
- Keep original-byte hashes, UTC publication dates, observation periods and project phases distinct. Surface numeric-token/stage review notes and extraction warnings in the brief without changing the public v1 schema or certifying factual truth.
- Add three reviewer-authored demonstrations and exercise real local Workflow/D1 with PDF/DOCX fixtures, including the real 125-page Aktau PDF as an additional local check. Keep quotas, cloud resources, payment and other profile behavior unchanged.
Research evidence selection — 2026-10-27
- Build a bounded source-fragment ledger before synthesis. The model selects known fragment IDs in a source-keyed map; the server attaches unchanged quotations and enforces source ownership, one finding per selected source and existing quotation limits. Public findings retain their original contract.
- Preserve finite validation codes across Workflow RPC error serialization. Add real-engine coverage of evidence selection and rejected references without repeating inference.
Research output language — 2026-10-27
- Repeat the requested output language at the final model contract and in structured input. Reject fully English narrative fields when Russian was requested; keep exact source quotations in their original language. Localize Russian Markdown section labels.
- Exercise English and Russian jobs in the real local Workflow smoke, with one fixture inference per job. The first completed live response had a Russian metadata label but English narrative; it is recorded as a failed language acceptance case.
Server research runtime corrections — 2026-10-27
- Supply the required Workflow retry delay even with zero retries; a real engine smoke now covers the deployed entry, local D1, private polling and one fixture inference. The first live attempt failed before any model dispatch because its step configuration was rejected.
- Advertise canonical MCP at
/v1/research/mcpunder the existing machine API exception, retaining the earlier application alias. Ordinary urllib access to the initial/mcp/researchroute was blocked by BIC. - Publish research discovery through a standard A2A capability extension and sign the final augmented card; check the actual served schema and signature in the runtime smoke.
Bounded server research — 2026-10-27
- Implement a separate Middle Corridor/Caspian research interface: collect bounded official HTML sources, run one server-side Workers AI synthesis, check source IDs and verbatim quotations, and retain private job artifacts and source provenance. Preserve unknown publication/observation dates, access failures, interpretations and mandatory human review.
- Add restartable Workflow execution, atomic D1 admission limits, caller-owned privacy capabilities and idempotency, a browser entry point and two stateless MCP tools. Journal inference before dispatch to prevent automatic repeat spending after an ambiguous provider outcome.
- The owner approved one dedicated D1 database, one Workflow and bounded Workers AI usage. Configure the real database and reuse the existing Vizier-gated workflow with a root-only target for activation. Existing profile MCP tools, evidence checks, payment and authorization contracts are unchanged.
First-check integration path — 2026-10-27
- Publish a standalone Node client, canonical downloadable source and task/discovery links for connection inspection, exact raw trial examples, schema preflight, one explicitly chosen evaluation and optional completion-bound usefulness feedback. No SDK installation is required; invalid JSON stops locally and disabled/exhausted trials never fall back to a paid call.
- Preserve prepared input snapshots, stop a second submission after an uncertain response, retain printed results on file-save failure and keep feedback explicit. Test the actual offline handlers across twelve profiles, including different paid/trial wrappers. Existing protocols, authentication, payment, quotas and result contracts remain intact; owner tests do not establish external adoption or usefulness.
Archive follow-through — 2026-10-26
- Add explicit device draft save/load/remove with checked original bytes, committed-transaction acknowledgments, unsaved-change warnings and stale-tab protection. Keep one working copy separate from portable archive v1 backups and supplier dossiers; storage errors retain working data.
- Add editable company, supplier and reporting starters with no supplied evidence or automatic adequacy claims. Publish a bounded archive handover test offer and synthetic sample, with written scope, availability, final price/date and acceptance confirmed before payment.
- Collect voluntary finite self-reports in a separate same-origin form while preserving the workspace's no-network CSP. Distinguish example/own-file contexts and owner checks; accepted feedback does not prove a download, reviewer acceptance, customer identity or revenue. API tariffs and admission remain unchanged.
Document archive review and A2A response stages — 2026-10-26
- Add a free browser-local archive workspace with an explicit checklist, owners, checked original bytes, exact duplicates and same-name/different-content warnings. Count distinct nonempty contents toward user-defined requirements; export a source-linked review, CSV register, checked JSON backup and reviewer ZIP. Reuse the bounded document worker for PDF/DOCX extraction and ZIP export. Preserve working data on invalid imports or failed file batches.
- Route unstructured Agenda A2A archive-review intent to that workspace without a domain evaluation, trial reservation, task persistence or payment. Stamp known A2A setup, routing, input-required, evaluation, failed and unmeasured responses separately, with finite content-free stage telemetry. HTTP success is not evaluation, customer demand or approval. Existing schemas, admission, tariffs and limits remain intact.
First-result follow-through and supplier offer — 2026-10-25
- Add free input-format validation to trial-limit recovery, using the same raw trial fields on all ten campaign profiles. Distinguish network campaign and daily capacity, preserve the last result, reject stale preflight replies and keep retry/payment explicit. Show feedback as recorded only after acknowledgment for its completed attempt; offer an explicit revision step without submitting.
- Publish read-only
/supplier-reviewand/supplier-review/sample.md: a source-linked synthetic handover, open owner requests and an unresolved adverse update. Offer a bounded first assignment at an indicative 99 USD with written scope/price confirmation before payment. No upload, checkout, message delivery or customer outcome is created; API tariffs, quotas and human approval remain unchanged.
Smithery publisher metadata — 2026-10-24
- Align the local MCP publisher configuration with package 1.21.2, the current project homepage and deterministic supplied-evidence checks. Remove unsupported latency, retention, clearance and autonomous-arbitration claims from its description and keywords. Hosted registry descriptions and tool snapshots are maintained separately in Smithery.
Pro volume pricing — 2026-10-24
- Lower Pro to 49 USDC for 30 days and 10,000 checks: 0.0049 USDC/check at full use, 51% below ordinary 0.01 USDC checks. Derive current card, settlement, quota-response and browser prices from the same amount. Preserve quotas, expiry, funding-wallet signatures and replay protection.
- Keep the separate 49 USDC dossier activation distinct via the explicit tier. Preserve historical omitted-tier routing and existing tokens; test actual signed activation and all twelve profiles offline without moving funds.
Free-routing health expectations — 2026-10-24
- Make the configured fleet proof select a published paid operation for unpaid admission checks, including Assistant HS screening; validate explicitly free routing results when no suitable paid operation exists. Preserve production authentication and reject tool errors, absent results or action authorization even with HTTP200.
- Use the existing canonical-origin inventory and an owner client marker with urllib’s default identity. Keep tests and operator probes distinct from customer activity; no payment or trial reservation is performed.
Payment recipient discovery — 2026-10-24
- Publish optional x402 discovery in its own A2A capability extension and expose the existing Base USDC
payTo, asset, network, canonical manifest and explorer link directly in payment manifests. Retain the closed A2A root, signed card contents, exact-request payment requirements, prices and free operations. Do not advertise standard x402 when disabled or infer paid usage from discovery. Correct free-routing examples to advertise HTTP200 without payment. - Verify all twelve profiles, recipient consistency with operation quotes, disabled standard configuration and caller-supplied recipient refusal. A third-party directory still controls its own extraction and refresh; on-chain inflow is not verified service revenue.
Entry pricing — 2026-10-24
- Make Agenda and Corridor Assistant text routing free without trial or Pro consumption, retaining configured authentication and hourly limits. Set automatic checks to 0.01 USDC and Escrow evidence review to 0.05 USDC. Keep Bankability’s free preview and optional 25 USDC full export; HS-code screening remains separately paid. Align operation offers, cards, MCP guidance, web forms and current pricing documentation.
- Preserve original cached-result recovery after price changes in both payment rails. Reject new stale x402 quotes before settlement; now-free routing accepts old payment proof only for cached recovery. Keep published schemas, existing trial quotas and human-review boundaries. Offline synthetic tests do not establish real payments or demand.
Catalog setup commands — 2026-10-24
- Make the first three catalog prompts executable text-only setup commands: a saved worked example, serving-profile input requirements and configured free-trial options. Preserve structured JSON evaluation examples and retain ordinary task descriptions separately as evaluation intents. Keep skill IDs, evaluation contracts and normal admission intact.
- Return current published schemas, preflight, trial limits and explicit next steps without evaluating input, checking live allowance, consuming attempts, storing tasks or making upstream calls. Respect disabled campaigns, deployment authorization, protocol checks and payment-material refusal. Record setup views only as separate funnel steps; they do not establish useful results, users or revenue.
Catalog first use — 2026-10-23
- Publish an explicit text-only A2A saved-example command as the first catalog example on all twelve profiles. Return actual precomputed synthetic inputs, findings and saved follow-ups, with a deliberate link to the existing trial; never evaluate supplied cases, spend an attempt, charge payment or issue authorization. Preserve production authentication, protocol checks and paid admission; record only a worked-example funnel event.
- Clarify Output Verification skill names and tags around AI-report evidence quality and citation/reference consistency, preserving stable IDs and actual structural-check boundaries. Catalog taxonomy and stale enrichment require independent Agenstry reindexing; no ranking, adoption or customer claim is made.
1.21.2 — 2026-10-23
- Refresh the PyPI description with a self-contained installed-package example, current hosted first-call recovery and browser-local Supplier Evidence Desk handover. Use release-pinned absolute documentation links, distinguishing hosted workflows from installed Python APIs.
- Synchronize package, manifest, discovery, SDK, plugin, Docker and current documentation versions; regenerate synthetic fixtures. Preserve core schemas, tools, domain behavior, prices, quotas and authorization. Carry the already tested hosted improvements in the source release without claiming real users, payments or reviewer acceptance.
First-call recovery — 2026-10-23
- Expose the serving host's free input preflight and configured trial inspection in REST/A2A/MCP input/payment refusals. Preserve x402 challenges, exact paid-request recovery, authentication and quotas; never replay, pay or consume an attempt by showing guidance. Disabled trials no longer get an unconditional MCP invitation.
- Verify read-only recovery for all twelve products, production authentication, private-input exclusion and unchanged standard x402 payloads. Keep the existing real-task pilot kits; owner checks do not establish user acceptance or demand.
Supplier document handover — 2026-10-23
- Add bounded browser-local PDF/DOCX extraction with page/paragraph locators, explicit partial/OCR warnings and manual excerpt adoption. Isolate parsing/export in a terminable dedicated worker, retain no-network CSP and preserve the portable dossier v1 contract.
- Export a readable Unicode reviewer PDF with checklist gaps, requests, source hashes and the selected version comparison, plus a separate ZIP of verified current original files and a path/hash manifest. Keep full history in JSON backups.
- Show saved dossiers with expiry alerts, outstanding owner requests and direct revision comparison. Prepare a 3–5 real-assignment pilot protocol and an empty measurement register; no customer usage or savings is claimed.
Supplier Evidence Desk — 2026-10-22
- Restrict illustrative-document markers to explicit example/fixture wording so ordinary synthetic-material descriptions do not create false documentary gaps. Preserve human review and the explicit demo markers.
- Add a free browser-local supplier workspace on existing Workers: editable checklist and owners, source attachments/excerpts, manual request tracking and copyable drafts, explicitly saved versions, scoped revision comparison and portable JSON/Markdown/CSV handover. Validate imported history and attachment bytes; preserve unsaved work on storage failure. Keep document text out of network calls and telemetry. Human review remains required; no automatic supplier approval or message sending.
Snapshot machine domain — 2026-10-22
- Read the canonical snapshot directly through the CIS Static Assets binding for screening and dependency health. Avoid same-zone route fetches reaching the legacy Pages origin; retain configured-URL behavior elsewhere, cache/freshness checks and failure without a network fallback.
- Serve the compact JSON from Static Assets on the existing CIS Worker at the owned
sanctions-index.agendamcp.dpdns.orgexact path. Cloudflare traced a matching BIC Skip followed by Pages-side403; a Pages custom domain alone was insufficient. Preserve the Pages compatibility publication, existing BIC-only rules, source/canary/drift/freshness gates and separate credentials. Bind the asset SHA-256 to the signed Vizier deployment request and receipt; serialize daily refreshes with fleet deployments. Restore verified canonical bytes for ordinary releases, with an explicit short-lived pinned-watchdog-artifact bootstrap for the migration. - Verify exact published bytes using default urllib identity and no redirects. Treat HTTP 401/403 as terminal without retry or User-Agent fallback, and avoid inferring a Worker outage from a single direct-download failure.
Pages-scoped publisher authentication — 2026-10-22
- Authenticate Pages-only tokens against the fixed snapshot project instead of
wrangler whoami, which can require unrelated identity permissions. Require the explicit account and expected project/subdomain; refuse redirects, oversized/malformed metadata and access failures before deployment. Retain local OAuth account checks and all source, drift and exact canonical-byte gates.
Pages publisher credential boundary — 2026-10-21
- Bind snapshot publication to a dedicated protected
CLOUDFLARE_PAGES_API_TOKENsecret after the first run confirmed that the Worker-only token cannot access Pages. Fail explicitly if missing; retain all publication gates and avoid a fallback that widens Worker credentials.
Fleet service adoption — 2026-10-21
- Add the standalone Corridor service to strict SDK/default-urllib monitoring using its own health and MCP metadata contract. Check all twelve fleet dependency endpoints and require CIS's snapshot to be current within 72 hours; liveness cannot hide stale screening data. Schedule the existing gated Pages publisher in the existing protected production environment, without adding credentials or widening permissions. Preserve signed A2A verification on the thirteen services that publish it.
- Support paired typographic quotations and simple HTTP(S) Markdown citation links in the bounded hosted answer review. Retain exact source-ID resolution, quote comparison, unsupported-syntax findings and unassessed semantic/factual support. Keep existing plain citations, schemas, quota and payment contracts.
- Prepare specialist JSON locally on Agenda/Assistant, copying compatible supplied fields and showing missing fields without a cross-origin submission or evaluation attempt. Put Minerals document-owner request drafts before the generic summary. Demonstrate intact/tampered Escrow artifacts with actual hash/schema checks and mandatory human review.
- Publish scoped human-delivered service offers, a synthetic editable-document sample, acceptance runner and scope/measurement templates. Prices are test hypotheses; API billing is separate. Correct Snapshot/trial/Escrow descriptions; do not claim customers, autonomous document production, clearance or paid validation.
Answer review first use — 2026-10-21
- Remove manual source-ID entry from the MCP Apps first-use path: suggest stable citation labels, show how to cite them, preserve supplied IDs and never silently reuse a removed label for another document.
- Explain network versus daily trial exhaustion, prevent another review after known exhaustion, and permit a deliberate allowance refresh without losing the previous result. Keep backend admission, quotas, payment, public schemas and factuality boundaries unchanged. Add first-use and exhaustion regressions; verify local owner practice separately from external demand.
Machine-client edge access — 2026-10-21
- Confirm the owned domain and attribute default Python urllib's 403/1010 to Cloudflare Browser Integrity Check using the matching Security Event. Activate an owner-confirmed BIC-only exception on the thirteen canonical hosts' machine routes, retaining the global BIC setting and all other security settings. Verify unchanged urllib and official SDK discovery across all thirteen hosts; document scope and rollback.
- Require default-urllib compatibility in the existing scheduled and post-deploy monitor, including Output-only runs. Correct stale domain-ownership and infrastructure-limitation notes. No Worker runtime, authentication, quota, price, payment or package-version changes.
1.21.1 — 2026-10-21
- Fix production x402 v2 admission at the dedicated Output plugin endpoint: return an unevaluated MCP tool error in HTTP 200, matching
/mcp/agent, while retaining payment headers and exact URL binding. Share standard client-path selection across legacy and x402 adapters; cover challenge and failed/unavailable payment responses under the production configuration. Preserve direct legacy MCP/REST statuses, prices, quotas and authorization.
1.21.0 — 2026-10-21
- Make hosted onboarding free-first across the fleet and align the Output plugin with its actual trial catalog. Add a bounded answer/source citation preflight (
review_answer) and optional MCP Apps form using the same Output campaign admission, completion and feedback path. Opening, status and schema preflight consume no attempt; explicit reruns do. Preserve existing full audits and paid admission. Citation structure does not establish semantic support, factual truth or permission to act. - Return complete MCP JSON in text content for clients that omit structuredContent. Negotiate supported legacy initialization versions; validate modern HTTP mirrored version/method/name headers before quota/payment admission and preserve supported 2025 clients. Add corrected-rerun, contract, quota, privacy, UI and dual-era regressions; update package mirrors, catalogs and documentation. No live model API check or external adoption claim.
1.20.0 — 2026-10-21
- Release bounded optional schema-output memo generation and private offline replay with exact coverage checks. Expose replay through the installed Python module as well as the checkout wrapper, fingerprint installed scorer sources, and verify wheel/PyPI replay plus incomplete-coverage refusal in CI smoke.
- Synchronize package, manifest, discovery, SDK, Docker and current documentation versions; regenerate synthetic contract responses and Worker examples. Retain original local schema/quality checks, v1 contracts, prices, quotas and authorization. Live model API validation was omitted at the maintainer's request; offline synthetic results are not factuality, model-quality or adoption evidence.
Memo generation and replay — 2026-10-20
- Send an explicit schema for optional Anthropic memo generation, retain original local schema/quality validation, and reject refusal, truncation, ambiguous JSON and budget overflow without automatic generation retries. Preflight provider token estimates and a local serialized-input byte ceiling; keep server audit metadata separate from model output.
- Capture private raw memo outputs with provenance and rescore offline against exact unique case/sample coverage. Suppress aggregate scores on incomplete/altered artifacts and count technical failures as mismatches. Reuse the existing synthetic memo-quality corpus; no factuality, model-quality or adoption claim.
OSS Scanner preparation — 2026-10-20
- Add a source-built Docker audit environment, offline verification commands and a source-backed security threat model. Keep production releases, credentials and deployment behavior unchanged. Enrollment remains subject to maintainer approval and Anthropic review; preparation is not a completed audit or security certification.
- Keep the intentional unknown-method MCP diagnostic typed when the optional official SDK is installed; include that SDK in CI typechecking and the existing real stdio exchange regression. No wire behavior changes.
Preflight observation — 2026-10-20
- Record content-free HTTP/MCP schema-preflight outcomes in funnel v6, separately from evaluation, payment and trial consumption. Bound tool/reason labels, retain owner-purpose classification and preserve responses if telemetry fails. Add all-profile privacy and refusal regressions. No public tool schema, service version, evaluation, pricing, authentication or quota changes.
Operational signature monitoring — 2026-10-19
- Require deployed A2A card ES256 signatures in the existing thirteen-host MCP compatibility monitor. Read public JWKS only from configured canonical HTTPS origins, refuse redirects and ambiguous JSON/keys, verify every published signature and confirm altered cards fail. Report a failing signature as a required monitor failure on the existing schedule and post-deploy runs. Add negative/rotation regressions without changing service versions, signing keys, evaluation, authentication, payment or deployment behavior.
1.19.0 — 2026-10-19
- Add free schema-only input preflight over hosted MCP and HTTP across twelve profiles, with bounded static validators, JSON Pointer diagnostics and no evaluation or trial consumption. Publish same-origin tool schemas, synthetic examples and per-host machine contracts; expand fleet routing metadata and complete nested Financial Guard/Escrow input schemas. Synchronize x402/card/payment discovery with configured v2 and separate optional shared offerings. Preserve domain verdicts, authorization, prices, settlement and quotas; shape validation is not evidence verification or action approval. Include a dependency-free discovery/preflight client and all-profile contract regressions.
1.18.0 — 2026-10-19
- Add an action-bound Critical Minerals evidence loop: source-level supplier/counsel request drafts, blank document templates and optional rechecked previous submissions. Compare newly reviewable, regressed and still-missing documentary coverage only within unchanged decision scope and explicit nondecreasing assessment dates; flag removed blocker statements for human review. Expose the loop through existing local/HTTP/MCP/A2A tools and browser revision preparation without automatic submission or new dossier storage. Preserve scoring, upstream blocks, authentication, prices, quotas and mandatory human approval. Synthetic tests are not external usefulness evidence.
Operational checks — 2026-10-19
- Probe the canonical custom domains in the live MCP monitor, retain the independent default-urllib strict check, and update the exact catalog baseline for native feedback. Cross-check monitored origins and tool inventories against actual Worker discovery in an offline regression so a catalog change cannot silently leave the production monitor stale.
1.17.1 — 2026-10-19
- Expose optional completed-trial feedback through native MCP and A2A, including the Critical Minerals pre-offtake pilot. Return the attempt ID inside trial metadata, preserve completion/network/product/expiry checks and production authorization, and consume no evaluation allowance for feedback. Publish a two-step dossier workflow and correct paid-only onboarding copy. Feedback is self-reported; synthetic regressions and maintainer checks are not external adoption or usefulness evidence.
Guard npm clients — 2026-10-18
- Release independently versioned ElizaOS plugin 2.1.0 and mobile client 1.3.0 with canonical custom domains, current evidence diagnostics and transport of externally signed x402 v2 proofs. Preserve exact-request/proof recovery and legacy payments; no automatic funding, signing, retries, action authorization or settlement. SDK tests include current Worker fixtures and synthetic loss/recovery. Hosted/core version remains 1.17.0.
1.17.0 — 2026-10-18
-
Regenerate saved synthetic responses used by all twelve landing pages and verify them against actual handlers in every Worker test/deploy. Publish current advisory routing and conservative evidence boundaries under a new synchronized package, card and registry version.
-
Add stable Output Verification reason codes/checks and optional five-minute ES256 evaluation attestations bound to the request and result. Enable the existing Output deployment, refuse signing failure, and preserve advisory verdicts, human review, prices and quotas. Include complete signed JSON for official x402 MCP clients that retain only text content; add trusted-origin client verification, explicit-budget paid example and synthetic replay/latency examples. No real payment or source-authenticity claim.
-
Add native A2A free-trial status/evaluation through the advertised optional message-metadata extension; reuse the HTTP/MCP validator, atomic product/network quota and fleet daily limit. Preserve production authentication, task capabilities, and paid evaluation admission.
-
Add standard x402 v2 exact EIP-3009 Base native USDC payments over HTTP headers and native MCP metadata, with official-client offline regressions. Use PayAI's public free path, local signature validation, durable first-request binding, encrypted response recovery, and independent onchain authorization/transfer confirmation. Never release an evaluated result before confirmed payment or automatically re-submit uncertain settlement. Preserve legacy funding-wallet signatures and prices. Real settlement is not claimed by maintainer tests.
-
Classify every quote absent from supplied nonempty source text as unsafe, including a fabricated quote beside a matching one. Missing source text remains insufficient evidence rather than a proven mismatch.
-
Add advisory action metadata across hosted evaluation results and the maintained Python profile responses; separate risk scores from evidence readiness and never grant authority. Preserve legacy verdicts and access/payment/quota rules.
-
Report the actual Financial Guard rule violations and unassessed AML screening. Expose sanctions screening freshness/identity limitations, label caller assertions, and exclude explicitly illustrative/placeholder sources from documentary coverage. Refresh examples and generated schema clients; historical fixture names remain for compatibility even when illustrative evidence now yields insufficient readiness.
-
Legacy Bankability preview now separates delivered free output from the optional $25 scenario memo/schedule and exposes HTTP/MCP continuation on the caller's hostname. Correct payment instructions to require the funding-wallet challenge signature and exact-request retry; no pricing or entitlement changes.
-
Return a serialized, query-free JSON wire example after malformed hosted requests. Explain verbatim sending versus form encoding or double serialization, without echoing submitted content or bypassing payment.
1.16.2 — 2026-10-16
-
Publish current MCP onboarding on PyPI and use absolute release-pinned GitHub documentation links in the distribution README. Keep runtime contracts and review boundaries unchanged.
-
Clarify MCP tool selection for answer-only evidence review, unsigned action checks, signed readiness receipts and the native free trial. Keep existing names, argument schemas, access rules and evaluation behavior.
-
Clarify local stdio versus profile-scoped hosted MCP catalogs in README and MCP documentation. Document native trials, current custom-domain connection URLs, actual 32-tool local count and non-idempotent trial calls.
-
Expose enabled fleet trials as native MCP
free_trial_statusandfree_trialtools, including the Output Verification plugin endpoint. Reuse the HTTP trial's evaluator, atomic network/daily quotas and durable receipts; preserve paid-tool admission and configured production authentication. Publish schema/example-driven MCP onboarding and return quota/storage failures as tool errors without a successful evaluation payload. -
Lead all twelve A2A cards with distinct task descriptions and publish a first-evaluation recipe for each enabled free trial. Correct paid-only copy that hid the existing five/two-attempt trials, explain the raw-arguments HTTP trial format to MCP clients, and preserve authentication, admission, quotas and human review. Group fleet entries by workflow and link standalone Dual-Use guidance and current Agenstry aliases.
1.16.1 — 2026-10-15
-
Make ordinary MCP checks and public Python SDK clients use neutral client labels instead of claiming maintainer probes. Add explicit MCP
--owner-test/owner_testfor own checks and report caller purpose. Historical labels do not establish user identity and are not reclassified. -
Add
agenda-mcp-check --self-testusing the installed interpreter and read-only local tool, so the pip quickstart works outside a source checkout. Keep operator opt-in for remote examples and strict incomplete results for untested tool execution. -
Clarify the Interaction Trust evidence-review boundary and link the request-bound Python integration and maintained Vizier Worker executor. Verify installation and local enforcement cases without claiming actual human approvals, live protected actions or external adoption.
-
Add a blank one-claim citation-review entry on Output Verification: paste an assertion, original excerpt, optional quote and explicit caller support assessment. Reuse trial limits, recovery, owner markers and optional feedback; preserve literal input and mandatory human review. Record only a bounded, unverified flow label and publish a self-serve pilot guide without claiming participants or demand.
-
Label same-origin web-console requests with a bounded, explicitly unverified surface claim in payment diagnostics. Preserve caller identities, auth, quotas and payment; discard arbitrary labels. Exercise actual bundled JSON submissions across the fleet and form-encoded A2A rejection/correction. Historical malformed inputs remain unattributed.
-
Move all twelve official MCP Registry remotes and the website to the registered custom domains. Support immutable registry-only metadata revisions without republishing Python packages; preserve workers.dev aliases and signing keys.
-
Repair the hosted quickstart's A2A example extraction from the signed card extension and document A2A 1.0 endpoint discovery. Distinguish empty, malformed, invalid-UTF-8 and oversized JSON admission failures with finite privacy-preserving diagnostics and specific repair instructions. Preserve input rejection, quotas, prices and authorization; historical failures remain unattributed.
-
Publish existing evidence-review facets for nine one-skill Worker profiles with executable A2A examples and response JSON pointers. Preserve original skill ids, paid admission, configured authentication and human-review boundaries; no unimplemented security, protocol or business-identity declarations.
-
Reconcile completed Output Verification verdicts in usage counters without treating unknown decisions or execution failures as usable results. Disable repeated free submissions after quota refusal until an explicit successful availability check. Add optional bounded usefulness feedback tied to an existing completed same-network/product trial, with input/result-free telemetry and privacy disclosure. Keep prices and atomic campaign limits.
-
Complete custom-domain navigation in landing pages, hosted llms.txt and MCP orientation. Preserve summary links for both new canonical hosts and saved workers.dev results while rejecting unrelated destinations.
-
Publish the registered agendamcp.dpdns.org custom-domain origins in fleet discovery, verifier handoffs, routing recommendations and agent-readable documentation. Preserve workers.dev aliases, OAuth issuer identifiers, tool contracts, authentication and payment admission.
-
Show free-trial allowance before preparing input through an optional read-only availability check. After a quota refusal, preserve input and offer the saved synthetic example without another attempt. Publish the matching A2A example in trial discovery and clarify structured-request recovery. Keep atomic admission, campaign identities, quotas and prices.
-
Revalidate the official PyPI index without pip's HTTP cache during post-release smoke retries, and allow a longer bounded propagation window. Keep exact version pins and fail if the package remains unavailable.
-
Fix successful evaluations appearing as
Evaluation failed: __name is not definedafter deployment. Keep serialized summary functions self-contained under Wrangler's name-preserving build; retain the original verdict, evidence gaps, actions and complete response. -
Exercise generated landing scripts from a bundled Worker across all twelve products before deployment. Pin esbuild as a test-only dependency; service contracts, pricing and trial allowances are unchanged.
1.16.0 — 2026-10-10
- Add request-bound Interaction Trust + Vizier integration gate and offline diagnostic CLI. Check authenticated scope, signed delegation provenance, exact request receipts, expiry, real human approval consumption and durable one-use reservation before the integration dispatch callback.
- Add MCP Integration Check CLI and composite GitHub Action with an optional pinned official client: discovery, JSON Schemas, required/public auth, protocol errors and explicitly opted-in examples; test both stdio and HTTP.
- Add an offline Agent Checkout Readiness ACP sandbox profile with pinned licensed protocol schema, catalog/variant/price/stock checks, idempotent repeats, cancellation and merchant-owned refund handoff. No live commerce or settlement claim.
- Preserve wrapped Markdown sentence context and table column labels for local grounding diagnostics. Bind table numeric support to the named row and compare explicit claim clauses for polarity without changing raw evidence, quote matching or lexical thresholds.
1.15.0 — 2026-10-10
Local RAG Output Verification
- Assemble evidence packets from inline-cited answers and original retrieved chunks with
review_rag_answerandreview-answer. Preserve every nonblank line, unknown citations, quote attribution and source identities; surface line offsets and specific repair actions without a model, wallet or network. - Reuse the deterministic packet checker and evidence ledger. Reject malformed/empty/oversized input and duplicate chunk IDs; bounded citation parsing routes findings to revision and clean lint only to human review. Factuality remains unassessed.
- Add an optional LangGraph repair/recheck/human-handoff example, fictional original/revised fixtures and failure/reward-hacking contract tests. No new core dependency, hosted route, pricing or quota changes.
- Publish standalone installation guidance and exercise both the Python adapter and strict CLI from an installed wheel and the published package. Synchronize maintained release metadata and regenerate versioned fixtures; preserve service outcomes and evidence.
Structured A2A onboarding
- Publish canonical A2A 1.0 message parts in all twelve Worker examples and input-repair hints, without the legacy
kinddiscriminator. Retain inbound legacy data parts and structured JSON serialized as text. - Give Interaction Trust an executable structured skill example and a runnable admission check. Clarify required evidence and that valid unpaid evaluations return HTTP 402; completion describes the admitted success shape. Prices, quotas, validators and payment requirements remain unchanged.
Free-trial admission diagnostics
- Distinguish product campaign network exhaustion from shared UTC daily capacity in free-trial 429 responses and bounded telemetry. Keep
trial_exhausted, quotas and prices; refusals consume no attempt. Only daily capacity returns aRetry-Afterhint. - Separate free-trial admission refusals from evaluation/receipt failures in telemetry. Determine the quota reason and reserve atomically in one D1 transaction; fail closed on unavailable or inconsistent storage.
1.14.1 — 2026-10-09
- Add
/mcp/agentfor standard MCP clients: payment admission and funding signature challenges are explicit unevaluated tool errors. Preserve legacy HTTP payment statuses, exact-request signatures, auth, trials and recovery. - Retry temporary registry read timeouts when confirming publication, without treating an unavailable registry as a successful verification.
- Align secondary discovery, verifier handoffs and OpenAPI with the standard-client MCP endpoint; preserve legacy OAuth resource identifiers and routing aliases.
- Publish the serving hosted catalog, actual per-tool access, factual data retention and current pricing links in discovery; expose the shared fleet directory at
/.well-known/fleet.json. - Separate local stdio tools from hosted profiles in agent-readable documentation. Release the previously merged Russian geography routing fix to PyPI and align MCP Registry publication to immutable release artifacts.
Unreleased — fleet walkthrough repairs
- Preserve the Escrow product identifier in optional feedback drafts; bounded identifiers may contain digits after the first letter.
- Recognize Russian Kazakhstan names and inflections in Python and hosted routing; keep subject matching Unicode-aware. Link Kazakhstan market-entry questions to the existing review gate without changing other geographies.
- Offer editable fields, published enum choices and empty document rows across all twelve free-trial pages; retain the complete JSON editor, unknown caller fields and explicit paid action. Add optional caller classification and escrow artifact/hash/schema inputs without inventing evidence.
- Show specific dual-use review leads, suggested document-owner requests where the service has no assigned actions, and changes since the previous successful on-page check. Preserve routes, scores, service evidence and factual-verification boundaries. Clear stale summaries when parsing or a request fails.
- Shorten optional user-reviewed feedback to usefulness and a blocker; neither the request nor result is attached or automatically sent. Keep trial quotas and prices unchanged.
Unreleased — durable free-trial completion measurement
- Record a bounded free-trial completion receipt in the existing shared D1 ledger before returning HTTP 200. No inputs, outputs, caller identifiers, payment proof or client traces are retained. A receipt write failure returns an explicit 503 with consumed-attempt status; paid execution remains separate.
- Add authenticated fleet completion aggregates to
/stats, with a rollout coverage boundary and null counts for uninstrumented history or unavailable storage. Keep the provider logs for diagnosis and do not reconstruct missing historical events. - Offer a user-reviewed feedback email draft on each free-trial page, asking about task usefulness, missing pieces and repeat intent. Attach only the product and bounded check status; no automatic send or raw request/result attachment.
Unreleased — free first attempts across the fleet
- Extend opt-in free live trials to all twelve configured products using their existing evaluators and matching input contracts. Keep the Output Verification trial URL; add
/v1/trialand publish product-specific examples, optional paid tools and prices. - Reserve two attempts per hashed network address per product under one atomic 1,000/day fleet ceiling, preserving existing Output campaign usage. Reuse the existing trial table without changing payment records; missing storage fails closed.
- Put a free-first editor on every product, preserve submitted inputs and structured results, and require an explicit paid action. Escrow retains its 0.50 USDC price; other evaluation prices remain 0.05 USDC. Free Financial Guard results omit payment challenges; free CIS screening disables the paid hosted fallback.
- Keep free completions and owner/probe exclusions separate from confirmed paid executions. Routing products retain routing scope; no conversion or customer usefulness improvement is claimed.
Unreleased — Output Verification free first evaluation
- Add an opt-in REST trial endpoint using the same evidence validator and evaluator: two reserved attempts per hashed network address and an atomic 1,000/day service limit in D1. Validation errors do not consume attempts; missing storage fails closed.
- Put the live free trial first on Output Verification, preserve inspectable results and offer a separate explicitly paid evaluation. Trial completion is recorded as free preview, never confirmed paid execution; page-local correlation carries into the optional paid request.
- Publish trial scope and the additive migration; shared networks share allowances, fingerprints do not establish users, and no usefulness or conversion improvement is claimed.
Unreleased — first useful result across the fleet
- Align Agenda and Kazakhstan Market Entry directory links with their configured production Worker names; check all twelve canonical task links.
- Group existing products by user task and show intake, useful output and next human step on every landing page. Project existing routes, evidence gaps and owner actions into readable summaries while retaining complete responses.
- Replace generic trade text consoles with valid published MCP requests for Agenda, Corridor Assistant and Middle Corridor; retain paid admission and explicit recovery.
- Fix Corridor Assistant matching
shippingas a Gulf vessel, prioritize explicit Gulf geography over corridor hints, and make the selected dual-use gate reachable. Refresh saved synthetic examples from the local handlers. - Extend malformed/oversized JSON recovery hints across REST/MCP/A2A; preserve schema diagnostics, trace and attempt IDs in the shared Node client and reject non-object tool input before HTTP.
- Add private session templates and a local aggregate readout for the prepared human usefulness pilot. Unknown values remain null, owner practice is separate, and no actual human sessions or customer benefit are claimed.
Unreleased — telemetry demand quality and input recovery
- Separate catalog/domain usage and record deployment-key authentication without asserting customer identity; align owner test labels across telemetry sources.
- Add paid-input validation events, bounded failure families and malformed/oversized input measurements while retaining existing admission, payment and replay behavior.
- Return transport-specific schema/example hints and expose server HTTP attempt IDs; preserve page-local traces during manual input correction.
- Document compatible vault aggregates and a five-session human-assessed pilot protocol; deployment and real-user sessions are not claimed by this patch.
Unreleased — development dependency security
- Update the ElizaOS integration's installed PBKDF2 dependency to 3.1.7 and scope a PDF.js 6.2.108 override to its type-checking development host. Source development requires Node 22.13+ or 24+; the standalone client retains Node 20 support.
- Document remaining upstream ElizaOS/elliptic advisories and bundled crypto limitations. Repository overrides do not repair consumer hosts or establish runtime PDF compatibility.
Unreleased — comprehensive quality corrections
- Keep HTTP failure status, payment trace and retained proof when response bodies are non-JSON, null or unreadable. Successful malformed bodies cannot become verdicts.
- Prepare patch releases plugin-guard 2.0.1 and guard-mobile 1.2.4; publication is tracked separately. Reject invalid SDK amounts and timeouts; normalize legacy remote allow to mandatory review in the mobile client, matching ADR 0027.
- Validate finite, non-negative escrow allocations and balance conservation before displaying a ready proposal. Held results have zero proposed payouts, human review and no settlement authorization.
- Preserve Python paid/authentication HTTP refusals instead of hiding them behind network fallback; remove the canonical Ethereum USDC contract from its erroneous local risk denylist.
- Extend public conformance to all twelve Workers, verify AgentCard signatures and treat paid 402 admission as the expected boundary; keep domain input refusal tests offline.
- Keep generated HTTP client cancellation active through response-body streaming, remove abort listeners after completion and retain 429 retry metadata for non-JSON refusals.
- Align local Makefile lint/format coverage with CI by including Python integrations.
- Repair the offline Virtuals example, remove fabricated contract dates/identities/digests from count-only requests and preserve required review in integration results; replace stale execution/latency/clearance claims and catalog snippets with current connection instructions.
2026-10-06 — ElizaOS plugin 2.0.0 public contract
- Replace outdated npm-facing firewall, zero-retention and autonomous arbitration claims with the evidence-review boundary; include an offline synthetic example, character template and license in the archive.
- Preserve pricing, signature challenges, trace and the exact Financial Guard/Escrow request for explicit payment recovery. No automatic funding, signing, retry or settlement.
- Require structured action input, honor the runtime financial endpoint setting, validate returned verdict shape, await callbacks and return the ElizaOS 1.7.2 ActionResult contract with signing_authorized=false. Evaluation success is distinct from wallet permission.
- Make the ElizaOS peer optional for standalone users and limit its declared range to >=1.7.2 <2. The major release documents migration from the old boolean action handler; compatibility with 0.x is not asserted.
- Replace the invalid json_dataset deliverable example with the Worker-supported json_data enum and type the supported deliverables.
2026-10-06 — Fleet client and adapter consistency
- Share exact-request MCP admission and explicit recovery across all twelve profiles; link the runnable client from every landing page and retain Output Verification's bounded result check.
- Preserve mobile SDK HTTP/payment refusals, price, challenge and trace; add retained Financial Guard/Escrow calls and prevent a failed paid request from falling back to a local approval.
- Require an approving human-review callback before the mobile executor can run; default offline client fallback to human review. Keep the legacy strictMode option source-compatible without bypassing required review.
- Repair three offline Python adapter examples that expected obsolete approvals/settlements; replace live-dependent mobile tests with actual local-handler and network-failure fixtures. Add these checks to CI.
2026-10-06 — Public integration and exact-call recovery
- Preserve 402 pricing and payment correlation in the focused Output Verification client; keep the original request, protocol headers and proof for explicit signed retries and lost-response recovery. The helper does not open a wallet, transfer funds, sign or retry automatically.
- Link the runnable integration from the Output Verification landing page and clarify the free worked-example path for visitors without a wallet.
- Document a bounded pilot handoff and metrics without claiming external usage, customer identity or revenue.
2026-10-06 — Protected initialization of missing AgentCard signatures
- Add an opt-in, two-target Financial Guard / Escrow signing-key bootstrap to the existing protected fleet workflow. It runs only after a matching owner-signed Vizier ALLOW, never rotates existing signing credentials, and verifies the served JWS against the public JWKS.
- Preserve captured Wrangler JSON inventory at its normal log level while forcing sanitization; fail closed on unreadable inventory and label bootstrap discovery probes as owner checks.
- Keep private ES256 keys out of logs, arguments, repository files and artifacts; only the per-Worker Cloudflare secret retains them. Actual skills, provider identity and access policy are unchanged.
Unreleased — measurable adoption
- Exclude unknown/error outcomes from usable KV completions; label payment-header counts explicitly and leave confirmed executions unmeasured in this source.
- Add a private caller fingerprint and server-generated execution UUID to payment stage v3; commit the UUID with the payment binding and preserve it on replay. No ledger migration, new payment privileges or raw wallet/transaction data in logs.
- Add a runnable Output Verification MCP client with synthetic hand-off evidence, real-handler regression checks, and explicit payment refusal handling.
Unreleased — Fleet evidence and screening boundaries
- Add source-record integrity review: impossible dates, blank IDs/titles and conflicting document IDs cannot increase reference coverage.
- Separate reference completeness from actual risk and trust; complete labels do not authorize agent actions or establish low exposure.
- Preserve earlier sanctions flags after later upstream errors, distinguish outages from observed leaks, and align readiness with blockers and incomplete screening.
- Correct CHPL using the 50 exact HS6 codes in the BIS snapshot, including Tier 4A electronics equipment and Tier 4B CNC; make legal applicability a review question.
- Keep asserted guarantees from waiving DSCR screening; identify model thresholds and principal-only reserve assumptions.
- Publish additive contracts, corrected examples and service scope guidance; no new paid data dependencies.
Unreleased — Critical Minerals dossier review
- Replace document-label verification with dated, scoped excerpt review, duplicate/expiry checks, stage-specific evidence gaps and owner tasks (
mineral-dossier.v2). - Require human approval for complete dossiers; remove automatic quota, FEOC, uranium-transit and aerospace qualification conclusions.
- Distinguish unavailable upstream screening from observed DLP leaks and keep screening blocks consistent with readiness status.
- Preserve legacy request fields and source aliases; publish additive schemas, fictional examples and honest product instructions.
All notable changes to Agenda‑Intelligence.md are documented here.
Unreleased
-
Correlate signed checkout retries using an optional UUID-only
X-Payment-Trace-Id; keep per-request attempt IDs, payment authorization and replay protection separate. Add REST/MCP/A2A checkout and recovery tests. -
Preserve deployed profile on early paid protocol refusals and record bounded input-validation categories without retaining payloads or validator text.
-
Add explicit owner browser-test marking (
?owner_test=1) across example telemetry and same-origin checkout; the marker grants no entitlement. -
Remove misleading
freeskill tags from paid Worker deployments while preserving free discovery and fixed examples. -
Bind Financial Guard and M2M Escrow to their issued Agenstry ownership proofs; clarify skill inputs, outputs, examples and human-review limits without adding unsupported capabilities.
-
Restore the issued per-domain Agenstry ownership proofs for Output Verification and Kazakhstan Market Entry; test the configured proof routes against the owner verification records.
-
Clarify free hosted discovery versus signed paid execution, add a tested MCP/A2A quickstart, and correct the public successful A2A 1.0 envelope.
-
Accept Cloudflare empty POST body streams for worked-example telemetry while rejecting the first nonempty chunk without buffering request contents.
-
Close free bankability preview telemetry with explicit preview outcomes and measure fixed example opens with page-scoped trace linkage to payment attempts.
-
Restore wallet-free worked examples as fixed synthetic request/result pairs; edited live evaluations remain paid.
-
Keep paid MCP/A2A refusal responses JSON-RPC compatible and provide a closed text-only no-op heartbeat without domain evaluation.
-
Correct paid AgentCard descriptions that still advertised free evidence triage.
-
Separate privacy-bounded payment stage events expose 402/401 payment admission, verified execution and response replay with deployment versions. Declared integration-check clients are excluded from candidate usage.
1.14.0 — 2026-10-01
- Hosted pay-per-call v2 requires funding-wallet signatures bound to the exact URL, JSON request and task/protocol context. Public transaction hashes and inline body aliases cannot grant paid access.
- Signed non-Pro activation reserves one execution rather than consuming it. Identical signed retries recover the encrypted completed response for 24 hours; concurrent calls share an atomic execution lease.
- Validate paid inputs and operation prices before reservation, including the $25 bankability unlock. Financial receipts reuse verified request context and report the actual payer.
- Configure the deployed fleet for mandatory payment on evaluation, retain free discovery and bankability preview, and add browser checkout with original-payment retries. Apply D1 migration 0002 before gate release.
- See ADR 0032 and the payment execution contract for this intentional hosted payment compatibility change. Pro credential issuance retains its existing manual recovery boundary.
Unreleased — signed production deployment
- Require an owner-signed grant and principal-signed, identity/expiry/request-bound ALLOW before the gated Worker deploy invokes Wrangler.
- Mint a ten-minute, single-Worker delegation in a separate protected GitHub Environment step; private signing key is absent from the deployment step. Grant files are bounded and removed after the job.
- Missing, expired, mismatched or caller-asserted authorization stops deployment. Existing direct administrator access remains outside this gate.
Unreleased
Fleet website contract integration follow-up (2026-10-01)
- Exercise Explorer and zero-debt Bankability forms against actual REST handlers. Read
arbitration_ruling.payout_breakdown, require the API numeric DSCR input before payment, and mark the fixed illustrative interest rate read-only.
Fleet website alignment (2026-10-01)
- Align Explorer with the arbitration response envelope; preserve zero delivery counts, validate explicit deadlines, and replace fabricated contract state and autonomous settlement claims with caller-supplied evidence boundaries.
- Keep submitted wallet payments in page memory for activation/evaluation retries without another transfer; show incomplete activation honestly, preserve payer signatures, and stop payment on refused network switches or invalid bankability inputs.
- Preserve zero-debt bankability inputs and render debt-free DSCR as not applicable. Publish private A2A continuation and source freshness guidance; clarify separate telemetry and payment retention.
Fleet operations and payment ledger (2026-10-01)
-
Enforce configured deployment Bearer authorization on every POST
/v1/*execution alias, and bound JSON reads while streaming (1 MiB). REST payment amounts follow the requested operation while authorization follows the host. -
Replace settlement replay claims and Pro quota counters with one shared D1 ledger: atomic claims, permanent transaction uniqueness, hashed Pro credentials, and atomic quota consumption even when the free limiter is disabled. New claims require a Base block timestamp within seven days. Missing D1 denies settlement. This supersedes the KV-only limitation below.
-
Deployed A2A task continuation now requires a server-issued private
X-Task-Token; caller labels remain telemetry only. Old tasks must be recreated. Local legacy label mode remains available. -
Generate directory required fields from MCP schemas; empty Assistant MCP calls return the advertised directory.
-
Identify technical verification and owner traffic separately. Journal v2 compares full canonical inputs only within the same profile, capability, contract, engine and source snapshot; historical partial hashes remain explicitly marked.
-
Add
/health/dependencies, propagate source age and digest, reject future-dated snapshots, and align published-index CI with the runtime's 72-hour freshness limit. See ADR 0031 and the fleet operations runbook. -
Align live Trust and Dual-Use health proofs with DLP-only receipts, unverified ownership and mandatory human review; retain blocked-name and synthetic secret detection checks. Retry read-only MCP discovery transport interruptions at most three times and preserve each failed attempt in reports; persistent transport, HTTP and contract failures remain visible.
-
Publish outputSchema for all hosted Agenda MCP tools, including Financial Guard and Escrow legacy task envelopes, strategic triage, fleet directory and corridor orientation. Validate successful output and controlled refusals without changing request or response formats. Mark legacy Financial Guard/Escrow INPUT_REQUIRED refusals as MCP errors.
-
Preserve signed numeric facts (including Unicode minus), require contextual support for numbers across documents, and prevent unrelated verbatim quotes from upgrading grounded_check. Ambiguous numeric context requires human review; matching values in relevant sentences can still support multi-source claims.
-
Ship a zero-dependency urllib JSON MCP discovery example with an explicit application identity; require application-identified urllib discovery to pass the hosted monitor while keeping unmodified urllib 1010 visible separately. Telemetry identifies itself rather than claiming to be curl.
-
Monitor all configured hosted MCP endpoints plus Vizier using the ordinary MCP SDK identity, health and A2A discovery. Keep Cloudflare default-urllib error 1010 visible separately; add scheduled and post-deploy reports without credentials, paid calls or state-changing proofs.
-
Reject missing/invented bankability figures and non-boolean guarantees across hosted and Python tools; preserve legitimate zero-debt inputs and require human signoff. Scenario output no longer fabricates Excel provenance or promises files it does not generate.
-
Validate malformed financial/escrow fields before evaluation; decode ERC-20 approve independently of the declared method, and reject invalid arbitration policies/fees.
-
Align Dual-Use, CIS and decision-policy MCP schemas with runtime output; validate protocol results with full JSON Schema in CI. Dual-Use JSON carries a structural-only score and mandatory human-review boundaries.
-
Separate DLP receipt forwarding from unverified ownership and payment confirmation from security clearance. Report missing source quotes/content and actionable repair steps in Python and hosted output verification.
-
Document machine-client User-Agent requirements, payment signature scope, and production deployment prerequisites. Add an explicitly authorized manual, main-only rollout for existing Workers through protected CI and a separate signed grant per target.
-
Fix fleet health checks for required signed delegation: unsigned tenant requests must return BLOCK/GRANT_REQUIRED, require protected credentials, and revoke temporary keys even when assertions fail.
-
Hosted MCP discovery now derives required arguments from published schemas, provides illustrative first-call examples and evidence-specific next steps, and advertises actual deployment Bearer/quota settings without exposing secrets. Pricing manifest identity follows the serving profile registry. HTTP contract tests cover examples, missing evidence, authorization, quota exhaustion, plugin isolation and signed receipt binding.
-
Package Output Verification as a portable OpenAI/Claude plugin with a dedicated single-tool MCP URL, explicit human-review skill, and synthetic reviewer cases. Add the OpenAI domain-challenge route, conservative tool annotations, and local/live package checks.
Pro activation and MCP identity (round 6)
- Landing Pro activation now reads the
bearer_tokenfield returned by/v1/settle; a mocked wallet-to-settlement browser-script regression test checks that the buyer sees the issued key. - An
X-Payment-Txheader-settled Pro payment can be claimed for a Pro key only once, with the funding wallet's EIP-191 signature and matching payer/amount/tier in the existing settlement marker. Completed claims still return 409 without exposing the key. Workers KV remains eventually consistent, so this is not an atomic cross-region replay guarantee. - MCP discovery, initialize and response metadata now expose distinct server names per profile; the server-card display name follows the profile identity.
1.13.0 — 2026-09-26
Security hardening (round 5, breaking)
/v1/settlePro tier (tier_2_pro) now requirespayer_signature: an EIP-191 personal_sign by the funding wallet over the settlement challenge (Agenda Intelligence MD pro-tenant settlement\ntx_hash: <hash>\npayer: <address>). A public tx_hash alone no longer issues a bearer token, replayed claims answer 409 without any token material, and the KV marker stores only the token's SHA-256 fingerprint.- Agent Output Verification never issues
allow_relayor trusthighfrom caller-declared evidence packs; the ceiling isverify_before_relaywith mandatory human review, and a quote counts as grounded only when its text appears in the cited evidence content. - A2A tasks are tenant-bound to the caller's X-Client-Id label: cross-tenant GetTask/continuation answers TASK_NOT_FOUND; unlabeled tasks are scoped to anonymous callers only.
- CIS name screening treats a public-list snapshot older than the freshness maximum (default 72h,
SNAPSHOT_MAX_AGE_HOURS) as UNKNOWN instead of "no match", and name normalization covers Cyrillic and homoglyph variants. - The live telemetry stats token is read from
AGENDA_STATS_TOKENenv, not from the repository.
Contract and metadata alignment (round 5b)
- Agent Output Verification card, skill, boundaries, and the Python MCP tool description no longer advertise
allow_relay; they state theverify_before_relayceiling and mandatory human review. - Card
task_continuity.tenant_bindingstates that unlabeled tasks are visible to anonymous callers only, not to labeled tenants. docs/use-cases/agent-financial-guard.mddocuments thepayer_signaturerequirement for the Dedicated Pro Key.- Landing-page "Pay Pro (Base USDC)" flow signs the EIP-191 settlement challenge with the paying wallet before calling
/v1/settle, so browser Pro activation keeps working after the round-5 change, and surfaces settlement errors instead of staying silent.
Landing conversion, runnable v1 curl, and honest pricing catalog (2026-09-25)
- Profile-specific conversion on landing pages: console preloaded with realistic synthetic fixtures, worked example buttons, canonical/OG metadata, and self-referencing agent-card links.
- Verified runnable A2A 1.0 SendMessage curl snippets with
A2A-Version: 1.0,X-Trace-Id: example-trace-001, and concrete fixture response output shapes. - Honest pricing display scoped per profile (micro-check/dispute, deal dossier, sandbox) with explicit notice that legacy payment integration is not certified for standard x402 clients.
Growth readiness: intake, observability and verdict standard (proposed, 2026-09-25)
- Free-text intake on every vertical gate: unstructured text returns a typed INPUT_REQUIRED with a deterministic candidate (recognized vs unconfirmed), required fields and a working example; nothing is screened or guessed on intake, and high-stakes gates stay strict.
- Observability: end-to-end trace ids (X-Trace-Id header / params.trace_id / generated and echoed in task metadata), privacy-safe hashed caller identity, owner-synthetic (X-Client-Id instinct-owner-*) and named-benchmark (ZeroMockProof, ProofBench, mcpqueen) caller buckets, an x402 payment-header signal, and a qualified demand chain in /stats (unique caller -> usable completion -> repeat -> paid).
- Fleet-wide structured verdict block (agenda-structured-verdict/v1) on every v1 task: reason_code, next_permitted_action, human_review_required, evidence gaps, confidence basis and caller_supplied/auto_fetched/static_snapshot source labels.
- Financial Guard velocity check now reads UNKNOWN unless a caller-supplied policy was actually breached; Corridor Assistant routing recognizes commodities, corridor ports and bank-review phrasing.
- Usage event v8 / funnel event v4; historical rows remain readable (new buckets repair at read time like earlier probes).
A2A fleet contract and evidence safety (proposed, 2026-09-25)
- Advertise runnable A2A SendMessage envelopes for each shared Worker profile and distinguish A2A parts from MCP tool arguments.
- Remove the expedited PayPal URL from triage output; retain separately described pricing paths.
- Refuse empty Corridor Assistant requests, choose a single route when identifiable, and separate required from optional input fields.
- Downgrade placeholder output evidence, unknown CIS ownership, missing vessel subjects, and unevaluated escrow/financial checks instead of emitting a false clean signal.
- Mark sanctions index retrieval as a dated static snapshot rather than live success, and remove unsourced OEM-specific titanium claims.
- These status/score changes can affect clients that branch on existing labels. Review downstream consumers and deploy deliberately; no settlement behavior was changed.
Agent discovery compatibility — 2026-09-24
- Serve a non-executing MCP capability document on
GET/HEAD /mcp, while retaining POST-only tool invocation. - Add canonical redirects for common MCP aliases, crawler assets, sitemap discovery, a favicon, an agent-directory alias and an MCP probing document across the shared Worker fleet.
- Put the worked example, enterprise contact and confidential project-room actions above the fold; preserve the existing evidence and human-review boundaries.
Enterprise readiness corrections — 2026-09-23
- Escrow verifies artifact content and holds unverified delivery evidence; additive per-check status (contract 1.1.0).
- Scoped product pages, shared price catalog, synthetic dossiers, public trust/privacy/terms, JSON Schema routes and explicit DLP receipt scope.
- No new autonomous settlement, live fact-checking or institutional certification is claimed.
1.12.1 — 2026-09-23
- Fix the Base native-USDC history collector to query at most 1,000 blocks per
eth_getLogscall, matching the observed public RPC cap while preserving fail-closed whole-window coverage. - Document Vizier workflow reservations, owner-configured limits, extended financial retention and finalized Base reconciliation for the existing Python review integration.
1.12.0 — 2026-09-21
-
Add explicit Base native-USDC review preparation and optional authenticated Vizier review client with ES256 verification and one-time claims.
-
Ship the finalized Base USDC history collector in the Python package.
-
Preserve Guard rejection and manual wallet confirmation; no signing, broadcasting or automatic ALLOW.
-
feat(base wallet evidence): add a bounded read-only native-USDC transfer collector using the official Base RPC. Pin a finalized 24-hour window, reject partial/malformed responses, retain exact base units and explicit scope. Expose it separately on the Python Financial Guard SDK; verdicts still require human review and no wallet signing, sanctions clearance or USD valuation is added.
1.11.1 — 2026-09-20
-
fix(elizaos release): expose schema and escalation types, map Worker payout fields to the client contract, hold unknown rulings for review, remove the placeholder evaluator and document explicit wallet integration. Publish tests now run before the npm release; package and lockfile versions are aligned.
-
fix(worker trust boundaries): remove fabricated Vizier clearance and quorum proposal side effects from Financial Guard and Escrow. Require human review for unverified spending/sanctions evidence; enforce the same boundary in Python fallbacks and wallet adapters. Validate escrow artifacts against supported offline JSON Schema constraints, and hold unsupported or missing evidence for review. Relayers reject escalated rulings before preparing calldata.
-
fix(fleet coverage): derive monitored Workers from Wrangler configuration and add Financial Guard / Escrow negative safety proofs.
-
refactor(worker): extract browser presentation and telemetry from the shared request handler. See ADR 0027 for behavior, supported schemas and migration.
-
feat(ops): make manual sanctions-index publication a single fail-closed command.
scripts/publish_sanctions_index.pydefaults to a non-mutating rehearsal that rebuilds all four official sources, checks shape and canaries, rejects timestamp rollback or name-count drift above 10% against production, and records the candidate SHA-256.--publishadditionally requires a cleanmain, records an external decision workspace, deploys with pinned Wrangler 4.122.0 through the operator's local login, and requires the canonical Pages URL to serve the exact candidate bytes. The short-lived scheduled publisher and its GitHub credential path are removed; the credential-free watchdog returns to 04:20 UTC and remains the only scheduled index workflow. -
fix(ci): preserve a verified recovery artifact when the published sanctions index is stale. The watchdog still fails when the served snapshot exceeds its seven-day freshness budget, but it no longer skips the independent four-source rebuild after that failure. A successful rebuild is shape-checked and retained for seven days as an Actions artifact before the stale-publication failure is enforced, so an operator can recover even when local TLS policy blocks direct source downloads. The workflow also moves its GitHub-maintained actions to their current Node 24-compatible major versions. Publishing remains a deliberate authenticated operation.
-
fix(worker discovery and telemetry): keep external-agent discovery visible without counting its scouts as usage.
GET /.well-known/openapi.jsonnow serves the same contract as the canonical OpenAPI route, matching the path already requested by GAIP discovery clients. Self-identifying scout, test-loop, indexer, and benchmark user agents are classified as service probes for new events and repaired at/statsread time for historical KV rows. The Agent Card extension and completed-response engagement block now explain the optionalX-Client-Idheader as a stable non-personal integration label; it remains optional and is not authentication.
1.11.0 — 2026-09-18
-
feat(corridor-bankability): add hybrid Trans-Caspian bankability screener and x402 paywalled IFI memo. Exposes deterministic infrastructure finance covenants (DSCR floor 1.20x, non-sovereign margin 1.30x, leverage ceiling 80%), Caspian Sea hydrological bottleneck drop (-1.20m Baltic datum draft limit), and FX currency mismatch reserve sizing. Features a Freemium Decision Teaser ($0.00) and paid tier ($25.00 USDC via x402 on Base) unlocking a full 15-year deterministic debt waterfall schedule, standard-form EBRD/ADB Investment Memorandum in Markdown, and financial model SHA-256 hash. Available via REST (
POST /v1/corridor-bankability/screen), MCP (corridor_bankability_screen), and A2A (SendMessage). -
feat(web3-ui): launch interactive Brave Wallet bankability screener at
/corridor-bankability. Native web application for analysts and investors in Brave Browser, MetaMask, or Coinbase Wallet. Enables instant project simulation, live covenant table rendering, and one-click $25 USDC settlement on Base mainnet (0x833589...2913) with automatic memo and waterfall JSON/Markdown downloads. -
feat(smart-fallback): auto-complete unstructured agent queries to eliminate
input_requiredrefusals. Heuristic parameter extraction automatically identifies corridor segments, CapEx numbers, and infrastructure types from natural language prompts, populating standard IFI benchmark defaults to maximize conversion for external autonomous agents.
1.10.0 — 2026-09-17
-
feat(agent-financial-guard): add deterministic pre-sign transaction firewall for autonomous AI agents. Provides sub-5ms multi-layer pre-execution validation before transactions or smart contract interactions are broadcast by wallet-bearing agents (Coinbase AgentKit, Stripe Agent Toolkit, Privy, Circle). Enforces OFAC SDN and AML mixer screening (Tornado Cash, Lazarus, Garantex), drainer calldata defenses (infinite allowance detection), spending limits ($100 single, $500 rolling 24h), and intent prompt-injection scanning. Available via Python SDK (
AgentFinancialGuard), direct REST (POST /v1/agent-financial/pre-sign-check), MCP (agent_financial_pre_sign_check), and A2A (SendMessage). -
feat(m2m-escrow-arbiter): add autonomous B2B deal arbiter, settlement engine, and reference Base smart contract. Deterministic dispute arbitration and milestone verification for Machine-to-Machine (M2M) commerce. Evaluates contract delivery deadlines, artifact SHA-256 integrity, JSON Schema compliance, and telemetry SLO completeness. Computes mathematical payout allocations (
RELEASE_TO_SELLER,REFUND_TO_BUYER,PARTIAL_SETTLEMENT) with automated 1% arbiter fee deduction. Ships reference Base USDC smart contract (contracts/M2MEscrow.sol) with cryptographic ECDSA ruling verification and replay protection. Available via Python SDK (M2MEscrowArbiter), direct REST (POST /v1/m2m-escrow/evaluate-dispute), MCP (m2m_escrow_arbitration_ruling), and interactive 4-scenario simulator on Cloudflare Edge landing page. -
feat(monetization & fleet): add autonomous Base USDC settlement and expand fleet to 12 edge workers. Edge workers now accept on-chain Base USDC payments (
0x5b5296A3a7bAc0F5F096F93b60C1c121f2e5c663) with automated 30-day Pro Bearer key provisioning (agy_pro_...) and instant 429 bypass viaX-Payment-Tx. Public fleet expanded from 10 to 12 specialized gated edge workers.
1.9.0 — 2026-09-09
-
feat(worker): make agent-to-agent intake tolerant without making sanctions decisions from guesses. The CIS gate now normalizes the unambiguous aliases
financial_institution/bankingtobankandtintonational_tin, and discloses every change innormalizations_applied. Ambiguous labels such asfreight,logistics, andofficial_registryremain rejected, but now name the canonical choices instead of forcing a blind retry. Plain-text CIS and dual-use calls produce an unconfirmed structured candidate andTASK_STATE_INPUT_REQUIRED; no screening or classification runs until the caller confirms structured input. A newcis_secondary_sanctions_batchMCP tool andPOST /v1/cis-secondary-sanctions/exposure/batchroute accept up to ten independent counterparty requests, retain completed results when another item is invalid, and publish an explicit human-review decision workspace.GET /openapi.jsonnow serves the same document as/api/openapi.jsonfor clients that probe the conventional root path. No pricing or x402 signal is advertised because this deployment has no payment rail or enforced paid tier. -
feat(grounding): add a cached, morphology-aware IDF index plus async and SARIF adapters.
GroundingIndexnow tokenizes each supplied document and sentence once per check run, folds a conservative set of English and Russian inflections, and weights rare corpus terms above corpus-wide language using deterministic IDF. Single-document packets retain the previous plain-overlap scale, numeric and polarity guards remain independent, and all existing response schemas stay unchanged. The zero-dependency Python integration adds typed dataclass inputs,check_async,validate_or_repair_async, and a dependency-freeas_langgraph_nodestate adapter.check --format sarif [--out FILE]emits SARIF 2.1.0 findings located at claim lines, and the GitHub Action can upload that file to code scanning before enforcing strict failure. The standalone HTML reviewer adds a click-selected side-by-side claim/source excerpt with exact shared literals highlighted. No semantic similarity, translation, factuality inference, Pydantic, LangGraph, or stemming dependency was added. -
feat(evidence packet): reduce multilingual, numeric, and extracted-document false alarms. Lexical support now drops common Russian and Arabic function words in addition to English stopwords, while the existing sentence-scoped polarity check continues to read negation independently. Numeric facts are compared through conservative deterministic forms: scaled values (
10M,10 million,10,000,000), percentages (62%,62 percent), selected English/Russian/Arabic month-name dates plus ISO/dotted dates, and USD/EUR/GBP/RUB/KZT spellings. Currency remains part of the fact, so equal amounts in different currencies do not match; no exchange-rate or approximate-value inference is performed. Canonical numeric facts also reach lexical coverage, rather than only theunmatched_numbersdiagnostic. Quote matching now tolerates soft hyphens and both forms of PDF line-break hyphenation. A typo-level candidate at >=95% similarity is returned as a boundednear_missdiff for reviewers but the quote remainsabsentand the packet remains incomplete; candidates with changed numeric facts or polarity cues are suppressed. The optional diagnostic is additive in both v1 response schemas and is surfaced by check, grounded-check, verify-quotes, and HTML/Markdown review. The shared lexical and quote-matching implementation now lives in the internalagenda_intelligence.groundingmodule;agenda_intelligence.servicesretains its compatibility facade while discovery depends on the focused module directly. No model, network call, language detector, currency conversion, or factuality claim was added. -
feat(worker telemetry): explain why external calls stop at
input_required. Usage event v7 adds a bounded outcome reason and static required-field names, and KV now retains the already-computed structured-payload character count./statsreports external input-required totals, how many contained no parseable structured data, their reason codes, and the fields named by the gate's request guide. Raw prompts, validation text, examples, headers, and caller identifiers remain excluded; older KV rows stay immutable and aggregate underlegacy_or_unknown. -
fix(worker telemetry): make the usage counter exclude known probes and identified self-tests.
/stats.non_probetrusted only the storedlikely_probeboolean, while the same event could already saycaller_kind: service_probeandtraffic_class: machine_probe. Measured over 2026-09-01..07: 695 action rows, 554 reported non-probe, 522 from the operator's ALMANET connection and 31 of the remaining 32 from self-identified scanners. The two classifiers now share one probe decision for A2A and MCP calls, record a boundedprobe_reason, and repair event-v5 scanner rows at read time without rewriting KV history./statsaddsexternal_non_probe,external_empty_handed, andprobe_reasons; the stats CLI prints them. The production refusal and decision-gate verification scripts now identify themselves with the existingagenda-intelligence-*self-test convention. ALMANET is deliberately not hard-coded: an ASN identifies a network, not the operator, and would hide a legitimate caller on the same ISP. The agent card, optionalX-Client-Id, response engagement/contact block, request schemas, and product verdicts are unchanged. -
fix(ci): keep the sanctions watchdog meaningful during a temporary official-source outage. The first scheduled run hit a persistent HTTP 500 from the European Commission FSF file backend and stopped before checking the public index, even though the served snapshot was one day old, contained all four sources, and still had 84,367 names. Downloads now retry transient network, rate-limit, and 5xx failures with bounded backoff and report the affected source without an unhandled traceback. The workflow now gates the served index first; a failed fresh rebuild becomes a visible warning while that index passes availability, shape, and seven-day freshness checks, and the drift comparison is deferred. An unavailable, malformed, undersized, incomplete, or stale served index still fails the run.
-
fix(ci): watch the published index instead of publishing it, and drop the credential. The scheduled job added a moment ago deployed to Cloudflare Pages, which meant standing up an API token and an environment to hold it. That was solving the wrong half. The failure this guards against was never the absence of automatic publishing — it was silence: the previous index stopped being served in August and nobody noticed for a month, because a worker that degrades gracefully degrades quietly. Publishing needs a credential; noticing does not. So
refresh-sanctions-index.ymlbecomescheck-sanctions-index.ymland writes nothing. It rebuilds from the four official sources — which is how an upstream serving an error page, a truncated body, or an expired certificate gets caught on an ordinary day rather than on the day someone needs to republish — thenscripts/check_published_index.pyreads the public URL the worker actually reads and fails when it is unreachable, carries no build date, is older than seven days, or has drifted more than 10% from what the sources give today. All three failure paths were exercised against doctored copies: a 404 exits 1 with "the worker is screening on caller-supplied evidence only until this is republished", a July index exits 1 with "65 days old (limit 7)", and a corpus missing half its names exits 1 naming the drift. Against production it exits 0. Republishing stays the deliberate local command indeploy/snapshot-site/README.md, run under the maintainer's own wrangler login, so no Cloudflare token is stored in GitHub at all and no environment is needed. Correction to the previous entry: it describedagent-output-verification-productionas administrator-gated. That environment carries a branch policy and no reviewers — the phrase came from that workflow's own self-description rather than its actual protection rules. -
feat(ci): rebuild and republish the sanctions index on a schedule, and refuse to publish a broken one. The previous index stopped being served in August and nobody noticed for a month — the host was a repository that had been deleted, the worker degraded to evidence-only exactly as designed, and the silence was the whole problem. A snapshot that nothing rebuilds fails the same quiet way: the gate keeps answering
successwhilegenerated_at_utcages.refresh-sanctions-index.ymlnow rebuilds daily from the four official sources and republishes to Cloudflare Pages, withworkflow_dispatchfor a manual run. The gate in front of the deploy is the point.scripts/verify_sanctions_index.pyrejects an index whosename_countfell below 60,000, whosesource_countis not 4, or that lost either of two long-standing canary designations — the failure this guards against is not a crash but a source serving an error page or a truncated body with HTTP 200, which yields a valid-looking index with most of the names gone. Publishing that would leave the gate matching nothing while still reporting that it screened. Both rejection paths were exercised against deliberately damaged copies before the workflow was committed. On failure the job stops before deploying and the last good index stays live, and the final step polls the published URL untilgenerated_at_utcmatches what was just built, so a green run means the file is actually serving. The job runs in its ownsanctions-index-productionenvironment rather than borrowingagent-output-verification-production: that environment is administrator-gated because it can deploy workers, and an unattended scheduled job should hold a Pages-only token instead. -
fix(cis): score the evidence the screening actually merged, instead of contradicting it. Activating the Snapshot upstream (ADR 0020) made one response say two things. The result builder merges an auto-fetched name match into
supplied_sources, somissingshrinks and the evidence half of the response reports an OFAC SDN hit — but all three scorers still short-circuited onrequest.dated_sources, which the minimal first pass (#307/#308) defaults to[]. Measured on the deployed endpoint forSBERBANK OF RUSSIA:auto_fetched_sourcesnaming the SDN entry,supplied_sources: ["ofac_sdn_extract", "uk_ofsi_extract"], and a verdict ofsecondary_exposure_signal: unknown/triage_recommendation: insufficient_information/decision_readiness_score: 0. The body named the match; the verdict said nothing was found. The guard was right when it was written —dated_sourceswas the whole evidence pack. Live retrieval made the caller's array and the scored pack two different sets, and the scorers were never moved across. They now read the effective pack (supplied_sources, caller evidence plus whatever screening merged), so a match reaches thehighbranch,escalate_before_*, and a non-zero readiness score. A counterparty nobody screened, and one screening cleared, both still returnunknown/insufficient_information/ 0 — scoring the effective pack invents no evidence where there is none. Whathighasserts is unchanged and now says so in the response: a merged match adds a limitation reading "a name on a public sanctions list resembles this counterparty ... not a determination that this counterparty is listed, and not identity, ownership, or 50 % rule resolution", and the markdown artifact carries aName screening:line beside the signal.human_review_requiredstays unconditionally true. Same fix in the Python service and the worker, so parity holds; no response field added (the v1 schema isadditionalProperties: falseunder ADR 0003). ADR 0020 records the posture change. Also fixed while proving whathighmay be scored from: the worker passedautoFetched.length— which includes GLEIF ownership records (ADR 0022) — as the sanctions match count, so an ownership record alone could raise the signal tohigh. It is now counted before ownership enrichment appends to the same array. -
feat(cis): live name screening is back on, against an index this project owns. ADR 0020 activated the Snapshot upstream in June and was rolled back on 2026-08-31 when the configured URL returned 404. The cause, found now: the index was published by the portfolio site at
vassiliylakhonin.github.io, and that repository no longer exists on GitHub — Pages stopped serving, the index went with it, and the A2A discovery alias on the same domain has been failing ever since (66.7% uptime on the marketplace listing, the only agent below 100%). The upstream was fine; the host was somebody else's. So the build moves in-tree.scripts/sanctions_name_index.pyand the published directorydeploy/snapshot-site/now live here, and the index is served from Cloudflare Pages — the same account that already runs the worker fleet. Rebuilt from the four official sources (OFAC SDN, OFAC consolidated non-SDN, EU consolidated, UK FCDO): 84,367 names, 2.8 MB,application/json. Verified throughupstream_snapshot.jsagainst the published file beforeSNAPSHOT_INDEX_URLwas set —VTB BANKmatcheseu_consolidated_extract,SBERBANK OF RUSSIAandMADURO MOROS, Nicolasmatchofac_sdn_extract, all exact, and an invented company returns nothing. Generated JSON is gitignored: it is a build artifact, not source. Nothing about the profile's claims widens — a match is still a possible string match, still not identity verification or a sanctions determination, and human review is still required. What changes is thatlive_retrieval_statusissuccessinstead ofdisabled, and callers getlive_retrieval_snapshot_generated_atso they can see exactly how fresh the screening was. -
fix(gates): the two decision routes now publish their own request guide, not the verification gate's. The
every request guide now publishes an example the schema it names actually acceptsentry below corrected the examples insideGATE_REQUEST_GUIDES. It deliberately left the call sites alone, and two of them were the same bug one level out:decision_policies_listanddecision_verifyeach passed theagent_output_verificationprofile toinvalidRequestResultbeside its own schema string, so a refused caller was told to readdecision-policies-list-request.schema.jsonordecision-receipt-verify-request.schema.jsonand handed the evidence-audit claims/evidence example — a request the named schema rejects in every field.decision_policies_listwas doubly wrong: it takes no arguments at all, and the example it published was the reason it refused. Each route now has a standalone guide passed asguideOverride, the wayPRE_ACTION_CHECK_GUIDEalready was —DECISION_POLICIES_LIST_GUIDEpublishes the empty request the route accepts,DECISION_VERIFY_GUIDEpublishes a{ receipt, expected_request_hash, expected_action_hash }request and says to compute both hashes locally rather than copying them out of the receipt response. The/v1/agent-output/pre-action-checkbranch of the verification handler was quoting the pre-action schema without passingPRE_ACTION_CHECK_GUIDEand is fixed with them. Guides may now carry an optionalexampleNote, surfaced in the artifact text and asexample_notein the JSON part and task metadata, so an empty example reads as "this route takes no arguments" rather than a truncated payload, and a placeholder receipt says it is one. Additive: the field appears only where a guide sets it. The contract test from the entry below covers both new guides, its hand-rolled validator now implementspattern(the only constraint the verify schema carries beyond its required fields, with a negative case proving it can fail), and a new test reads the Worker source and asserts noinvalidRequestResultorrequestGuidanceResultcall site pairs a guide with a schema that guide does not name — the pairing the declarativeDIRECT_V1_ROUTEScheck could not see. It too has a negative case, because a source scanner that silently matches nothing reports every source clean. Golden and failure cases for both routes over A2A: the refusal carries the right example, and the example it publishes comes back accepted. -
fix(watchman): a sanctions hit is attributed to the list it came from, not to the caller. Measured against a live
moov/watchmanv0.66.0 on 2026-09-04,sourceListcomes back as the snake_case identifiers declared inpkg/search/models.go—us_ofac,us_non_sdn,us_csl,us_fincen_311,us_tel,eu_csl,uk_csl,un_csl. Not one of them was inSOURCE_LIST_TO_SOURCE_TYPE, so every real match fell through the default and an OFAC SDN hit on Nicolas Maduro was returned assource_type: user_provided_note— evidence the caller supposedly wrote, rather than a name on a sanctions list. The existing test did not catch it because its fixture was hand-written in the old grouped shape rather than captured from a running instance; the new test uses a real v0.66.0 payload. The unrecognised-list default is nowotherrather thanuser_provided_note: anything reaching that function came from the upstream, so it is never a caller note — unattributed is honest, misattributed is not. Also documented, in the degraded-status message and the module header, thatWATCHMAN_URLcarries the API version prefix: v0.6x serves/v2/search, so the variable is set tohttps://<host>/v2and a bare host answers 404. No behaviour change whenWATCHMAN_URLis unset — the profile still degrades to user-supplied evidence. -
fix(gates): every request guide now publishes an example the schema it names actually accepts. A gate that refuses a request answers with
GATE_REQUEST_GUIDES: the fields it needs, one worked example, and the schema file to read. That example has to be true on both transports. It was checked on neither — the Worker validates a few enums per gate, never the published schema, so an example could drift from the contract it advertises and every test still passed. Measured 2026-09-04, three had.agent_output_verificationhanded out evidence items of{ evidence_id, title, date }whileevidence-audit.schema.jsonsetsadditionalProperties: falseonevidence_itemand requiressource_type;gulf_maritime_exposurenestedvesselandcargoinside avoyagethat permits neither (both are top-level siblings, and the Worker never read them where the example put them);critical_minerals_due_diligenceput anidon eachsupplied_sourcesentry, which that schema has no property for. All three were accepted over A2A and/v1/...and rejected byservices.audit_claims,gulf_maritime_exposure, andcritical_minerals_due_diligence— so the same published request worked or failed depending on which door the caller used. This is the driftPRE_ACTION_CHECK_GUIDEcarried until 2026-09-02, found on three more gates. Examples corrected, and therequired:lines that described the wrong shape with them. Each guide now carries theschemait is checked against, and a contract test indeploy/cloudflare-worker/test/worker.test.jsreads that file off disk and validates the example against it, so a guide cannot ship without a schema or drift from the one it names. The same test asserts eachDIRECT_V1_ROUTESentry quotes the schema its guide names, and a negative case proves the validator rejects the exact shape that shipped. No response field changed:schemais read only by the test, andrequired_fields/example_requestcarry the corrected content. Theaudit_claimsexample inMCP.mdcarried the same drift plus abrief_idthe root schema forbids, under a "Returnsvalid: true" that was not reachable; corrected totopicand asource_type-bearing evidence item. -
fix(gates): a declared
support_levelis a caller assertion, and the verification gate now scores it as one.agent_output_verificationcomputed readiness from the caller's own declared support level per claim, with nothing required to back it. Measured on 2026-09-04: one claim atsupport_level: "direct"andevidence: []returnedreadiness_score: 100,readiness_label: review_ready,trust_signal: medium— full marks for an empty pack, from the gate whose stated job is checking that claims are backed. A level now counts only where the claim cites anevidence_idpresent in the supplied evidence. An uncited level weighs nothing in the score; a claim set where nothing is corroborated returnsinsufficient_information/readiness_score: 0/trust_signal: unknowninstead of a scored verdict; and one uncorroborated claim among corroborated ones holds the score below thereview_readyband and names the claim inevidence_gapsandowner_actions.allow_relayis unchanged — it already required every claim grounded by a quote in supplied evidence — and so is every one of the twentypre-action-checkreplay cases. No new response fields: the v1 shape is unchanged under the ADR 0003 freeze, and theverdictandreadiness_scoredescriptions now state the corroboration rule. Python and Worker carry the same rule, with contract tests on both sides. -
feat(gates): with that fixed, the first pass extends to
agent_output_verificationtoo. It was one of the two gates held out of the minimal-request first pass below, on the measurement that a defaultedevidence: []returned readiness 100 /review_ready. That is no longer what it returns, so the gate takes the pass through the same mechanism the others share: a non-empty claim set is the subject, the evidence pack is the one defaulted field, and the artifact discloses it in the same block as the score. A caller who sends claims and no evidence getsinsufficient_informationand the list of claims that cite nothing, rather than the request guide.pre_action_checkstays held out: it requiresrisk_tier, and defaulting a risk classification would invent the one judgement that gate carries. -
feat(gates): the first pass extends to every gate whose scorers stay honest without evidence. The CIS gate now shares one mechanism —
completeMinimalRequestplusminimalRequestFromCandidates— withagentic_interaction_trust,gulf_maritime_exposure,kazakhstan_market_entry_readiness,critical_minerals_due_diligence, anddual_use_technology_export. Each spec names the subject the caller must have sent and defaults only the evidence and framing around it, and every one was measured with an empty pack before being wired: agentic returnstrust_signal: unknown, gulfexposure_signal: unknown, market entryreadiness_label: insufficient_information, mineralsrisk_signal: unknownwithoperational_decision.decision: request_evidence, and dual-usenot_decision_readywithNo dated supporting sources were suppliedstated in its risk vectors. Disclosure is one shared block appended at the artifact call site, the wayengagementMarkdownalready is, so all six gates read alike. Two are held out, on evidence rather than taste.agent_output_verificationscores readiness from the caller's own declaredsupport_levelper claim, so defaultingevidenceto[]returnedreadiness_score: 100/review_readyfor a request that supplied no evidence — measured, and the exact invention this pass exists to prevent; a caller can still sendevidence: []deliberately, but it must not become the silent default.pre_action_checkrequiresrisk_tier, and defaulting a risk classification would invent the one judgement that gate carries.critical_minerals_due_diligencehas nootherin itsdecision_stageenum, so its default ispre_offtake_agreement— whatcriticalMineralsResultalready fell back to silently, now stated in the artifact. Empty requests are unchanged everywhere and still answerTASK_STATE_INPUT_REQUIRED. -
feat(cis): a named counterparty with no evidence pack gets a first pass instead of a refusal. ADR 0026 draws its line at a caller who sent nothing, and answers them with the request guide. A caller who sent
counterparty.nameandcounterparty.jurisdictionand no evidence was landing on that same path, becauseisCisSecondarySanctionsRequestrequires all five top-level fields at once. That caller sent the subject of the review; the gate could already answer them truthfully and did not. The scorers handle an empty evidence pack honestly on their own —cisExposureSignalreturnsunknownwith zero dated sources,cisTriageRecommendationreturnsinsufficient_information, andcisDecisionReadinessreturns0. So the A2A and/v1/cis-secondary-sanctions/exposureextractor now takes a second pass after the strict shape has been ruled out everywhere: a named counterparty is completed with defaults and run. Nothing is invented — the response still reports signalunknown, recommendationinsufficient_information, readiness0/100,supplied_sources: [], and the five source types the caller has to bring back.exposure_facetscarriesminItems: 1, so the completion cannot leave it empty; it defaults toownership_or_control, the one facet that applies to every counterparty, and the artifact text names all four defaulted fields in the same block as the score, so a defaulted facet is never read as a finding about a real company. An empty request is unchanged and still answersTASK_STATE_INPUT_REQUIRED; a request that names a counterparty and carries a bad enum is unchanged and still answersTASK_STATE_FAILED. The completion marker is aSymbol, so it cannot reach the wire. The Python service is deliberately not mirrored:cis_secondary_sanctions_exposurevalidates againstcis-secondary-sanctions-request.schema.jsonand stays strict for embedders. Completion belongs at the hosted edge, which is where strangers arrive — and the completed request validates against that same v1 schema, so what reaches the service is unchanged in kind. -
fix(mcp): the endpoint answers a non-POST with
405, not404./mcpwas routed for POST only, so every other method fell through to the catch-all. The endpoint is advertised asstreamable-http, a transport whose client may open the stream with GET, and404does not say "wrong method" — it says there is no MCP server at this address. Measured over the 24h to 2026-09-03: 148 GET and 9 HEAD on/mcpacross the fleet, every one a 404, fromio.verifymcp,mcp-scraper(mcp-cloud.ai),AIVE-MCP-EndpointProbe,reliability-bureau-spikeandSentinelOracle— registries and monitors deciding whether to list the endpoint. 115 of them sentAccept: text/event-stream, so they were opening the transport, not guessing at a URL. Now405withAllow: POST, which is whatvizieralready answered. -
feat(discovery): the corpus is now searched exhaustively, and only the judgement is left to a model.
check_evidence_packetreads the sources a claim already names, so everything upstream of it rests on whoever assignedsource_ids. On a handful of documents that is a person reading. On four hundred it is a model guessing, and the two failures it produces are indistinguishable in the output: a claim whose real support sits in an undeclared document comes backpacket_incomplete, and a claim pointed at the wrong document comes backsource_review_requiredwith weak lexical support and no reason.agenda-intelligence discoverderives literal patterns from each claim — numbers and quoted spans first, then content terms rarest-first by document frequency — and matches every one against every source, reporting the line that matched. Nothing is sampled and no model is called, so the behaviour is the same on 40 sources and on 4,000; a 401-source corpus is pinned by a test. Two fields carry the finding:undeclared_candidates, sources a claim's own figures reach but it does not cite, anddeclared_without_match, sources it cites where not one pattern occurs.--strictexits non-zero on the second. -
docs(discovery): a candidate is a place to look, and the tests hold it to that.
discovery_statusis the constantcandidates_only, and the findings carry no field named for a verdict. Two limits are pinned rather than described: a supporting source sharing no token with the claim does not appear at all, and a source that denies the claim scores within a hair of one that supports it — both spellings share the same literals. Polarity ischeck_evidence_packet's job, against the source a reviewer accepted. Reading a high candidate as support gets that case exactly backwards, which is why the score is documented as an ordering and never as a probability. -
test(worker):
npm run verify:decision-gateplays the enforcing caller against the live Gate. Every existing test of the signed Gate signs and verifies with the same JavaScript, so none of them can see the only failure this binding has — the two parties disagreeing. This one computes the hashes withagenda_intelligence.canonical, which shares no code with the Worker, and completesdecision_check → decision_verifyagainst production. The binding itself held: independent hashes agreed, the receipt verified against the published JWKS rather than the key that signed it,gate_passedcame back true, and all three refusals — changed action, non-continuereceipt, malformed token — answered correctly. 17 checks. The four failures were all in front of it, in what a caller reads before it sends anything. -
fix(worker): the Gate's own example could not reach the decision the Gate exists to produce. A claim counts as grounded only if it carries
supporting_quotes, and the decision iscontinueonly if every claim is grounded. The advertisedexample_requesthad none, so it returnedrequest_evidenceevery time: the one example the Gate published demonstrated only its negative path, and a caller following it never sawgate_passed: true. Its evidence was also invalid against the schema published beside it —titleanddatewhere$defs.evidence_itemsetsadditionalProperties: falseand requiressource_type— and the guide named three risk tiers where the gate accepts four. The 2026-08-28 comment above it already warned that handing a caller the wrong example hands them a request this gate rejects; the evidence half stayed wrong anyway. Four regression tests, verified to fail against the previous code. -
fix(worker):
input_schemapointed at a GitHub HTML page.decision_policies_listpublished a/blob/URL as the caller's input schema. Fetching it returnstext/html, so a caller that does what the field says cannot parse what comes back. Now the raw URL. -
feat(worker): the published binding states the Unicode normal form it does not apply.
canonicalization: "RFC8785-JCS"is not enough to reimplement: JCS canonicalizes structure, not text, so two conformant implementations still disagree when the same name arrives decomposed. The binding now carriesunicode_normalization: "none", which is what the Gate actually does, and leaves the caller to settle its own text before hashing rather than discovering the rule throughbinding_mismatch. -
feat(cli):
decision-hashes -reads stdin. An enforcing caller holds the request in memory and had to write it to disk to hash it. -
feat(canonical): a Python caller can now compute the Gate hashes it is required to compute. ADR 0025 tells an enforcing caller to derive
expected_request_hashandexpected_action_hashfrom its own copy of the request rather than echoing whatdecision_checkreturned, anddecision_policies_listpublishescanonicalization: "RFC8785-JCS"— but this package shipped no JCS. The nearest thing,services._input_digest, isjson.dumps(sort_keys=True)over a different field (run_provenance.input_digest), and it disagrees with the Worker on 3 of 11 probe cases: it renders9.0as9.0where ECMAScript renders9,-0.0as-0.0where ECMAScript renders0, and a 22-digit integer in full where ECMAScript renders1e+22. A caller that reached for it would pass on ASCII integers and getbinding_mismatchon the first whole-number float — a ratio or threshold that landed exactly on an integer — with the Gate refusing a legitimate action and no field saying why.agenda_intelligence.canonicalreproducesjcs()fromdeploy/cloudflare-worker/src/jws.jsbyte for byte, including the two rules Python gets wrong by default: ECMAScript number rendering, and key order by UTF-16 code unit rather than code point, which differ for any astral key. 600 randomized structures and 31 boundary numbers agree with Node;tests/fixtures/jcs-parity.jsonfreezes 19 named cases and regenerates from the Worker under test, so drift injws.jsfails here instead of in production. Verified end to end: a receipt signed by the Worker over a request carryingthreshold: 9.0verifiesgate_passed: trueagainst hashes computed byagenda-intelligence decision-hashes. -
docs(canonical): JCS canonicalizes structure, not text, and the tests say so. RFC 8785 does not normalize Unicode, so
Айдын Жумабайin NFD hashes differently from the same name in NFC and the Gate answersbinding_mismatchfor what a reader calls one request. Decomposed text reaches a caller by ordinary routes — macOS paths, clipboard, some IMEs — and this product's regions are exactly the ones where it is not ASCII. Normalizing inside the canonicalizer would break parity with the Worker, so the limit is pinned byTestUnicodeNormalizationIsTheCallersJoband answered with an explicit--normalize nfcon the CLI that both parties must choose together. -
fix(a2a): an empty message asks for input on every gate, not eight of ten. ADR 0026 enumerated the eight
Missing structured …call sites and moved them toTASK_STATE_INPUT_REQUIRED. The sharedemptyRequestResultpath was not among them, soagendaandkazakhstanstill answered a request with nothing in it — case 1 in that ADR, "an empty message" included — withTASK_STATE_FAILED. Swept the live fleet 2026-09-02: those two of ten. Both now ask for input, which also moves them out ofinvalid_requestin/stats. -
fix(mcp): the front door's schema now says it answers without a question.
corridor_sanctions_assistantdeclaredtextrequired andadditionalProperties: falsewhile answering{text: 12345},{text: null}and{nope: "…"}alike with the gate list; its siblingstrategic_risk_triage, generated from the same branch, refuses all three. Declared the permissive behaviour rather than tightening it: every other gate's refusal now routes an empty-handed caller here, so this is the one tool that must not turn one away. -
test(worker):
npm run verify:refusalssweeps the refusal paths across the live fleet.verify:public-agentsproves a gate answers a request it accepts; this proves what all ten do with the requests they do not — empty call, wrong-shaped object, unknown tool — plus the round trip that takesexample_requestout of a gate's own refusal and sends it back. 130 checks. Both fixes above came out of its first run. -
docs(mcp): tool descriptions now state the precondition, not just the promise. Every gate summary said what comes back — "returns ... missing evidence", "... evidence gaps" — and none said the caller has to bring its own evidence first, which each of them requires. An agent reading that while holding only a question concluded it could ask what it was missing, called, and was refused. The ten tools that grade caller-supplied evidence now say so and name
corridor_sanctions_assistantas the place to start with a question and nothing else; the two free-text tools and the two that grade no evidence (decision_policies_list,decision_verify) are unchanged. Descriptions only — no schema, contract, or behaviour change. -
fix(mcp): an empty
tools/callis an error, and every refusal names its arguments. A2A distinguishes "done", "broken" and "I need input you have not sent"; MCP has onlyisError, and the gates that answeredTASK_STATE_INPUT_REQUIREDcrossed into MCP asisError: false— telling a machine caller its empty request had worked, the failure the A2A-side fix of 2026-08-25 set out to stop. Seven gates did this.INPUT_REQUIREDnow surfaces as an MCP error carrying the same field guide, under its own code so that sending nothing stays distinguishable from sending something broken. The free-text profile kept its guide only inside the artifact and so refused with no field named at all; it now names its onetextargument. A2A behaviour, task states, and usage classification are unchanged, and no gate accepts or refuses anything it did not before. -
fix(mcp): a
tools/callrefusal now carries the field guide, not just a sentence. A caller that sent the wrong arguments got back only "The supplied arguments do not satisfy this tool's input contract" — no field named, no example, nothing to retry against. The refusal already builtrequired_fields, a ready-to-send example, the routing front door and a support contact, and the A2A route returned all of it; the MCP layer forwardedmetadata.errorsalone and dropped the rest. It now forwards them, and because the example is a bare arguments object a caller can resend it unchanged. The refusal also no longer namesparams.message.parts, which is the A2A request path and does not exist in an MCPtools/call. No contract changed: every gate accepts and refuses exactly what it did before. -
fix(cis-secondary-sanctions): report an unconfigured retrieval upstream as disabled, not degraded. The dispatcher no longer invokes the keyless OpenSanctions adapter when Snapshot, Watchman, and OpenSanctions are all unconfigured. Evidence-only requests now emit
live_retrieval_status: "disabled"with the bounded operator reasonnot_configured, make no outbound request, and attach no upstream attribution. A configured upstream that fails still emitsdegradedwith its bounded failure reason. -
feat(observability): separate human, machine, probe, and self-test traffic in Worker logs and
/stats. Usage and funnel events now carry boundedtraffic_classandrequest_kindfields, so discovery traffic, A2A actions, and MCP actions can be counted without re-parsing user agents and paths. Daily stats expose the same split and direct human/machine counters. Live-retrieval failures now carry an aggregate-safereason_code(for examplenetwork_errororupstream_http_503) while raw exception and configuration detail remains out of logs and user-facing limitations. -
fix(a2a): answer an unstructured gate request with
TASK_STATE_INPUT_REQUIRED, notTASK_STATE_FAILED. Measured 2026-08-29 over the preceding 72h of Workers Logs: the Agenstry listing probe calls all ten hosted agents with the same four-character message; the three free-text profiles answeredTASK_STATE_COMPLETEDand the seven structured gates answeredTASK_STATE_FAILED— the same seven every time, 14 of 38 probe calls. Nothing was failing. Each gate was describing its input contract through a status that means the opposite, on the one external channel that shows the fleet to people who did not build it. A caller who sends no structured request now getsTASK_STATE_INPUT_REQUIREDwith the unchangedGATE_REQUEST_GUIDESartifact — required fields, a worked example, the front door. A caller who sends a structured request that does not validate still getsTASK_STATE_FAILEDwith the field errors, because that request did fail./statsreports the new outcome asinput_requiredrather than folding it intoinvalid_request, which on 2026-08-27 counted 271 calls that were mostly one local test script. Both still count towardempty_handed. See ADR 0026. The Python A2A adapter is unchanged and still returnsTASK_STATE_FAILEDfor both cases. -
chore(observability): sample traces on
cis-secondary-sanctions. Over 2026-08-22..28 that Worker was 12.4% of named-script requests but 47.4% of the fleet's CPU, withcpuTimeP99423ms against a 1.27ms median, and it is the only agent reporting subrequests (49; every other agent reports 0). The tail is an outbound-call path, not computation. Logs stay unsampled fleet-wide: ~5,900 requests a week is nowhere near the free 200k/day budget, and thinning them would cost the funnel its census.
1.8.0 — 2026-08-28
-
feat(registry): declare the ten hosted endpoints in
server.json. The registry entry offered exactly one way to reach this project — install the PyPI package and speak stdio — while ten Streamable HTTP endpoints were live, open, and answeringtools/listwith complete input and output schemas. An agent browsing the registry saw software to install, not endpoints it could call. Measured the same day in the Agenstry directory: 4–5 listing impressions per gate, zero invocations.remotes[]now names all ten, general profile first, andwebsiteUrlpoints at the hosted landing page.tests/test_server_manifest.pychecks both directions offline againstwrangler.toml: no declared URL that no deployment serves, and no deployed Worker the manifest forgets. The release workflow syncs versions only, so it needs no change. -
chore(signals): re-sync the vendored snapshot with the canon, and translate the links vendoring breaks. The snapshot was three signals behind
global-think-tank-analyst— the guard that should have said so had been looking for the checkout in the wrong place — and it carried the disclaimer removal that the canon has since reverted.scripts/sync_signals.pynow also rewrites repository-relative links (../../README.md) to their canonical URL: they resolve in the canon, where signals sit two levels below the repository root, and point at nothing five levels down inside this package.feed.jsonembeds a copy of each signal, so itscontent_textis re-derived from the rewritten markdown rather than left to contradict it. -
fix(opensanctions): never fabricate a sanctions match when the API key is missing. The Python adapter now follows its documented degradation contract and returns an empty match list. A regression test calls the adapter directly so future callers cannot mistake simulated data for an upstream result.
-
fix(docs-smoke): execute allowlisted documentation commands without a shell. Markdown examples are parsed with
shlexand passed as argument lists, removing the avoidableshell=Truesurface. -
docs(demos): replace infinite-scale, staffing, and invented-price claims with a bounded concurrency example whose output is explicitly one observed run. Removed the generated 100-agent catalog because its inactive entries and pricing could be mistaken for shipped capabilities.
-
docs(economics): replace invented pricing, margin, labour, latency, and error-rate figures with a measurement plan and explicit evidence threshold.
-
docs(scenarios): relabel fabricated enterprise case studies as synthetic workflow scenarios and remove invented customer volumes and outcomes.
-
fix(docs,skills): restore the honest-scope layer removed in 9a7d32e. That commit stripped "not legal advice" and "not compliance advice" from
okf/index.md, the sanctions sector reference, andskills/source-ingest/SKILL.md, removed the limitation-note requirement the memo contract depends on, deleted the## Disclaimerblock from every published signal, dropped theLimitationssections from all three agent-eval cases, and removed theHonest scoperubric row that scored exactly this. The runtime boundary never moved — live workers still returnhuman_review_requiredandnot_advice_notice— so what was left was a code boundary with no documentation behind it and, in the skills, runtime instructions that no longer ask for the caveat the contract still requires. The CHANGELOG's[2.0.0] Autonomous Compliance Editionblock, which announced definitive legal, compliance, and sanctions determinations, is removed with it: the product does not do that, and AGENTS.md forbids claiming it. -
fix(tooling): make the signal-sync guard find the GTTA checkout.
scripts/sync_signals.pyandtests/test_signal_sync.pyeach hard-coded~/work/global-think-tank-analyst. The checkout moved to~/projects, so the script failed loudly and the test — which skips when the source is absent — went quiet, and stayed quiet through a sweep that edited the vendored snapshot directly. The path is now resolved once, in the script, from$GTTA_SIGNALSor a checkout beside this repository or under~/work/~/projects; the test imports that resolver instead of repeating it. With the guard live again it immediately reports the snapshot is three signals behind canon. -
test(worker): verify all ten deployed profiles, not eight.
critical-minerals-due-diligenceanddual-use-technology-exportwere live and checked by nothing —verify:public-agentshad never called either. Adds the first public example for the dual-use profile (examples/dual-use-technology-export/contract/), a contract test asserting the profile still gives that example the answer its response fixture publishes, and both profiles to the live conformance run. -
ops(worker): rotate
STATS_TOKENacross every environment, not just the top-level Worker.wrangler secret put STATS_TOKENwithout--envreaches one Worker; the other nine answered/statswith 401 and nothing reported it, because/statsis the one endpoint no monitor calls. Observed 2026-08-28, four environments behind.scripts/rotate-stats-token.jsreads the environment list fromwrangler.toml, writes the secret everywhere, rewrites only theSTATS_TOKENline of.env(the previous helper truncated the file and tookAGENDA_OBSERVABILITY_TOKENwith it), and re-publishes throughdeploy:all, since a secret write leaves an unstamped version and drops the gated environment's ALLOW receipt.--checkasks every environment and writes nothing. -
feat(worker): the agent card now carries the same tool contracts
tools/listcarries. Every hosted MCP tool has published a complete input and output JSON Schema since the endpoint shipped; the card publishedinputModes, so an agent that found a gate through its card learned that it accepts JSON and nothing about which JSON. Composing against a gate meant reading prose or speaking MCP first.capabilities.extensions[].params.x_tool_contractsnow carries the schemas and annotations, read frommcpToolsForProfilerather than restated, so a schema change lands on both surfaces or on neither. It sits in the vendor extension because the A2A v1AgentSkillfield set is closed. Cards get heavier:agent-output-verification, with five tools, goes from ~8.6 kB to ~35 kB. -
feat(deploy): every environment ships through the Vizier gate, not one of ten. Nine environments went out with a plain
wrangler deployand left no receipt, so the question the gate exists to answer had an answer for one tenth of the fleet — while the gate cost the tenth environment about twenty seconds and refused nothing in two weeks.vizier-gated-deploy.jsnow takes--env <name>or--top-leveland derives both the Vizier action target and the wrangler invocation fromwrangler.toml, so the request names the worker the deploy actually ships; an environment the file does not declare is refused rather than silently defaulted.deploy:all --checkasks every environment for a receipt. Until the first full gated deploy, it reports nine asUNGATEDand exits non-zero, which is the true state of the fleet. -
feat(worker): every gate response says whether anything verified it. Agent Output Verification and the Agentic Interaction Trust Gate are deployments beside the other gates, not a step between them and the caller, and nothing in a response distinguished "verified" from "nobody looked" — so a relayed verdict carried the same weight either way.
task.metadata.verificationnow reportsnot_performedfor the nine gates that cannot check their own output andselffor the verifier's own deployment, names where verification is available, and states that the gate issues no receipt, holds no authority, and performs no action. Self-reported, and it names no outcome. It sits in task metadata because every v1 response schema isadditionalProperties: falseand this describes the transport, not the verdict. -
feat(worker): a decision journal, so two runs of one file can be compared.
/statsanswers how many calls and from where; it keeps no input and no verdict, and the detailed funnel events live in Workers Logs, which retains 72 hours on the free plan — so "did this file get a different answer than last time" had nowhere to look.GET /decisions?date=(samex-stats-token, 30-day retention) returns one record perSendMessage: timestamp, profile, contract version, asha256:hash of the input, the verdict, and whether human review was required. It stores a hash, never the input: these payloads carry counterparty names, routes and cargo. Therunsblock pairs a repeated input with the verdicts it received and marks the pair changed when they differ, including when only the contract version moved.npm run decisionsprints the changed pairs first. One KV write per call, none on discovery GETs. -
fix(worker): route the Dual-Use Technology deployment to its declared profile. The environment, profile registry, MCP schema, and deployment existed, but the Worker host/env dispatcher fell through to the generic Agenda Intelligence card and response path. The deployment now serves its own A2A Agent Card, structured evidence-readiness response, request guidance, and MCP/A2A routing while retaining mandatory human review and explicit no-classification/no-clearance boundaries.
1.7.1 — 2026-08-27
- feat(workers): Edge REST routes, streamable MCP resources & prompts, and critical minerals vertical worker.
- Direct REST validation endpoints on Cloudflare Workers:
POST /v1/evidence-packet/check,POST /v1/evidence-packet/repair-prompt,POST /v1/critical-minerals/due-diligence. - Remote Streamable HTTP MCP JSON-RPC transport extended with
resources/list,resources/read,prompts/list,prompts/get. - Added sixth vertical gate profile:
critical_minerals_due_diligencefor origin tracing, export quota compliance (rare earths, graphite, gallium, germanium, tungsten), and CSDDD alignment.
- Direct REST validation endpoints on Cloudflare Workers:
1.7.0 — 2026-08-27
-
feat(review): interactive standalone HTML report (
--format html).agenda-intelligence reviewnow supports--format html, generating a self-contained, offline HTML report with status badges, interactive claim-to-source highlighting, clickable reviewer action checkboxes, and dark/light mode responsiveness. -
feat(ingestion): native CSV/TSV table parsing, local HTML stripping, and scanned PDF layer detection.
evidence_reviewnatively parses.csvand.tsvtabular sources into readable records, cleans tags and scripts from local.html/.htmdocuments, and explicitly warns when a PDF has no extractable text layer (OCR required). -
feat(mcp): native MCP resources and prompt templates. Implements
resources/list,resources/read(agenda://manifest,agenda://protocol/core,agenda://schemas/v1/...) andprompts/list,prompts/get(draft_evidence_memo,self_correct_packet,audit_evidence_claims) in the stdio MCP server. -
feat(services): enhanced quote matching with ellipsis and typographical normalization.
check_evidence_packet,grounded_check, andverify_quotesnow support ellipsis (...,…) in quoted excerpts to match non-contiguous verbatim passages in order, and normalize typographical quotes (“”«»‘’), dashes, and unicode whitespace. -
feat(services/cli/mcp): self-correction repair prompt generation for LLM agents. Adds
build_repair_promptservice function,agenda-intelligence repair-promptCLI command, andgenerate_repair_promptMCP tool. Inspects claim diagnostics (missing sources, misquotes, unmatched numbers, polarity/negation mismatches, weak lexical support) and formats structured markdown guidance for agent retries. -
feat(integrations): EvidencePacketGuardrail for agent pipelines. Adds
src/agenda_intelligence/integrations.pyproviding a lightweight, zero-dependency guardrail and automatedvalidate_or_repairfeedback loop for LangChain, LlamaIndex, CrewAI, DSPy, and custom agent loops. -
feat(ci): GitHub Action (
action.yml) for evidence linting. Adds a composite GitHub Action definition allowing CI workflows to validate evidence packets or run local document reviews directly viauses: vassiliylakhonin/agenda-intelligence-md@main. -
fix(tests): isolate PYTHONPATH in subprocess calls in
test_lens_packs.py. -
fix(worker): the deal-risk gate no longer contradicts the subject line two rows above it. Measured live on the Middle Corridor gate right after #266 deployed: "Aluminium extrusions from Aktau to Jebel Ali via Baku and Poti" produced a subject line naming all four places and a cargo class, and directly beneath it
Route: not suppliedandCargo: not supplied. The gate's extractors only fire on the schema's own vocabulary (aRoute:label, or the literal word "route"), so ordinary English missed them; the defect predates #266, which made it visible by printing what had in fact been read. Route extraction now falls back to afrom X to Ycapture and then to the named places in written order, and cargo to the commodity class, each labelled as read from the wording rather than supplied as a field. Thefrom X to Ycapture is dropped when it overruns into a party, payment or valuation clause — on the live example it had swallowed "buyer is a UAE company incorporated in 2025, payment through a Georgian bank" into the route. Place names are matched from a route vocabulary kept separate from the jurisdiction table, which collapses Baku into Azerbaijan and is right to. -
fix(worker): drop the duplicated source-category checklist from the routing note. All six categories under "Collect next" were repeated verbatim under "Full source-category checklist" — 1,059 bytes of a 7,442-byte note restating what the caller had just read. The complete list stays in the machine-readable part under
signal_screen.source_categories_required. -
fix(worker): answer the caller's question before describing the server (#266). Missing from this file when that PR merged; recorded here. A replayed external-shaped call naming a UAE counterparty, Fujairah, refined products and Kazakhstan transit came back with none of those words: the note opened with "live wrapper is responding" and
pip install, reached the subject on line 12, and gave five copies of "No caller-supplied evidence in this live A2A request". Over the preceding 30 days ten external calls carried a real prompt, from three callers, and none returned after their first day. The note now opens with what was read, then the named regimes and lists that apply to it, one decision-relevant fact per named port, and what to collect with what each item settles; packaging moved to the bottom. Correction to that PR's own claim: the note grew, 5,586 to 7,442 bytes (7,036 after the checklist above came out) — the original "20,864 to ~7,400" compared a whole JSON body against a single text part and was wrong in both size and direction. What changed is the order and the content, not the length. -
fix(worker): the deal-risk gate names its own missing sources in the offer. Found live after the previous change deployed, not in review. The Middle Corridor deal-risk gate — the busiest host in the funnel — answered
escalate_before_signaturewith seven named gaps and still returned the generic sentence, because it names them inminimum_sources_before_goandmissing_sources, neither of which the first version ofENGAGEMENT_OPEN_ITEM_FIELDSknew. Both are added, and the list is now ordered from the narrowest reading of "still missing" to the broadest, since the first field with entries wins. A regression test asserts the gate's verdict and one of its own missing sources reach the offer, and fails without the fix. -
feat(worker): offer person-led work on the caller's own open items, on every completed profile. The contact reached the failure paths and, from #262, the base profile's routing note. It never reached the seven vertical gates, and everywhere it appeared it was the same generic sentence. Measured over the 2026-08-18..26 archive: twelve substantive external calls from a single caller, every one
TASK_STATE_COMPLETED, no reply — whileinvalidRequestResultand the "nothing to route" path, which nobody whose request works ever sees, carried a contact throughout. The offer is now built atrunProfileRequest, the one point every profile passes through, so a new profile cannot ship without it, and it names this run's own verdict and the items its file is still short of (minimum_sources_before_review,minimum_sources_before_action,evidence_gaps,blocking_gaps,owner_actions, found at the top of the response or one level down undersignal_screen). Two results are left untouched: aTASK_STATE_FAILEDtask, which already carriessupport_contactand needs its request fixed rather than a scoping conversation, and any result that already carries an engagement — the base profile's routing note and the corridor assistant's orientation payload. No new response field and no schema change:metadata.engagementis the block #262 already defined, and the markdown gains the same lines it already gained there. No price and no traction claim. Three contract tests cover a golden gate response, a rejected request, and double-stamping; reverting the offer to a generic sentence fails two of them. -
fix(cis): stop reporting a listed ship as a match on the counterparty. OFAC SDN carries
NURSULTAN NAZARBAYEVas aVessel— IMO 9842217, linked to Joint Stock Company Rosnefteflot, designated under EO 14024. It is a Russian supply vessel named after a former head of state, not the person. Two defects turned that into a wrong statement in the gate's output. The Snapshot upstream hardcodedschema: "Company"on every match, so a designated person, a company, a ship and an aircraft were reported identically; andcisTopExposureDimensionsturned any match count above zero intodirect or near-direct match in OpenSanctions consolidated dataset, which both overstated what matched and misattributed provenance whenever Snapshot or Watchman was the active upstream.upstream_snapshot.jsnow reads the entity type published in compact index v2 (typestable plus a third element per row, added by the portfolio site'sscripts/sanctions_name_index.py) and maps it onto the FollowTheMoney vocabulary the other upstreams already return —individual→Person,entity→Company,vessel→Vessel,aircraft→Airplane. A v1 index has no types; those rows resolve tounknown/LegalEntityrather than being dressed up as companies. The type travels to the caller on bothmatch.schemaand a newentity_typeon eachauto_fetched_sourcesentry, and the dimension now separates a match on something that could be the counterparty from a listing on a vessel or aircraft carrying the same name, naming the datasets that actually answered. Mirrored inservices.pyfor parity, where OpenSanctions matches are classified from the schema the API returns. Risk thresholds are deliberately unchanged: a vessel listing still contributes to the exposure signal exactly as before, because whether it should is a policy decision, not a defect. Contract tests both sides: vessel / company / individual typing, v1 fallback without guessing, the vessel-only dimension, the company-match positive control, and upstream labelling. No schema, endpoint, profile, or tool changed. -
feat(hosted decision gate): sign and verify exact-request readiness receipts. The existing
pre_action_checkalready returnedcontinue,request_evidence,require_approval, orstop, but itsdecision_idwas only a correlation identifier and a downstream machine could not verify that the result was current or bound to the action it was about to perform. The Agent Output Verification Worker now adds three hosted MCP tools:decision_policies_list,decision_check, anddecision_verify.decision_checkattaches a five-minute ES256 compact-JWS receipt containing no claim text, only decision metadata and SHA-256 hashes of the full request and action identity;decision_verifyfails closed for a bad signature, expiry, hash mismatch, or any decision other thancontinue. The receipt reuses the profile's existing Agent Card P-256 key with a distinct JWS type for this initial bounded scope. It proves the Worker's readiness result, not identity, delegated authority, factual truth, external approval, legal clearance, or authorization. No new Worker, storage, payment, policy pack, A2A response, local stdio tool, or external action executor is added.
1.6.0 — 2026-08-24
-
fix(hosted MCP): publish complete contracts and stop duplicating A2A tasks in model context. Hosted
tools/listpreviously described every structured request as an open{request: object}shell, omittedoutputSchemaand behavior annotations, andtools/callserialized the full A2A task twice: pretty-printed incontentand again instructuredContent. A local Middle Corridor fixture measured 91,861 bytes for one MCP response. The Worker now generates complete input and output schemas from the versionedschemas/v1contracts, accepts the request object directly while preserving the old wrapper and its A2A task-shaped result as a compatibility shim, advertises read-only/non-destructive/idempotent hints, and returns the service result once plus a short summary for direct-schema calls. The same fixture is contract-tested below 15,000 bytes. A generation-drift check runs before the Worker tests, and browser preflight now permits the MCP 2026-07-28Mcp-MethodandMcp-Namerouting headers. A2A response shapes and existing tool names are unchanged. The A2A 1.0 live fixture also now usesSendMessageand includes the requiredmessageId; it previously combined legacymessage/sendwith an A2A 1.0 header in live use. -
fix(release): align the Cloudflare Worker version with the Python release. The live Workers and Worker source still reported
1.2.0while PyPI and the repository reported1.5.0. The Worker now reports1.6.0, its contract tests are updated, and the Python version-sync test covers the Worker constant so the two release surfaces cannot drift silently again. This changes version metadata only; the local-file review command remains Python/CLI-only. -
feat(evidence review): add a bounded local-file review workflow and Unicode lexical support.
agenda-intelligence review <manifest>now loads caller-selected UTF-8, Markdown, DOCX, or optional PDF sources, hydrates the stable evidence-packet request, and returns a reviewer-facing Markdown or JSON result without repeating full source text. Paths stay inside the manifest directory; source size, extracted text, and PDF page count are bounded. The deterministic tokenizer now retains Unicode words instead of silently dropping Cyrillic and Arabic text, preserves numeric percentages, and checks common English, Russian, and Arabic negation cues. Exact-match Cyrillic and Arabic fixtures and a Russian polarity-conflict fixture pin the behavior. This is not claim extraction, translation, semantic entailment, source discovery, or factual verification; those limits remain visible in every result and human review remains required. -
fix(skill packaging): ship and validate the complete
source-ingestcontract. The plugin exposed the skill, and packagedllms.txtadvertised it, but the Python package data carried onlyagenda-intelligence; the dual-copy test also checked only that one skill despite the documentedskills/**invariant.source-ingestis now mirrored into package data, every packaged skill is parity-checked, its downstream routes resolve from the skill directory, and its evidence-mode handoff names the exact values accepted by the evidence-pack and agenda-memo schemas. The Claude marketplace description of the sibling Global Think Tank Analyst also drops the unsupporteddecision-gradewording, with a metadata test preventing that grade claim from returning. -
fix(agent card verifier): the live check still read
x_agent_contractfrom the card root. The extension move rewrote everycard?.x_agenda_intelligenceread inverify-agent-card.jsbut missedcard?.x_agent_contract, so after the 2026-08-23 deploy the Middle Corridor card reported three false failures while the card itself validated against the official schema. The unit test that covers this verifier passed throughout, because it handed the verifieragentCard()— the internal shape — instead of what the endpoint serves. It now passes the wire shape, which reproduces the defect when the fix is reverted. -
fix(agent card): the card carried fields the A2A v1 schema does not define. An independent conformance scan published 2026-08-23 (
msavdert/a2a-scorecard, 2,479 endpoints) failed every card this project serves on schema validation, and the finding checks out againsta2aproject/A2Aspecification/a2a.proto:AgentCarddefines a closed field set andAgentProviderexactly two fields,organizationandurl. The Workers were servingsupport,x_agenda_intelligence,x_agent_contractand a top-levelsignatureat the card root plusprovider.legalEntity; the published alias addedremote_mcp,resources,updated_at,x_identity,x_profile_mcp,x_profile_resourcesandx_security_posture, plusprovider.nameandprovider.contact; the Python adapter card addedurl,protocolVersionandprotocolVersions. None of those are card fields, and the one extension mechanism the spec defines iscapabilities.extensions[], whoseparamsis an arbitrary JSON Struct.Everything moves there under
https://agenda-intelligence-a2a.vassiliy-lakhonin.workers.dev/a2a/extensions/agenda-intelligence/v1, declaredrequired: false— no data is dropped and reading it is never needed to call an agent. The signature moves from a top-levelsignaturestring holding a compact detached JWS (<header>..<signature>, RFC 7797 unencoded payload, written for the Agenstryjws_signaturecriterion) tosignatures: [{protected, signature}]with an ordinary base64url-encoded payload, which is what A2A v1 section 8.4.2 specifies; existing signing keys and the JWKS are unaffected. Agenstry's own current criteria point the same way — itsvalid_cardcriterion requires A2A v1.0 schema validation, and its signature criterion names no field — so this is not a trade between the two.Normalisation happens at the wire boundary, so
profiles.js, the Python adapter's callers, the contract tests and every internal reader keep readingcard.x_agenda_intelligenceunchanged; only the served JSON moves. The field list is an allow-list rather than a list of known offenders, so a profile adding a new block stays conformant without touching it. Verified by validating the served cards against the official generateda2a-v1.0.1JSON Schema bundle: 8 of 8 pass, and the same harness fails all three currently-deployed cards with exactly the violations the scan reported.npm run verify:agent-cardnow checks the field set on the live cards, and it reports failure until the Workers are redeployed. Callers reading a card served before the move still resolve, because the extension reader falls back to the card root. 198 worker tests and 538 Python tests green.Not changed: Vizier returns
-32009 VersionNotSupportedto a caller that sends noA2A-Versionheader, which the same scan grades as a non-answering endpoint. A2A v1 section 3.6.1 says an empty header means version 0.3 and section 3.6.2 says an unsupported version must be refused, so that behaviour is correct as written and was left alone. -
feat(worker): give a machine caller a way to reach a person. A successful
message/sendto the base profile returnedagent_card,repository,package,mcp_transport,modules_usedandtriage, and no contact anywhere in the payload (measured 2026-08-22 against the live endpoint). The agent card'ssupportfield and the landing-page mailto do not reach a caller that integrates from code and never renders HTML — and the single external non-probe call on record arrived exactly that way, from another Cloudflare Worker with no user agent, referer or origin, which also makes it unidentifiable from the logs.metadata.engagementnow carriesoffer,contact_email,support_hours,next_stepandhuman_page, matching the block the corridor assistant already returns. No price, no customer claim, no urgency: a contract test fails the build if any appears. Additive metadata only — no schema, endpoint, or artifact change. Zero inbound contact has arrived through it; it is a channel, not a measurement. -
fix(worker telemetry): the two biggest crawlers were counted as unidentified callers.
caller_kindrecognised a probe by keyword only —bot,crawler,probe,auditand so on — and the two highest-volume crawlers against these endpoints name neither a role nor a bot suffix. Measured 2026-08-20..22, 411 requests over three days therefore landed inexternal, the bucket that means "not a probe", 224 of them from one scheduled crawler alone. A probe is now also recognised by the self-identification convention: a parenthesised contact prefixed with+, as in(+https://example.com/bot)or(+someone@example.com). Every crawler in the observed population that the keywords missed carries it. Generic HTTP libraries (node,python-httpx,Go-http-client,undici) stayexternalon purpose —externalmeans unidentified, and collapsing it into "probe" would hide exactly the callers this classification exists to find. -
feat(worker telemetry): name the caller who signs nothing. The usage and funnel events recorded a truncated user agent and nothing else about who called, so a request that sent no user agent at all was indistinguishable from any other automation, and the count of "real" calls silently included directory probes and this repository's own conformance runs. Both events now carry
caller_kind(self_test,service_probe,external,unsigned_external) andcaller_zone, the calling Cloudflare Worker zone from thecf-workerheader./statsreports both, andnpm run funnelprints them. Measured over 12,155 raw log rows for 2026-08-19..22: 50 rows carried acf-workerzone and 49 of those were probes already self-identified in the user agent (ProofBench, mcpqueen-grader, x402-observatory, Cloudflare infrastructure); the fiftieth sent no user agent and was the single external non-probe call in the window. 55 requests arrived unsigned in total. Deliberately narrower than a full caller taxonomy: every probe observed so far names itself, so only the unsigned bucket carries information the user agent did not already give. No schema, endpoint, or response-shape change —event_versionmoves to 3 for usage and 2 for funnel, and nothing reads it. The fields are observability only and are not evidence of demand. Worker deploys are manual, so live environments keep the old event shape until redeployed.
1.5.0 — 2026-08-21
-
feat(evidence-packet): flag claims that negate the source they cite. Lexical support is the share of a claim's content terms found in its named source, and
not/noare stopwords that never reach that ratio — socheck_evidence_packetreturnedpacket_completefor a claim asserting the exact opposite of its own source (measured: claim "The EBRD did not approve the loan facility in March 2024" against source "The EBRD approved the loan facility in March 2024" scoredlexical_support=supported, coverage 0.875). The check now compares negation and denial cues between the claim and its closest sentence in the cited source; a one-sided cue downgradessupportedtoweakand addslexical_support_polarity_mismatchplus a reviewer action. Sentence scope, not the multi-sentence excerpt window, so a negation elsewhere in the same document does not flag an unrelated claim. Both directions are covered: a negated claim against a positive source, and a positive claim against a negated source. Reversed subject/object ("A approved a facility for B" against "B approved a facility for A") remains out of reach for term overlap and is documented as a limit inREADME.md, pinned bytest_polarity_check_does_not_claim_to_catch_reversed_roles. No schema change:lexical_support.statuskeeps its three values and the new string lands in the existing free-formissues[]. Behaviour change for--strictcallers: a packet with a polarity conflict now exits non-zero. The same guard is applied togrounded_check, which carried the identical blind spot: a one-sided cue downgradesgroundedtoweakly_groundedand appends the owner action. 536 tests green. -
fix(worker positioning): remove the stale free-memo promise from the corridor front door. The Corridor & Sanctions Risk Assistant, the three structured gate pointers, and invalid-request guidance now use the current person-led route: send a one-line description of the route or counterparty and the next decision or review; fit, scope, fee, and timing are confirmed before work starts. No price, new product, protocol, schema, or response shape was added. Worker deploys remain manual, so the live cards keep the old copy until the affected environments are redeployed.
-
fix(CIS discovery): remove the published price from the worker service text. The agent-card description, the skill-list entry, and the corridor-assistant intake notice carried a USD 99 returned-file pilot price. They now state the pricing shape only: one fixed fee per file, agreed before work starts, with scope, fee and timing confirmed within one business day. Mirrors the site removal of 2026-08-19. Worker deploys are manual, so the live card keeps the old text until it is redeployed.
-
fix(CIS discovery): align the public Worker metadata with the paid file-preparation intake. The CIS card and MCP summary now route exporters, importers, traders, freight forwarders, and finance leads who own the file to the redacted intake. The public description no longer targets institutional compliance teams, advertises a free pre-deal memo, or leads with the internal readiness score. The structured API contract and response are unchanged.
-
fix(deploy): a manual deploy loop overwrote two Vizier-gated deployments. On 2026-08-14 the
agent-output-verificationworker was shipped four times: the protected workflow deployed it at 05:23:51 and 05:43:30, each carrying an ALLOW receipt, and a hand-rolled "deploy all eight" loop overwrote both at 05:25:20 and 05:44:29 with plainwrangler deploy --env. Same commit, so the running code never diverged — but the live version lost its receipt, which is the whole reason the gate exists. The trail was restored by dispatching the workflow (vrf_6bf1ffee-29d8-4566-b2ff-2e9b3e75039f).npm run deploy:allnow ships the seven ungated envs plainly and routesagent-output-verificationthroughdeploy:agent-output-verification:gated, refusing to fall back to a direct deploy if the gate declines. It finishes by reading the live deployment list and failing when the newest deployment has no receipt — detection rather than prevention, since wrangler remains callable directly, but the drift is then reported rather than silent.The receipt check reads only the final block of
wrangler deployments list: a receipt earlier in the list is exactly the overwritten case, so scanning the whole output would have reported success on the drifted worker. A unit test covers both sequences. Worker suite 188/188. -
fix(worker discovery): two directory listings showed a bare name because the origin root carries no description.
GET /returned a link index —ok,name,version, and pointers to every discovery document. Directories that register the root as the card URL and never followagent_cardtherefore had nothing to copy.Observed 2026-08-14 on agent-tools.cloud, which lists three of the workers. The entry whose
card_urlpointed at/.well-known/agent-card.jsonread correctly: description, provider, skills, conformancepass. The two whosecard_urlwas the origin root came backdescription: null,provider_name: null,skills: [], conformancepartial, and hadprotocol_versionfilled from the cardversion(1.2.0) because the root JSON offers nothing better. Their public entries were a name and nothing else.The root now repeats
description,provider,documentation_url, and a compactskillslist (id, name, description) alongside the existing keys. All previous fields and links are unchanged, so nothing that reads the root today breaks. Additive only: no schema, endpoint, profile, or response change. Worker suite 187/187. Activation: redeploy each published env; directories pick it up on their next crawl. -
fix(worker landing): the HTML page gave a human no way to make contact. The agent card has always carried
support.emailandsupport_hours, so any machine reading the card could find a person. The landing page served to browsers carried neither. Measured 2026-08-14 across all eight live profiles: no mailto, no provider link, no contact of any kind — a human who arrived could read the page and nothing else. Three weeks of funnel instrumentation recorded a handful of such visits a week and no calls, and this is at least part of why: there was no next step to take.The page now ends with a short contact block using the existing
SUPPORT_CONTACT_EMAILandSUPPORT_HOURS_LOCALconstants, plus a link to the provider site already declared in the card. The mailto subject carries the profile name, so a reply can be attributed to the page that produced it — which also makes this the first place where machine discovery could turn into something countable.Presentation only: no schema, endpoint, profile, or response change, and no new claim about the product. Two tests assert every profile's page carries the contact and that the subject names the profile. Worker suite 186/186. Activation: redeploy each published env.
-
feat(worker tooling): require the Vizier gate in GitHub Actions before the Agent Output Verification production deploy. A secret-free job tests an immutable
maincommit first. A fresh protected job then records its external decision workspace, validates a VizierALLOWreceipt bound to that commit and fixed Worker target, and invokes pinned Wrangler. Deployment credentials live in a branch-restricted GitHub Environment; local Keychain operation stays available. Repository and Cloudflare administrators remain able to bypass the application-level gate and must not be delegated to action-taking agents. -
feat(worker): add an optional signed Gmail notification after CIS review intake. The Worker can now schedule a timestamped HMAC-SHA-256 webhook after KV storage, while keeping email delivery outside the form's success path. A Google Apps Script relay verifies the signature, suppresses duplicate request IDs, and sends the redacted request to the operator's Gmail. Both the deployment URL and shared secret remain encrypted Worker secrets.
-
feat(worker): add a durable redacted intake endpoint for the CIS review service page. The
cis_secondary_sanctionsWorker now acceptsPOST /intake/cis-reviewfrom the portfolio origin, validates a bounded JSON payload, drops honeypot submissions, rate-limits repeated requests, and stores the request in the existingAGENDA_USAGEKV namespace with a 30-day TTL.GET /intake/cis-reviewreuses the existing privateSTATS_TOKENauthorization, andnpm run intakeprints retained requests for the operator. Five Worker tests cover storage, validation and origin rejection, honeypot handling, rate limiting, and authenticated retrieval. Intake storage remains independent from the optional notification transport. -
fix(a2a): publish each Worker's JWKS location inside its protected JWS header. Signed Agent Cards now include an RFC 7515
jkuvalue derived from the card's own HTTPSsupportedInterfacesorigin and pointing to that deployment's/.well-known/jwks.json. This removes provider-level key lookup ambiguity without changing keys, endpoints, skills, authentication, or payload contracts. -
docs(a2a): declare the existing evidence-gap analysis on the Agent Output Verification card. The Worker already returns missing evidence ids, quote-to-reference mismatches, unsupported statements, weak claims, evidence gaps, and owner actions through the relay-readiness contract. Its public Agent Card now exposes that behavior as a third structured skill, alongside relay readiness and the pre-action evidence check. This is metadata parity, not a new endpoint, model call, retrieval capability, security scheme, or factuality claim.
-
feat(worker tooling): gate the Agent Output Verification deployment through Vizier. The local deployment command binds the fixed Worker target to the current clean Git commit, validates the decision and receipt hash, and runs Wrangler only after
ALLOW. The Vizier credential stays in macOS Keychain. This operator-side check is bypassable by a process that already has general shell and Cloudflare credential access. No Worker request, response, Agent Card, or public API contract changes. -
fix(worker): support Agenstry HTTP ownership verification. Worker deployments can now serve
GET /.well-known/agenstry-verifyfrom a per-environmentAGENSTRY_VERIFY_TOKENsecret. The route returns404when the binding is absent or malformed, disables caching, and is excluded from funnel telemetry. Verification tokens remain outside source and Wrangler configuration. -
feat(action gate): add
pre_action_checkto the existing Agent Output Verification surface. The additive request and response contracts route a caller-controlled action tocontinue,request_evidence,require_approval, orstopusing supplied claim evidence, risk tier, policy-check results, and an optional external approval reference. The same behavior is exposed through Python services, HTTP, stdio MCP, the A2A adapter, and the existing Cloudflare Worker profile. Twenty replay cases run against both Python and Worker implementations. The function is stateless; it does not authenticate, authorize, enforce, sign a receipt, store an approval, or perform an action. No new Worker or deployment is included. -
fix(a2a): align all eight Worker profiles with the A2A 1.0 JSON-RPC contract. Agent Cards now advertise the protocol only through
supportedInterfaces; public deployments no longer misrepresent the optionalX-Client-Idobservability header as authentication.SendMessagevalidates the v1 Message shape, rejects unsupported versions, preserves the JSON-RPC request id, and returns the requiredresult.taskwrapper. The legacymessage/sendandtasks/sendforms remain available as unadvertised A2A 0.3 aliases. Added local tests and an eight-endpoint public conformance matrix covering cards, representative calls, result envelopes, content types, and JSON-RPC errors. Operational inventory, signing state, staged deployment, and rollback-sensitive key guidance are recorded in A2A-MAINTENANCE.md. -
chore(packaging): conform to the Agent Plugins 1.0.0 layout. Added a root
plugin.jsonand a rootmcp.jsoncarrying the$schemaidentifiers from https://agent-plugins.org. The existing.claude-plugin/,.codex-plugin/and.mcp.jsonfiles are unchanged; the specification ignores them, so no installer loses its manifest.skills/already matched the spec's discovery rule (one skill per immediate child directory holding aSKILL.md). Both new files validate against the published Draft 2020-12 schemas. -
feat(worker tooling):
npm run funnelreads the funnel events, and works around Cloudflare's silent sampling. The events shipped in the previous entry could only be read by hand.deploy/cloudflare-worker/scripts/funnel.jsnow queries the Workers Observability API withCF_API_TOKENfrom.envand prints steps, networks, user agents, referrers, and a plain list of visits that are not self-identified automation — crawlers are split out for display rather than dropped, since a crawler visit is still a fact about who found the endpoint.The trap it works around: this dataset is sampled on wider timeframes. Measured 2026-08-07 against five known events — a 6-hour query returned all five at
abr_level1, a 24-hour query returned one atabr_level10. A naive 72-hour query undercounts by an order of magnitude with no error and no warning. The script walks the window in 6-hour slices, merges them, and prints a warning if a slice still comes back sampled. Tooling only: no worker code, schema, or deployment change. -
feat(worker analytics): instrument the steps before a call, and what the caller left with. The KV log records
message/sendandtools/callonly, so with single-digit weekly visitors the drop-off was invisible: someone who opened the agent card and left produced no record anywhere, and a call that returnedinsufficient_informationwas indistinguishable from one that returned a usable verdict.Two additions. Each discovery GET now emits an
agenda_intelligence_a2a_funnelevent with astepoflanding,card,discovery, ordocs, carrying the same privacy-safe caller fields as the usage event./health,/status,/robots.txt,/stats, and the JWKS route stay silent so monitoring traffic does not bury real visits. These go to Workers Logs, not KV: the free KV tier allows 1,000 writes a day against 250-480 discovery GETs on a namespace already shared with the rate limiter and the snapshot cache, while Workers Logs takes 200,000 a day at no cost.Second, every logged call now carries a uniform
outcome— the routing decision the caller received, its status, and its score — read from the profile'sreadiness_contract./statsgains anoutcomesbreakdown andcounters.empty_handed, the number of calls that ended ininsufficient_informationorinvalid_request. That ratio, not the raw call count, is what says whether people who arrive can use the thing.No IP address, cookie, authorization header, or prompt text is stored, in either event. Additive: no schema, endpoint, or A2A profile change. Worker suite 158/158. Activation: redeploy each published env.
-
feat(mcp): adopt the 2026-07-28 stateless core, and serve MCP from the deployed workers. The stdio server still declared
2025-03-26, three revisions behind. The 2026-07-28 revision removed sessions, theinitializehandshake, and SSE resumability; added the mandatoryserver/discover; made every result carryresultType; and madetools/listcacheable viattlMs/cacheScope. All of that is now implemented. Older revisions keep working —initialize,notifications/initialized, andpingare still answered, and a request that states no version in_metais treated as compatible. A version stated in_metaand outside the supported set is rejected with-32022.Because sessions are gone, MCP over HTTP no longer needs per-client state, so the Cloudflare workers now serve
POST /mcpon the same request/response path they already use for A2A — no Durable Objects, no new binding. One deployment serves one profile and therefore exposes exactly one tool, named identically to its stdio twin.tools/callandmessage/sendshare one dispatch (runProfileRequest), so the two transports cannot return different verdicts for the same payload, andtools/callinherits the same Bearer gate, rate limit, and usage logging.server/discoverandtools/liststay open, likeagent/card. The MCP server card advertises both transports.Roots, Sampling, and Logging were deprecated in the same revision; none were ever used here. MCP Apps and the Tasks extension are deliberately not adopted. See ADR 0024.
-
feat(mcp): two live workers had no MCP tool, and the rest could not be called without guessing. Two defects in what an agent can act on.
First,
kazakhstan_market_entry_readinessandagent_output_verificationshipped as service functions, HTTP routes, A2A profiles, and deployed Cloudflare Workers, but never as MCP tools — an MCP client could reach four of the six live vertical workers. Both are now exposed throughmcp_serverwrappers and theTOOLSregistry, with golden and failure contract tests.tests/test_mcp_tool_callability.pynow fails if any deployed worker has no MCP tool, so the surfaces cannot drift apart again.Second, every tool taking a structured payload declared it as a bare
{"type": "object"}whose description named a schema file the caller has never read. An agent selecting fromtools/listhad to guess the payload, fail validation, and drop the tool. Nine constructive parameters now inline the request shape — field names, types, enum values, required list, local$defsreferences resolved, plus the schema's own worked example — generated from the bundled schema at import time rather than hand-copied, so it cannot drift.get_schemastill serves the full nested contract, and each description names the exact key to ask for. Cost, measured: thetools/listpayload grows from 23,313 bytes over 27 tools to 37,002 over 29 — roughly 3.4k extra tokens per connected session. The shapes are capped at two levels for that reason.agent-manifest.jsonand its packaged copy are regenerated to match (ADR 0012 keeps them mirrored), andllms.txt, its packaged copy, andMCP.mdno longer say market-entry is A2A-only. Python suite 515/515, lint and typecheck clean. No schema, endpoint, or A2A profile change; no worker redeploy needed. -
fix(worker analytics):
modules_usedwas recorded asunknownfor every vertical worker.buildUsageEventnormalised the field withdetails.modules_used.map((item) => item.module), which is correct only for the routedanalyzepath ([{ module, role }, ...]). The six single-profile branches pass plain strings (["cis_secondary_sanctions"]), so the map read.moduleoff a string, produced[undefined], persisted[null]in KV, and aggregated asunknown. Measured over 2026-04-26..2026-07-24: 649 of 1329 logged calls reported no modules — exactly the sum of the six affected profiles (310 + 134 + 97 + 95 + 12 + 1), confirming the cause. The newnormalizeModuleshelper accepts both shapes and drops empty entries. Analytics-only; no request/response schema, enum, endpoint, or profile change. Regression test covers the string shape. -
feat(worker analytics): name the caller that the coarse client class cannot.
buildUsageEventalready derivedreferrer_hostandcf.colo, butrecordUsageStatsdropped both before writing to KV, so/statscould report only country and a five-bucket client class — every unrecognised caller aggregated asunknownfrom an unknown source. The reduced event now also persists the referrer host, the Cloudflare colo, the network operator (cf.asOrganization), and the user-agent truncated to 120 characters, and/statsgainsnetworks,referrers, anduser_agentsbreakdowns (user_agentscapped at the top 15 rows/day — crawlers each ship their own string).event_versiongoes 1 → 2. Still no IP address, cookie, authorization header, or prompt text: the privacy guarantee documented in the worker README is unchanged in kind, and the README field list is updated.scripts/stats.jsprints the three new rows. Worker suite 145/145, Python suite 506/506. Activation: redeploy each published env (wrangler deployplus--envfor the seven profile envs); until then/statskeeps returning the old shape for previously stored days, which remain readable — the new breakdowns simply readunknown/nonefor events written before the deploy. -
feat(cis worker): surface the snapshot provenance date in A2A metadata. The Snapshot upstream (ADR 0014) already computed
snapshot_generated_atfrom the static public-list index it matches against, but the worker dropped the value before assembling the response, so a caller sawlive_retrieval_status: "success"with no way to tell whether a "no match" reflected the current lists or a hand-rebuilt index that had gone stale. The A2A metadata block now carrieslive_retrieval_snapshot_generated_at(the index build date under the Snapshot upstream,nullfor Watchman / OpenSanctions, which query live). Additive metadata field, worker-only — the Python service uses the OpenSanctions adapter and has no snapshot path; no request/response schema, enum, endpoint, or profile change, so ADR 0003 / ADR 0015 are untouched. New worker test asserts the date is surfaced with the upstream on and isnullwith it off. Worker suite 142/142. Activation:wrangler deploy --env cis-secondary-sanctions. -
fix(cis worker): drop the edge-cache override that pinned a stale sanctions index. The Snapshot fetch passed
cf: { cacheTtl: 3600, cacheEverything: true }, so Cloudflare held the index body at the edge for an hour independently of the adapter's own six-hour module TTL — and unlike the module cache, the edge copy survived isolate restarts and awrangler deploy. Observed on 2026-07-24: the refreshed index was live on the site, the worker had been redeployed, and callers were still served the 2026-06-26 build with no operator lever to force the new one. The fetch now sets nocfoverride, leaving the module TTL as the single freshness regulator; the origin's own cache headers still absorb request load. Regression assertion added to the existing Snapshot adapter test. Worker suite 142/142. Activation:wrangler deploy --env cis-secondary-sanctions. -
chore(cis worker): agent-card prose said "screening" for what is dated snapshot name matching. Companion to the provenance-date change above. The card's
wrapper_scopedescribed "active server-side name screening against a public-list snapshot" and one buyer use case read "OFAC EO 14114 secondary-sanctions exposure screening" — the product's own landing page FAQ says in as many words that this is not sanctions screening, so the card was the surface where the claim leaked, and it is the surface agents and marketplaces read. Reworded to "name matching against a dated public-list snapshot rebuilt on an operator cadence, not a live list feed" and "exposure triage before screening". Card free-string text only; no schema, enum, endpoint, or profile change. Worker suite 142/142. Activation:wrangler deploy --env cis-secondary-sanctions.
1.4.0 — 2026-07-22
-
release: publish the MCP evidence-packet workflow. Synchronizes the package and discovery surfaces at
1.4.0, adds a focused runnable stdio example forcheck_evidence_packet, and documents the decision-workspace boundary before high-stakes or irreversible action. -
feat(mcp): expose the primary evidence-packet preflight. Adds
check_evidence_packetto the local stdio MCP contract so an agent can run the repository's primary claim/source packet check without dropping to the CLI or importing Python. The tool preserves the existing deterministic, caller-supplied-text boundary: it reports reference, quote, lexical-support, and unmatched-number diagnostics, never factual truth or authorization. -
feat(mcp): authoring tools
create_briefandappend_evidence. Adds two MCP tools (since: v1.4) that let an agent produce protocol documents inside the contract instead of hand-building JSON and validating it afterwards.create_briefassembles a brief from supplied fields, reportsmissing_requiredso an agent can fill it in over several turns, defaultsevidence_modetoreasoning_only, and surfaces unknown keys inignored_fieldsrather than dropping them.append_evidenceappends a claim and its sources to an evidence pack, de-duplicates sources on(name, url)when the claim already exists, keepsunsupported_claimsconsistent with per-claimsupport_status, and never inferssupported— an omitted status defaults tounsupportedorpartially_supported, and extending a claim without an explicit status leaves the stored one unchanged. Both are deterministic and stateless: they return the document to the caller and do not write files, fetch URLs, verify quotes, score source reliability, or assess factual truth. Additive per ADR 0012; no existing tool, schema, or response shape changed. -
chore(verification): reproducible repository evidence. Adds
make verification-report, which runs the existing Python/package and Cloudflare Worker gates and writes a deterministic JSON result with hashed contract files. The report records zero paid API calls and explicitly limits its claim to internal technical verification. The Makefile now pins localsrc/ahead of stale editable installs so documentation smoke tests exercise the checked-out code.
1.3.0 — 2026-07-15
-
release: prepare v1.3.0 evidence-packet preflight. Syncs package, manifest, discovery, container, registry, and plugin versions; adds a published-wheel smoke check for the evidence-packet command; and replaces the stale
1.2.0first-run path with a coherent editable-source workflow. -
feat(focus): evidence-packet preflight as the primary repo workflow. Adds additive
evidence-packet-requestandevidence-packet-responsev1 schemas plusservices.check_evidence_packet. The existingcheckCLI now auto-detects this packet shape and returnspacket_complete,source_review_required, orpacket_incomplete, with claim/source reference checks, verbatim quote checks, lexical-support diagnostics, unmatched-number flags, and owner actions.factuality_statusis alwaysnot_assessedand human review is always required. Legacycheck <agenda-brief.json>behavior remains compatible. Existing vertical workers and MCP/A2A/HTTP contracts are unchanged and are now documented as compatibility profiles rather than the repository's primary product narrative. -
docs(example): first live-source-backed Claim Verdict pack. Records authoritative PyPI and GitHub release metadata retrieved on 2026-07-11 for
agenda-intelligence-md1.2.0, with two boundedverifiedverdicts and an explicit reminder that source stance is caller-supplied rather than fetched or inferred byverify-claims. -
fix(release): serialize MCP Registry publication behind PyPI visibility. The tag-triggered registry workflow now waits for the exact package version to become visible through the PyPI JSON API before publishing. This closes the observed
404race between parallel release workflows. Post-release smoke now executesgrounded-checkandverify-claimsfrom the published wheel and asserts that both MCP tools are present. -
feat(capability): bounded factual Claim Verdict (
verify_claims). Adds a separate deterministic layer over caller-supplied evidence records. It checks freshness, source authority, independent source groups, conflicts, jurisdiction, and exact subject identifiers as of a declared date, then returnsverified,contradicted,partially_supported,unresolved, ornot_verifiable. Ships with request/response schemas, CLI and MCP surfaces, an example request, ADR 0023, and contract tests. It does not discover or fetch sources, perform fuzzy entity resolution, or make legal/compliance determinations.verifiedmeans the declared evidence threshold is met by the supplied set, not absolute truth; human review remains required. -
feat(capability):
grounded_check— claim-to-corpus grounding triage over caller-supplied source texts. New composed service capability (tier ofaudit_claims/verify_quotes, not a commercial vertical worker) that takes a claim set plus the full text of the sources the claims should rest on and returns a deterministic per-claim grounding status (grounded/weakly_grounded/ungrounded), term coverage against the best-matching corpus document, a best-matching passage excerpt, numeric values not found anywhere in the corpus, verbatim quote checks, owner actions, and an overallgrounding_signal. Ships behindschemas/v1/grounded-check-request.schema.jsongrounded-check-response.schema.json, thegrounded_checkMCP tool, thegrounded-checkCLI subcommand, an example pack underexamples/grounded-check/, and contract tests. Lexical and local-text only: no live retrieval, no source discovery, no source-reliability scoring, no factual-truth verification — grounding in a wrong corpus does not make a claim true;human_review_requiredis always true. Classification: reusable runtime improvement; no traction claim.
-
feat(worker): Cloudflare A2A parity + host for
agent_output_verification. JS parity of the relay-readiness verdict indeploy/cloudflare-worker(src/index.jsresult/card/parser,src/profiles.jsdiscovery profile), a dedicated wrangler envagent-output-verification-a2a(AGENT_PROFILE=agent_output_verification), and worker contract tests (grounded/allow, unsupported/block, orphan-evidence/block, weak/verify, invalid shape, bad enum).make verify-localgreen (141 worker tests). The live endpoint is not deployed by this change —wrangler deploy --env agent-output-verificationis the operator step. Build-to-learn: exposed as a discoverable trust/verification node, no traction claim. -
feat(capability):
agent_output_verification— A2A relay-readiness verdict over a claim set. New composed service capability (tier ofaudit_claims/score_output, not a commercial vertical worker) that wraps a claim-level evidence audit (evidence-audit.schema.json) and returns a machine-actionable relay verdict —allow_relay/verify_before_relay/block_unsafe_claims— plus unsafe/weak claims, evidence gaps, and owner actions, for one agent verifying another agent's output before relaying or acting on it. Ships behindschemas/v1/agent-output-verification-response.schema.json,POST /v1/agent-output/verification, theagent_output_verificationA2A capability and agent-card skill, and contract tests. Schema-level and structural only: no factual-truth verification, no live retrieval,human_review_requiredis true for any verdict other thanallow_relay. Classification: build-to-learn — no observed buyer or paid usage; exposed as a discovery/positioning capability, not a revenue claim. -
feat(worker): profile-as-funnel — point the structured gates at the Corridor & Sanctions Risk Assistant front door. Appended one factual navigation line (
PROVIDER_FRONT_DOOR_POINTER) to the Middle Corridor, Gulf maritime, CIS secondary-sanctions, and Kazakhstan market-entry card descriptions so a human landing on any gate is funnelled to the front door and the free pre-deal screening memo instead of navigating nine cards blind. No traction claim, no contract/schema/response change. -
feat(worker): add GLEIF ownership enrichment for
cis_secondary_sanctions(ADR 0022). Newdeploy/cloudflare-worker/src/upstream_gleif.jsadapter resolves a counterparty name against the free, no-key GLEIF LEI relationship pool (api.gleif.org, CC0-1.0) and contributes disclosed direct/ultimate parent asownership_chain_evidence/beneficial_ownership_source. It runs alongside the sanctions-list upstream (never replaces it) and is off by default — activated only when the operator setsGLEIF_ENABLED, so merging changes no live behavior. Disclosed relationships only; not hidden or multi-layer beneficial ownership; boundaries unchanged (not advice, human-review required, not identity verification). Adds a SOURCE_POLICY whitelist row (dual-copy) and two worker tests. No schema or response-shape change. -
feat(worker): sharpen Agentic Interaction Trust Gate positioning to counterparty-agent verification. Reframed the
agentic_interaction_trustagent card, skill, tags, examples, and use-case doc to lead with the agent-to-agent case — "before you let a counterparty agent transact or invoke a capability, check whether the evidence to trust that interaction is present" — matching the A2A/x402 marketplace audience. No contract, schema, service-function, or response change; boundary reaffirmed (evidence-readiness only, not identity verification or authorization). -
feat(worker): add Corridor & Sanctions Risk Assistant discovery front. New lightweight A2A profile
corridor_sanctions_assistant(Zee-pattern): a human-facing front door that orients a corridor/sanctions deal-risk question, routes to the four structured gates, and hands off a free pre-deal screening memo. It is NOT a vertical worker — no schema, no service function, no triage, scoring, screening, or retrieval of its own;message/sendreturns a deterministic orientation artifact only. Adds the profile (deploy/cloudflare-worker/src/profiles.js), card + routing + deterministic responder (src/index.js), wrangler envcorridor-sanctions-assistant, worker tests, and a use-case doc. Going live is an operator deploy (wrangler deploy --env corridor-sanctions-assistant), a public-positioning step outside CI. -
feat(distribution): add Codex plugin manifest. Added
.codex-plugin/plugin.jsonso Codex marketplace installs expose the bundledskills/and.mcp.jsonMCP server instead of installing only legacy Claude plugin metadata. -
feat(evidence-ledger): add internal evidence assembly module. Added
agenda_intelligence.evidence_ledgerwith an append-onlyEvidenceLedger, deterministic reference normalization, protected-reference filtering, claim-support/data-integrity channels, and a presentation-update guard that rejects formatter changes to route, score, verdict, or references. The shared service-layer dated-source intake now uses the ledger for de-duplicated supplied-source typing. No schema, CLI, MCP, HTTP, A2A, or public response contract change. -
feat(agent-readiness): add agent-card readiness lint + canon checklist. New top-level
AGENT_READINESS.md(delegation-readiness checklist: identity attribution, capability scope, interface contract, security declaration, autonomy boundary, payment permissions, operator contact; stance MCP-first / A2A-later / payment-safe / human-escalated) and a new CLI commandvalidate-agent-card— a static lint of a published agent card against that checklist plus the statically checkable subset of a public registry 9-criterion conformance methodology (CC-BY-4.0, attributed in the doc). No endpoint probing, no cryptographic signature verification, no new worker surface, no MCP tool added. Contract:schemas/v1/agent-readiness-report.schema.json(+ packaged copy); tests cover one golden signed card and one failure card (unsigned, payment surface without limits).
[1.1.2] – 2026-07-02
-
release: v1.1.2 distribution checkpoint. Bumped package, manifest, registry, and plugin metadata versions to
1.1.2. Added anagenda-intelligence-mdconsole-script alias foragenda_intelligence.mcp_stdio:mainsouvx agenda-intelligence-mdresolves (required by MCP Registry clients, which construct the launch command from the package identifier). Listedcentral-asia-caspianandgulf-middle-eastin the plugin marketplace after their repos renamed runtime overlays fromskills/toruntimes/and added plugin packaging. -
feat(distribution): stage official MCP Registry publication metadata. Added
server.json(registry nameio.github.vassiliylakhonin/agenda-intelligence-md, PyPI package entry, stdio transport,uvxruntime hint) and an invisiblemcp-name:HTML comment marker at the top of README so the registry can verify PyPI package ownership. Publication itself is a separate step: it requires a v1.1.2 PyPI release (so the marker lands in the published README) and an interactivemcp-publisher login github+mcp-publisher publish. The planned v1.1.2 release should also add anagenda-intelligence-mdconsole-script alias foragenda_intelligence.mcp_stdio:main, because registry clients constructuvx agenda-intelligence-mdfrom the package identifier and no script by that name exists today. -
feat(distribution): package the repo as a Claude Code plugin marketplace. Added
.claude-plugin/plugin.jsonand.claude-plugin/marketplace.json(listing this runtime plugin plusglobal-think-tank-analyst) and.mcp.jsonso the MCP server auto-loads on plugin install viauvx --from agenda-intelligence-md agenda-intelligence-mcp. Added an "Install in Claude Code" section to README. Verified locally withclaude plugin installfrom an isolated config (2 skills + 1 MCP server discovered). The two regional specialist repos are deferred: theirskills/{claude,codex,openclaw}/runtime-overlay layout collides with plugin skill auto-discovery (overlay dirs would install as junk-named skills), so listing them waits on a packaging-convention decision. -
release: prepare v1.1.1 hardening checkpoint. Bumped package, manifest, and MCP registry metadata versions to
1.1.1; addedRELEASE_NOTES_v1.1.1.md; correctedRELEASE_NOTES_v1.1.0.mdto match the already-published A2A / Worker parity release. No tag is pushed in this commit because the current tag workflow publishes to PyPI on anyv*tag. -
feat(weekly-delta): add confidential workflow golden/failure bench. Added
weekly-delta-benchfor deterministic weekly/status fixtures. The bench checks route selection, unsafe-to-repeat claim extraction, owner-action coverage, missing source-plan categories, alias-only discipline, and boundary notice. The initial fixture set includes one alias-only committee-escalation golden case and one naming-leak failure case. No LLM, factual verification, advice, or new worker surface added. -
test(memo-quality): add confidential project-room quality regressions. Added a golden confidential project-room memo, a schema-valid naming-leak failure memo, a new
confidential_alias_disciplineguardrail inmemo-quality-bench, and aweekly-deltaregression that checks alias-only synthetic output, unsafe-to-repeat claims, and owner-action coverage. This raises the memo-quality fixture set to 5 golden / 8 failure cases without changing the agenda-memo schema or factual-verification boundary. -
docs(analysis-bank): close the AnalysisBank hardening checkpoint. Added release notes and an operator checkpoint for the reasoning-memory layer: before/after state, runtime path, edit checklist, quality gates, and a stop rule. This documents the current contract after lifecycle linting, packaged memory parity, retrieval/applicability benches, guarded
analyzeprompt injection, andaudit.reasoning_memory. No runtime behavior changed in this docs-only checkpoint. -
docs(discovery): remove the deprecated discovery wedge. Deleted the deprecated teardown/profile docs, public-signal scans, profile template, OKF concept, catalog entry, entity-map node, and README /
llms.txtpositioning so the repository no longer advertises that removed discovery path. The remaining build-to-learn public artifact is the alias-first confidential project-room workflow. -
feat(worker): optional access controls on the CIS message/send route, both off by default. Two independent levers, shipped dormant so live behavior is unchanged until activated (same "off by default — activation is the go-live step" pattern as the Snapshot upstream). (1) Wired
cis_secondary_sanctionsinto the existing per-profile bearer gate (productionAuthKeynow readsCIS_SECONDARY_SANCTIONS_API_KEY) — a hard paywall that closes the route (incl. the public demo) for the day a paying integration appears; agent-card discovery stays public. (2) Added a best-effort soft rate limit onmessage/send(rateLimitPerHour/checkRateLimit): whenRATE_LIMIT_PER_HOUR > 0it buckets per profile + client IP (cf-connecting-ip) + UTC hour in the existingAGENDA_USAGEKV and returns JSON-RPC-32002/ HTTP 429 over the cap, keeping the free browser demo usable while throttling bulk programmatic use. KV is eventually consistent so this deters scripting rather than being a hard control, and it fails open on any storage error. Both documented as commentedwrangler.tomlentries on the CIS env. New contract tests (CIS key scoping;rateLimitPerHourparsing; throttle-past-cap with per-IP isolation; no-op when unconfigured; fail-open on KV error); worker suite 121/121 green,verify:agent-cardgreen. No schema, request/response shape, or dual-copy path touched. Deploy is manualwrangler deploy --env cis-secondary-sanctions; merging changes nothing live. -
fix(worker): agent-card prose lagged the active Snapshot upstream. The
live_retrievalblock correctly listed Snapshot as active, but four prose fields still described the profile as "optional OpenSanctions / Watchman live retrieval when configured":wrapper_scope,skills[0].description,focus[1]("OpenSanctions consolidated dataset name matching"), and theboundariesactive-line carried a wrong license tag (CC-BY 4.0 / Apache-2.0 — those are the OpenSanctions/Watchman licenses, not the public-list snapshot's). Reworded all four to describe active server-side name screening against a public-list snapshot (Snapshot upstream; Watchman / OpenSanctions as alternates), with the "possible string match only, not a determination" boundary. Card text only; worker suite 117/117; redeployed tocis-secondary-sanctions-a2a(verified live via cache-busted fetch — the plain.well-knownresponse converges as the edge cache expires). -
docs(cis): sync README / SOURCE_POLICY / use-case doc to the active Snapshot upstream. After ADR 0020 activated
cis_secondary_sanctionslive retrieval, the prose still described the profile as OpenSanctions-only and "both upstreams currently deferred". Updated the README CIS section + endpoint line, the use-case doc, and theSOURCE_POLICY.mdper-profile whitelist (dual-copy synced) to list three upstreams tried in order — Snapshot (active, $0, no host), Watchman (free self-host, deferred), OpenSanctions (paid, deferred) — with the Snapshot row marked Active. Boundaries restated: possible string match only, not identity verification / determination, human review required, no paying customers. Docs only;test_package_consistencygreen. -
feat(worker): activate the Snapshot upstream for
cis_secondary_sanctions(ADR 0020). SetsSNAPSHOT_INDEX_URLas a declarative var inwrangler.tomlfor thecis-secondary-sanctionsenv (pointing at the published compact index) and deploys it. The livecis-secondary-sanctions-a2aendpoint now performs $0 server-side name screening — verifiedlive_retrieval_status: success,upstream: Snapshot, exact match on a known SDN entity. This flips the profile's public posture from "no live retrieval" to "server-side screening against a fresh public-list snapshot" (hence the ADR); boundaries unchanged — possible string match only, not identity verification / determination, human review still required. Deactivate withSNAPSHOT_DISABLED=1+ redeploy. Portfolio demo page copy and agent-card text updated to match. -
feat(worker): $0 Snapshot upstream for CIS secondary-sanctions server-side name screening (ADR 0014). Adds a third per-profile live-retrieval upstream for
cis_secondary_sanctions,Snapshot(deploy/cloudflare-worker/src/upstream_snapshot.js), listed first ahead of Watchman (free self-host) and OpenSanctions (paid). Unlike those, it needs no external container: the worker fetches one compact public-list name index —sanctions-name-index-compact.json, published by the portfolio site'sscripts/sanctions_name_index.pyfrom OFAC SDN + consolidated, EU consolidated, and UK FCDO source files (11.3 MB full index → 2.76 MB compact, dropping the precomputed normalized string / type / id and de-duplicating authority+list into asrctable) — and matches in-process. Matching is deliberately CPU-cheap for the Worker budget: exact normalized-name match plus significant-token overlap (>=2 shared tokens, >=0.82 ratio), no per-request Levenshtein (fuzzy stays browser-side). The parsed index is cached in module-global scope per isolate and re-fetched after a 6 h TTL; corporate-noise tokens (>1500 postings) are dropped to bound memory. Graceful degrade on unsetSNAPSHOT_INDEX_URL, network/HTTP/timeout failure, or malformed index — the caller never fails. Wired intoPROFILE_LIVE_RETRIEVAL, the agent-cardlive_retrieval.upstream_options, the deferral note, and thematchAgainstActiveUpstreamdispatcher; results flow through the existingauto_fetched_sources+ attribution path (attribution only surfaced when a match is actually merged). New contract tests (exact + token-overlap golden with module-cache reuse and a no-false-positive case; disabled-when-unset degrade; status/agent-card upstream ordering); worker suite 117/117 green;verify:agent-cardgreen. Off by default — activation is the go-live step:wrangler secret put SNAPSHOT_INDEX_URL --env cis-secondary-sanctions(point it at the published compact index) thenwrangler deploy --env cis-secondary-sanctions. Flipping it on flips the profile's public "no live retrieval" posture, so it still needs the ADR-0014 positioning update + the page copy refresh before going live; until activated the profile stays evidence-only and the demo's browser-side preview is unchanged. -
docs(worker): ground the maritime indicators with supporting empirical research. Added a "Supporting research (empirical context)" section to the gulf-maritime-exposure use-case doc and a
vessel_due_diligence_indicatorsgrounding paragraph (previously undocumented in prose, unlike the other MC checklists) to the Middle Corridor use-case doc. Both cite recent maritime-detection research — dark ship-to-ship transfers, dark AIS-off vessel trajectories, and AIS / GNSS spoofing — as empirical corroboration that the dark-fleet / STS / AIS-manipulation practices the workers flag are prevalent and hard to detect, which is why a documented evidence-readiness check is warranted. Explicitly framed as empirical context, not the regulatory basis (OFAC / EU / UK OFSI / UN guidance remains load-bearing): the workers presence-flag the evidence gap and implement none of the cited detection methods. Docs only — no schema, contract, indicator logic, decision path, or dual-copy path touched; boundary disclaimers preserved. -
feat(worker): observe-only source-URL link-integrity lint on the Middle Corridor deal-risk response. Cited
dated_sources[].urlvalues are now structurally classified —well_formed,illustrative(documented placeholder hosts such as example.com), ormalformed(non-http(s) scheme, missing host, or a placeholder token liketbd/n/a). When at least one source carries a malformed URL the response gains an optionallink_integrityblock (checked/well_formed/illustrative/flagged[]with the offending url, reason, and source id/type); otherwise the field is omitted and existing output is byte-identical. The lint is structural only: it does NOT fetch URLs, verify that a page exists, perform live retrieval, or check content, and it does NOT change the triage recommendation, risk signal, operational decision, readiness score, or evidence gaps — proven by a contract test that runs the canonicalready_for_human_reviewfixture with and without a mutated URL and asserts every other field is unchanged. Additive optional schema property under top-leveladditionalProperties: false; dual-copy synced undersrc/agenda_intelligence/data/. First step toward source-citation-integrity checking; the live archive-presence variant remains deferred behind ADR 0014 and is not implemented here. -
docs(worker): name the encoded sanctions frameworks in the Middle Corridor agent card. The live
middle_corridor_deal_riskagent card described its output generically ("sanctions-relevant / re-export jurisdiction flags"), so a technical evaluator reading the card or the Agenstry listing could not see the specific frameworks the deterministic engine actually encodes. Thecard.descriptionand thesanctions-adjacency-evidence-gateskill description now name them: OFAC named-sector (EO 14024/14114) and newly-formed-counterparty red flags, EU re-export / circumvention-watch jurisdictions (incl. the 20th-package measures on Kyrgyzstan), and dual-use cargo screened against the EU/US Common High Priority List — plus an explicit "deterministic rule-based logic, no model in the decision path". Description text only; no schema, contract, skill id, tag, or dual-copy path touched; the "Presence-flagging and evidence triage only, not a sanctions determination" disclaimer is preserved verbatim. Worker suite 112/112 green;verify:agent-cardgreen. Activation:wrangler deploy --env middle-corridor-deal-risk-gate— until then the live card and the Agenstry listing keep the prior wording. -
fix(evidence-mode): tolerate terminal
[verify]punctuation and require provenance for source-backed modes. The post-hoccheck_evidence_mode_disciplinevalidator now accepts factual claims ending in[verify]followed only by trailing punctuation/whitespace, while still rejecting mid-sentence markers. It also treatsmixed/user_providedmemos with empty or missingaudit.provenanceas discipline failures, preservingreasoning_onlyas the valid source-free mode. Added generated schema-valid golden/failure fixtures plus direct regression tests. Docs now state the structural boundary explicitly: this validator cannot detect mislabeledbasis, fabricated content, or determinative facts hidden insidereasoning_onlyprose;[verify]is a human-review flag, not a truth signal. Runtime wiring remains a human decision because the function is still post-hoc/test/eval-only and is not yet invoked byvalidate_memo, MCP, HTTP, or A2A. -
feat(cis, market-entry): currency-refresh from a 2026-06-20 landscape pain-discovery. A fresh scan of the three corridor verticals confirmed the existing frames still hold (same finding as prior rounds: pains real, already covered) but surfaced two regime moves worth sharpening to the current state. Both additive, presence-flag only (no score movement, ADR 0015 intact), mirrored in the Cloudflare Worker JS parity, with new Python + JS tests. (1) CIS country-level anti-circumvention: the EU's 20th package (2026-04) was the first activation of the country-level anti-circumvention tool, against Kyrgyzstan (restricted item categories to the country + regional FI transaction bans). New
COUNTRY_LEVEL_ANTI_CIRCUMVENTIONset (Kyrgyzstan), andcis_secondary_sanctions_exposurenow adds a sharperlimitationsline when the counterparty is domiciled there — confirm the restricted item categories / onward destination and check correspondent exposure to any regional FI designated in that package. Distinct from, and sharper than, the existing softer circumvention-watch flag; no specific bank is named (durable, no maintenance liability). (2) Market-entry currency-control 2026 mechanism: Kazakhstan's 2026 currency-control rules (NB Resolution No. 29, in force 2026-04-19) make currency-contract registration mandatory at the USD 50,000 threshold for legal entities and let banks delay/refuse cross-border intercompany transfers lacking demonstrable economic substance. Thecurrency_control_and_repatriation_noteevidence-gap copy is sharpened to name the USD 50,000 threshold and economic-substance evidence for intercompany flows (capital, shareholder loans, royalties, management fees). Free-string output / code copy only — no schema, taxonomy structure, enum, or dual-copy path touched.make cigreen; worker suite 112/112. Activation:wrangler deploy --env cis-secondary-sanctionsand--env kazakhstan-market-entry-readiness. -
chore(cis): de-stale "EU 14th package" wording to non-staling "EU sanctions package". Companion to, and the deferred follow-up named in, the expert-review entry below. The CIS secondary-sanctions worker still referenced the "EU 14th package" (mid-2024) across descriptions, schema
descriptionfields, the emittedtop_exposure_dimensionstext, the three contract example fixtures, and docs; the EU is on its 20th package (April 2026), so the stale number read as unmaintained to a compliance audience seeing it in the agent card, MCP tool description, or the worker's own output. Replaced with the generic, non-staling "EU sanctions package" across README, worker JS (skill name / description / example + emitted dimension), MCP tool description, A2A adapter, request/response schemas (+ dual-copy underdata/), the CIS contract fixtures, and the use-case / agenstry docs. Non-breaking and deliberately minimal: the skill ideu-14th-packageis kept as an opaque stable slug (renaming it would be the only breaking part and risks external/Agenstry references for no user-visible benefit), so no version bump and no ADR are required — descriptive-text + free-string-output wording only, no schema shape / enum / endpoint / profile change. ADR-0014 left untouched (immutable history).top_exposure_dimensionsis a free string array (not enum) and the contract fixtures validate against schema rather than by equality, so the wording change stays schema-valid.make cigreen; worker suite 110/110. Activation:wrangler deploy --env cis-secondary-sanctions. -
feat(middle-corridor): expert-review output fixes — end-user-statement gap on dual-use cargo, rail-aware corridor framing, 50% Rule prompt, screening-result wording. A 2026-06-19 trade-compliance review of the live deal-risk gate surfaced four output-layer gaps, all fixed additively (no schema change, no dual-copy path touched, ADR 0003/0015 intact; score and signal stay structural). (1) End-user-statement gap (the substantive one): when the cargo is presence-flagged dual-use and no
end_user_or_reexport_evidenceis on hand,limitationsnow carries a distinct deal-state line ("…no end-user / re-export evidence is on hand; obtain a signed end-user statement before signature…") — the prior dual-use flag gave generic "obtain an EUS" advice but never said the file currently lacks one. Deliberately alimitationsflag, not a scored required-before-go item, so it does not movedecision_readiness_score(a test asserts the EUS-supplied vs. not-supplied score is identical). (2) Rail-aware framing: the corridor is rail + Caspian ferry, not maritime —vessel_or_carrier_historyevidence-gap copy and thecarrier / vessel / rail-operator history gaprisk relabelled, and two rail prompts added tocustoms_harmonization_indicators(gauge-change/transload at Khorgos / Altynkol; Caspian demurrage / wagon-detention / ferry-slot at Aktau / Kuryk). (3) 50% Rule prompt: the missing-beneficial-ownership exposure line now names the OFAC/EU 50 Percent Rule (aggregate blocked-person ownership) as the human-review step the file is not yet ready for. (4) Screening wording: "sanctions list extract" evidence-gap copy reframed to "sanctions screening result" (screening is a process producing a result, not a held document); the request-schema enum keysanctions_list_extractis unchanged. Mirrored in the Cloudflare Worker JS parity; new Python contract test (EUS-gap fires without evidence, clears with it, score-invariant) + JS worker parity test. Deliberately NOT changed: the engine'sEU 14th packagereferences (schemas, CIS contract example fixtures,eu-14th-packageskill id, ADR-0014 history) were left in place — sweeping them to the current package (20th, Apr 2026) touches the frozen contract, dual-copied schemas, a skill id, and an immutable ADR, so it needs its own versioned change; the user-facing portfolio pages were already updated to non-staling wording. Activation:wrangler deploy --env middle-corridor-deal-risk-gate. -
feat(middle-corridor): cargo-string dual-use / export-controlled presence flag (ADR 0015 deferred item). A 2026-06-19 functional review of the live deal-risk gate found that the cargo field was inert: a deal declaring
microcontrollers and RF modules— the single most material risk in a corridor-diversion deal — produced only the genericsanctions adjacencyrisk, never an export-control flag, even though ADR 0015 explicitly lists cargo-string dual-use detection as a legitimate, deferred, same-pattern presence flag.middle_corridor_deal_risknow scans the declaredcargostring against a BIS/EU Common High Priority List (CHPL) term set (microelectronics, RF/transceiver, FPGA, GNSS/inertial, CNC/machine-tools, precision bearings, UAV, thermal/night-vision, carbon fibre, …) and, on a match, adds"cargo includes a potential dual-use / export-controlled item"totop_risks, a namedlimitationsline ("…export-control escalation flag for human review, not a classification or licensing determination. Obtain an end-use / end-user statement…"), and surfacesreexport_control_indicatorseven when end-user evidence was supplied. Per the ADR 0015 boundary this is presence-flagging routed to human review — NOT an export-control classification, licensing determination, or live screening — and it deliberately does not movedecision_readiness_scoreorrisk_signal, which stay structural (a contract test asserts a dual-use vs. benign cargo yields the same score/signal). Surfaced through existing free-string response fields only, so no schema change and no dual-copy path touched; mirrored byte-for-wording in the Cloudflare Worker JS parity (deploy/cloudflare-worker/src/index.js). New Python contract tests (positive flag + score-invariance) and two JS worker parity tests; ADR 0003 freeze intact. Activation:wrangler deploy --env middle-corridor-deal-risk-gate— until then the live route keeps the prior output. -
feat(market-entry):
route_to_committeegate decision (ADR 0019). The market-entry gate previously collapsedcommittee_review_readyandlaunch_commitment_readyonto the sameescalate_before_signatureverdict, so a signature-grade file with open operational/sector gaps read as alarmingly as a fully complete one. Adds one value,route_to_committee, to the responsegate_decisionenum and remapscommittee_review_ready -> route_to_committee(leavinglaunch_commitment_ready -> escalate_before_signature). Additive output-enum extension to the market-entry response schema only — no request-contract change, no touch to the frozen v1.0.x request/memo family,x-schema-versionstays1. Mirrored in the Python service and the Cloudflare Worker JS parity; dual-copydata/response schema synced; new contract/service + worker tests assert both the committee and the complete-file mappings; worker redeployed. -
chore(reporting): migrate the deal-risk PDF renderer off the deprecated fpdf2
ln=parameter tonew_x=XPos.LMARGIN, new_y=YPos.NEXT(fpdf2 >= 2.7, the declaredpdf-extra floor). Output is identical; clears the local mypy deprecation diagnostics that appear when the optionalpdfextra is installed (CI's.[dev]env does not install fpdf2, so this was never a CI failure). -
feat(market-entry): real sector differentiation, tailored watch-next, and input-aware claim audit for the Kazakhstan market-entry readiness gate. Live-testing the demo surfaced that the gate treated
sectoras cosmetic — every sector (renewable_energy, epc, infrastructure, data_center, technology_transfer, distribution, …) returned the same generic checklist — and thatwatch_nextwas a static 20-item dump whileclaim_auditignored caller-suppliedknown_blockers/known_assumptions. Additive fix across both runtimes (Python serviceservices.kazakhstan_market_entry_readinessand the Cloudflare Worker JS parity indeploy/cloudflare-worker/src/index.js): (1) asector_requirementsmap in the source taxonomy folds sector-specific required evidence into the launch-commitment ceiling and the evidence-gap list, so a renewable file now surfaces grid-connection/offtake and land/site-control gaps, a technology-transfer file surfaces IP-ownership and export-control gaps, etc.; (2)watch_nextis now built from the sector's indicators plus the indicators for tiers that still have gaps plus one always-on regulator signal (sector_watch_indicators/tier_watch_indicatorsin the taxonomy), de-duplicated — no longer a static dump; (3)claim_auditappends anunsupportedblocker claim when the caller named blockers and anassumption_onlyclaim when assumptions were supplied. Four newsource_typeenum values added additively to the request schema (grid_connection_and_offtake_evidence,land_or_site_control_evidence,ip_ownership_and_licensing_evidence,export_control_classification_note) with curated evidence-gap copy. No response-schema shape change;gate_decision/readiness_labelenums unchanged (committee_review_ready and launch_commitment_ready still both route toescalate_before_signature, which the frozen enum constrains). Dual-copydata/schema + taxonomy updated in sync. New contract + service tests (sector gaps differentiate, watch-next tailored, claim audit reflects inputs, sector evidence caps launch commitment, every sector enum value has a requirement list) and JS-parity worker tests; Python 324 passed, worker suite 106/106 green. Demo page (kazakhstan-market-entry-readiness.htmlon the portfolio site) exposes the new sector evidence categories. -
feat(worker): Cloudflare Worker JS parity + dedicated env for the Kazakhstan market-entry readiness gate (deploy-ready). Companion to the in-repo worker (next entry), which gave it a Python service / HTTP / A2A surface but no published endpoint. The deployed A2A Worker (
deploy/cloudflare-worker/src/index.js) now carries a JS port ofkazakhstan_market_entry_readinessso the gate can run as its own*.workers.devendpoint like the other four. Adds the profile constants/URLs, the staged source-requirement tier arrays + stage→tier map + commitment-stage set, the curated signature-tier evidence-gap copy,marketEntryReadinessResult(deterministic gate decision / readiness label / evidence gaps / claim audit / owner actions / watch-next, byte-matching the Python wording), the request shape guard + enum validation (marketEntryEnumErrorsover sector / decision_stage / counterparty role /supplied_sources[].source_type), the agent-card profile block (applyMarketEntryReadinessProfile), and the dispatch wiring inagentProfile(newmarket_entry_readinessprofile, hostkazakhstan-market-entry-readiness-a2a),applyAgentProfile, and themessage/sendhandler. A new[env.kazakhstan-market-entry-readiness]inwrangler.toml(AGENT_PROFILE = "market_entry_readiness") — thekazakhstanprofile key was already taken by the Middle Corridor gate, so a distinct key was required.run_provenanceis intentionally omitted worker-side (the response schema makes it optional; same deferral as the other workers' worker-side provenance). 5 new worker tests (agent card exposes the skill;message/sendreturnsproceed_to_validation/validation_readyon the golden; empty-evidence-at-commitment-stagestop; badsource_typeenum rejected; non-market-entry shape rejected), worker suite 102/102 green. Worker JS + config + test only; no Python service, schema, or dual-copy path touched. Activation:wrangler deploy --env kazakhstan-market-entry-readiness— the one remaining step, run from an account with Cloudflare credentials; until then the endpoint is configured but not live. -
feat(market-entry-readiness): promote the Kazakhstan market-entry pack from contract-only to a live in-repo vertical worker. The schemas, source taxonomy, use-case doc, and contract example shipped earlier (#144–#147) but had no executable surface; this adds the layer that makes it callable like the other four workers. New
kazakhstan_market_entry_readinessservice function inservices.pygrades a market-entry file against the staged source-requirement taxonomy (required_before_validation→_signature→ stage-relevant operational tier), returning agate_decision(proceed_to_validation/pause_for_evidence/escalate_before_signature/not_decision_ready/stop), areadiness_label, evidence gaps with owner/next-action/decision-blocked, a claim audit, owner actions, watch-next indicators from the taxonomy, and mandatoryhuman_review_required+boundary_notice. The gate decision is deterministic from coverage anddecision_stage, never green-lights signature (that stays human review), and hardens tostopwhen a commitment-stage file arrives with no validation-tier evidence. Wired into the existing deployed surfaces: HTTPPOST /v1/market-entry/readiness(+ listed in/readyz) and A2A profilekazakhstan_market_entry_readiness(capability + aliases, agent-card skill, supported-contracts list, params builder, artifact text, dispatch). Tests:tests/test_market_entry_readiness_service.pyexercises a golden request (→proceed_to_validation/validation_ready, schema-valid, signature-tier gaps surfaced), an empty-evidence-at-commitment-stagestopcase, an invalid-request rejection, the HTTP route (200 + 400),/readyz, and the A2A dispatch + agent card; the prior static contract test is unchanged. Internal evidence triage only — not legal, compliance, customs, tax, financial, investment, insurance, sanctions, or launch-authorization advice. Additive, non-breaking; no schema change (request/response schemas already shipped), no new dual-copy files, ADR 0003 freeze intact. No Cloudflare deploy in this change: unlikegulf-maritime-exposure, this worker has no dedicated published Worker URL yet — it runs on the shared service / HTTP / A2A layer; a standaloneworkers.devendpoint is a separate follow-up requiringwrangler deploy. -
feat(reporting): deal-risk evidence-readiness memo renderer +
deal-reportCLI (md/html/pdf). Additive, non-breaking. Newagenda_intelligence.reportingmodule renders a Middle Corridor deal-risk response (the structuredmiddle_corridor_deal_risk/ live A2A worker contract) as a branded evidence-readiness memo — the deliverable behind the concierge offer. Markdown and self-contained, print-to-PDF-ready HTML carry no third-party dependencies; PDF usesfpdf2, declared as the optionalpdfextra (pip install agenda-intelligence-md[pdf]) so the core package stays dependency-light. Newagenda-intelligence deal-report <response.json> --format md|html|pdf [--out FILE]CLI subcommand. Reformat only: it surfaces the worker's ownoperational_decision/ score / evidence gaps / risks / flags / watch-next verbatim, invents nothing, performs no factual-truth verification, and rides thenot_advice_notice+ human-review disclaimer on every artifact (brand verdict colours: proceed green, hold / conditions amber, escalate red). Contract test intests/test_deal_report.py(md/html across the golden responses; pdf guarded by the optional extra). No schema, service, or worker surface touched; ADR 0003 freeze intact. -
fix(cis): surface the OpenSanctions attribution only when upstream data was actually used. The
cis_secondary_sanctionsservice and the deployed Cloudflare Worker appended the CC-BY OpenSanctions attribution notice ("Sanctions list matches via OpenSanctions…") tolimitationson every run where the upstream adapter returned an attribution block — including thedisabled/degraded/ zero-match paths, whereauto_fetched_sourcesis empty and no upstream data was used. That contradicted the adjacent "live retrieval not enabled" note and could read as a sanctions-list match that never happened. Both implementations now gate the attribution on actual use (auto_fetched_sourcesnon-empty /autoFetched.length): CC-BY attribution is only required when the upstream data is redistributed, so the disabled / zero-match output is now both honest and license-correct. Two tests that asserted the buggy behaviour (tests/test_cis_secondary_sanctions_contract.py,deploy/cloudflare-worker/test/worker.test.js) are converted to regression guards — degrade note present, attribution absent. Python suite + worker (97/97) green. Live activation: the worker fix reaches the livecis-secondary-sanctions-a2aendpoint only afterwrangler deploy --env cis-secondary-sanctions(no deploy-on-merge); the Python package path (MCP / HTTP / local) is fixed immediately. -
feat(middle-corridor): operational booking decision on the deal-risk response (logistics-facing). Additive, non-breaking.
middle_corridor_deal_risknow emits anoperational_decisionobject —{decision, applies_to, rationale}wheredecisionis one ofproceed/proceed_with_conditions/hold/escalate— derived from the existingdecision_readiness_score(40/70 bands),risk_signal,triage_recommendation, anddecision_stage. It restates the existing triage as the booking verb a forwarder / ops reader needs (do we quote, hold, or escalate?) without changing the score, the signal, the triage recommendation, or any other field. Boundary preserved: triage routing only, never a hard reject (a compliance/legal call) — the gate stops at hold/escalate — and human review remains required. New optional object onmiddle-corridor-deal-risk-response.schema.json(and packaged copy undersrc/agenda_intelligence/data/); Cloudflare Worker JS parity indealRiskContractResponseForRequestplus a human-readable summary line; a workedoperational_decisionadded to the response schema'sexamplesblock; one golden + one off-enum failure contract test added intests/test_middle_corridor_contract.py, plus one worker parity test. ADR 0003 freeze intact (response-family additive field, not a request/memo change). Activation:wrangler deploy --env middle-corridor-deal-risk-gate(no deploy workflow runs on merge; until then the live route keeps the prior output). -
feat(worker): Middle Corridor worker parity for the route sanctions-exposure and customs-harmonization layers. The deployed Cloudflare Worker (
middle-corridor-deal-risk-gate-a2a) now emitsroute_sanctions_exposure_indicators,customs_harmonization_indicators, and the optionalroute_sanctions_matched_segments(with itslimitationsline) at the live/message/sendendpoint, matching the Python service contract below. Substring presence-flagging on the route string only; per ADR 0015 not a sanctions determination, live screening, or customs/legal advice. Worker JS + two parity tests (96/96 green); no schema or service-layer change. -
feat(middle-corridor): route-level sanctions-exposure and customs-harmonization screening layers. Additive, non-breaking.
middle_corridor_deal_risknow ships two standing checklists on every response —route_sanctions_exposure_indicators(Iran-transit legs and Russia Northern Corridor overlaps grounded in OFAC Iran/Russia programs, sanctioned Caspian operators, onward connections into a sanctions-relevant jurisdiction) andcustoms_harmonization_indicators(permitting clarity, harmonized digital-customs coverage via eTIR vs. unharmonized national permitting) — plus an optionalroute_sanctions_matched_segmentspopulated when the declared route text names a flagged segment, which also adds onelimitationsline. Substring presence-flagging on the route string only; per ADR 0015 this is evidence-gap triage routed to human review, NOT a sanctions determination, live screening, or customs/legal advice. Three new optional fields added tomiddle-corridor-deal-risk-response.schema.json(and packaged copy); two contract tests added. Existing fields and the decision-readiness score unchanged. -
fix(worker):
wrangler dev --localstartup — movePROBE_PROMPT_CHAR_THRESHOLDout of the entry-module exports. Found during a 2026-06-12 usage-instrumentation debugging pass:wrangler dev --env middle-corridor-deal-risk-gate --localfailed to start because current workerd treats every named export of the entry module as a worker entrypoint and rejects non-function exports (Incorrect type for map entry 'PROBE_PROMPT_CHAR_THRESHOLD': the provided value is not of type 'function or ExportedHandler'). The deployed runtime tolerates the export, so production was unaffected — only local dev was broken. The constant moves todeploy/cloudflare-worker/src/usage_constants.js;src/index.jsimports it and drops it from its export block;test/worker.test.jsimports it from the new module. Behavior identical, 94/94 worker tests green,wrangler dev --localstarts and serves. Worker JS + test only; no schema, service, or contract surface touched. -
docs(canon): market-entry-readiness contract surfaced in AGENTS.md and llms.txt. Output of a 2026-06-10 repo test-and-review pass (full local CI gate, 94/94 Worker JS tests, live smoke of all five A2A agent cards plus a Middle Corridor
message/sendround-trip — all green). The one gap found was discoverability: the Kazakhstan market-entry readiness contract (shipped across #144–#147) was documented in README.md but absent from the two canon surfaces agents actually read — AGENTS.md (canonical project contract) and llms.txt (agent-readable index, dual-copied). An agent reading AGENTS.md could not learn the contract exists, and the "vertical worker MUST ship with a service function" rule made the contract-only state look like a violation rather than a recorded decision. AGENTS.md gains a Contract-only pack (not a vertical worker yet) entry under "Vertical workers inside this repo" stating exactly what ships (schemas, taxonomy, use-case, examples, static contract test) and what does not (no service function, HTTP route, A2A profile, or MCP tool), with the boundary that the MUST-ship checklist applies the day it gains a service function. llms.txt gains the matching contract-only block after the MCP worker tools (both dual-copy locations, byte-identical). Documentation only; no schema, service, worker, or test surface touched; ADR 0003 freeze intact. -
feat(market-entry-readiness): counterparty-integrity and bank-onboarding evidence types (pain pass 3). Third practitioner pain-discovery pass (2026-06-10): the taxonomy modelled who a counterparty is (registry extract, beneficial ownership) but not whether engaging them is clean, and it assumed banking without the onboarding friction that actually gates operations. Two cross-sector, pre-signature blockers a foreign parent routinely under-scopes: (1) integrity / anti-corruption due diligence on distributors, agents, and government-facing intermediaries — under the FCPA (enforcement resumed mid-2025 after a pause) and the UK Bribery Act the foreign parent can carry liability for an intermediary's conduct, so a partner who touches customs, certification, or akimat without integrity DD is an unmanaged exposure; and (2) corporate bank-account / KYC onboarding — opening an account for a foreign-owned entity requires a full UBO pack (apostilled), source-of-funds and expected-turnover statements, and often physical presence, and until it clears the entity cannot pay suppliers or receive revenue. Adds two
source_typeenum values —counterparty_integrity_due_diligenceandbank_account_and_kyc_onboarding— mapped intorequired_before_signature, plus twowatch_indicators. Use-case minimum-evidence bullets and the contract example demonstrate both gaps. Presence-flagging and routing only — never a clearance, a fit-and-proper determination, or sanctions advice (that stays the CIS secondary-sanctions worker's contract); human review remains required. Schema + taxonomy dual-copied;tests/test_market_entry_readiness_contract.pyextended with an integrity/banking enum-and-taxonomy guard. Additive, non-breaking; still a schema / source-taxonomy / use-case contract, not a deployed live worker; ADR 0003 freeze intact. -
feat(market-entry-readiness): trademark / brand-protection and data-localization evidence types (pain pass 2). Second practitioner pain-discovery pass (2026-06-10), surfaced by running a real brand-heavy distribution proposal through the contract: a foreign entrant plans heavy public brand promotion and customer/lead/app data capture, but the taxonomy had no evidence type for either intellectual-property protection or data-localization compliance — both commonly-missed, cross-sector, pre-public-launch blockers. Kazakhstan is a first-to-file trademark jurisdiction inside the EAEU regional system, and brand-squatting against foreign (notably Chinese) applicants has risen sharply, with most disputes surfacing within months of a brand's first promotion; separately, Kazakhstan personal-data localization can require citizen data to be stored in-country (including backups) and can apply even through a distributor without a local entity. Adds two
source_typeenum values —trademark_or_brand_protection_filinganddata_localization_and_privacy_note— mapped intorequired_before_showroom_or_public_launch(both are needed before brand spend / data capture, not before signature), plus twowatch_indicators(third-party trademark filing or brand-squatting signal,personal-data localization or privacy rule change). The use-case minimum-evidence list gains the matching bullets, and the contract example demonstrates both gaps. Presence-flagging and routing only — never an IP-clearance opinion or a data-compliance determination; human review remains required. Schema + taxonomy dual-copied;tests/test_market_entry_readiness_contract.pyextended with an IP/data enum-and-taxonomy guard. Additive, non-breaking; still a schema / source-taxonomy / use-case contract, not a deployed live worker; ADR 0003 freeze intact. -
feat(market-entry-readiness): cross-sector regulatory-setup evidence types + contract test + inline-example fix. Output of a 2026-06-09 practitioner pain-discovery pass on the just-added Kazakhstan market-entry readiness contract (#144). The original
source_typetaxonomy leaned heavily on a mobility / EV go-to-market path (showroom, dealer, test-ride, battery, spare-parts) and under-covered the cross-sector regulatory-setup blockers a foreign company hits before commitment regardless of sector: permanent-establishment / tax-residency treatment (branches are treated as residents; the entry model can create a taxable presence), currency-control and profit-repatriation reporting (currency-contract registration and repatriation thresholds gate how money moves in and out), the foreign-worker quota and local-national employee ratio, local-content / procurement-localization (production-facility and pre-qualified-bidder requirements for government and quasi-government tenders), and special-economic-zone eligibility as a cost / hiring lever. Adds fivesource_typeenum values —permanent_establishment_or_tax_residency_assessment,currency_control_and_repatriation_note,work_permit_and_local_employment_quota_note(mapped intorequired_before_signature), pluslocal_content_or_procurement_localization_noteandspecial_economic_zone_eligibility_note(mapped intohelpful_context/supporting_sources) — and four newwatch_indicators. The use-case doc gains the matching minimum-evidence bullets, and the contract example request/response demonstrate the permanent-establishment and currency-control gaps concretely. Sanctions / secondary-sanctions exposure is deliberately not added here — that stays the CIS secondary-sanctions worker's contract (portfolio coherence). Fixes the use-case "Output shape" inline example, which was missing the schema-requiredowner_actionsfield, so an agent or practitioner copying it as a template would have emitted an invalid response. Addstests/test_market_entry_readiness_contract.py: this contract-only worker (no service function yet) previously had zero CI schema-conformance coverage becausevalidate_public_examples.pyskips commercial fixture dirs — the new test validates the example and the inline-doc examples against the schemas, asserts the taxonomy stays a subset of the request enum, and guards the dual-copy sync (it is the check that would have caught theowner_actionsbug). Schema + taxonomy dual-copied. Additive, non-breaking; still a schema / source-taxonomy / use-case contract, not a deployed live worker; ADR 0003 freeze intact (new v1 schema family, not a change to frozen schemas). -
feat(worker): Cloudflare Worker JS parity for the Gulf price-cap attestation gap (deployed). Closes the deferral from the preceding entry — ports the
price_cap_attestation_or_recordkeepinghandling to the deployed A2A Worker (deploy/cloudflare-worker/src/index.js) so the livegulf-maritime-exposure-a2aendpoint emits the same triage as the Python service. Adds the value toGULF_SOURCE_TYPES(the worker'sgulfEnumErrorsvalidation enum — without this the live route would reject a request supplying the new source type, the same enum-parity bug previously fixed for Middle Corridor); whenrussia_oil_price_capis inexposure_facetsand the attestation is not supplied,gulfTopExposureDimensionssurfaces the per-loading attestation + itemized ancillary-cost recordkeeping gap andwatch_nextgains the price-cap attestation watch line, byte-identical to the Python wording. Not added to the worker readiness denominator (GULF_MARITIME_HELPFUL_CONTEXT), sodecision_readiness_scoreis unchanged. 2 new worker tests (gap surfaces when facet present + attestation absent; supplying the attestation clears the gap and leaves the score unchanged), 94/94 worker tests green. Worker JS + test only; no Python service, schema, or dual-copy path touched. Activation:wrangler deploy --env gulf-maritime-exposure(deployed in this change). -
feat(gulf_maritime_exposure):
price_cap_attestation_or_recordkeepingevidence type + per-loading attestation gap surfacing. Output of a 2026-06-08 practitioner pain-discovery pass against OFAC's Russian oil price-cap guidance (tiered attestation model, Dec 20 2023 update): a service provider must obtain a price-cap attestation from its counterparty prior to each loading or lifting and retain itemized ancillary-cost records — that attestation + recordkeeping process is the safe-harbor mechanism. The worker already scopedrussia_oil_price_capas an exposure facet but had no first-class evidence type for the attestation, no gap surfacing, and no watch indicator — a coverage hole in an existing facet that a technical evaluator inspecting the contract would notice. Addsprice_cap_attestation_or_recordkeepingto the requestsource_typeenum (dual-copied; the response schema does not constrainsource_type, so it is untouched). Whenrussia_oil_price_capis inexposure_facetsand that evidence is not supplied,top_exposure_dimensionssurfaces"per-loading price-cap attestation and itemized ancillary-cost recordkeeping not yet evidenced (OFAC tiered safe-harbor)"andwatch_nextgains a"price-cap attestation refusal, withdrawal, or itemized ancillary-cost gap"line. Presence-flagging routed to human review only — never a determination that the cap was met or breached, and not a safe-harbor opinion. Deliberately NOT added torequired_before_go/must_check(added to taxonomysupporting_sources/helpful_context), so thedecision_readiness_scoredenominator and ADR 0003 comparability are preserved — a contract test asserts that supplying the attestation clears the gap note without moving the score. Schema + taxonomy dual-copied. 2 new contract tests (gap surfaces when facet present + attestation absent; supplying the attestation clears the gap and leaves the score unchanged). Additive, non-breaking; ADR 0003 freeze intact. Deferred: Cloudflare Worker JS parity for the livegulf-maritime-exposure-a2aendpoint — until a follow-upwrangler deploy, the live route keeps the prior output. -
feat(mcp): all-errors validation,
get_schemadiscovery tool, andgulf_maritime_exposureas the fourth MCP worker. Output of an agent-consumer self-review of the live MCP surface (the channel an agent-integrator actually calls). Three fixes. (1) All schema errors at once —validate_brief/validate_evidence/validate_memo(and the vertical-worker request validation) returned only the first missing required field, forcing an agent constructing a payload to round-trip once per field. The three near-duplicate validators (mcp_server._validate_json,services._validate_json,product._validate) now usejsonschema'svalidator_for(schema).iter_errors(...), deterministically sorted by(path, message), soerrorslists every violation in one call. ImportError / schema-load-failure tri-state (valid: Nonewith the reason inerrors) is preserved exactly. (2)get_schemaMCP tool (12th validation-layer tool) — closes the discover → construct → validate loop on the MCP surface: an agent could discover protocols/lenses/signals but not the contracts it had to satisfy. Returns a packaged JSON Schema by manifest key (agenda_brief), file name, or bare stem; omitnameto list available schemas. The registry is read fromagent-manifest.json(ADR 0013 authoritative schema registry), so it never drifts fromschemas/v1/. Contract discovery only — does not validate, template, or verify truth. (3)gulf_maritime_exposureas an MCP tool — the fourth vertical worker was live on HTTP/A2A and present inservices.pybut was the one worker not exposed over stdio MCP; this brings worker parity on the MCP surface to 4/4. Manifestmcp.toolsupdated in both dual-copy locations fromTOOLSdirectly (ADR 0012 parity invariant holds; names match code order,input_schemabyte-equal). Tests: gulf golden round-trip + worker-list assertion extended,get_schema(named/aliases/list/unknown + stdio call), multi-error validation. MCP.md + counts (19→21 tools) updated. Python + docs only; noschemas/v1/contract, request/memo shape, or Worker JS touched; ADR 0003 freeze intact. Deliberately not added: alist_workerscatalog tool — the workers are already first-class MCP tools (discoverable viatools/list) and their HTTP routes / A2A profiles / endpoints live authoritatively ina2a_adapter.py/http_api.py; a separate catalog would duplicate that and invite drift. Activation: the installedagenda-intelligence-mcpserver must be reinstalled/redeployed to surface these (a stale install predating this change exposes 16 tools without the workers). -
docs(examples/kazakhstan-middle-corridor): contract example fixtures for
counterparty.specified_sectors[]andcounterparty.date_of_formationflagging. Two new example pairs underexamples/kazakhstan-middle-corridor/contract/—pre_signature_escalate_named_sector.{request,response}.jsonandpre_signature_escalate_newly_formed.{request,response}.json— generated end-to-end through the livemiddle_corridor_deal_riskservice function so eachresponseis byte-identical to what the contract emits today. The first shows a KZ-domiciled consignee withspecified_sectors: ["manufacturing", "technology"]triggering"counterparty operates in an OFAC-named sector under EO 14024"intop_risks+ matchingexposure_layers.foreign_sanctions_exposure_layer+ EO 14024 / EO 14114limitationsline; the second shows a KZ-domiciled consignee withdate_of_formation: "2023-08-12"triggering"counterparty newly formed in a transshipment-risk jurisdiction"and the matching exposure-layer / limitations entries. Both scoreescalate_before_signature/medium_high. Existing fixture-validation tests (test_middle_corridor_request_fixtures_validate,test_middle_corridor_response_fixtures_validate,..._include_not_advice_notice,..._include_readiness_score) auto-discover and exercise the new files, 31/31 green locally. Documentation / discoverability only; no schema, service, worker, or contract surface touched. -
feat(worker): Cloudflare Worker JS parity for
counterparty.specified_sectors[]andcounterparty.date_of_formationOFAC FFI sanctions-exposure flagging. Companion to the Python feature on the same fields (preceding entry). The deployed A2A Worker's JS port ofmiddle_corridor_deal_riskdid not know about the two new optionalcounterpartyfields, so a caller hitting the livemessage/sendendpoint withspecified_sectors[]ordate_of_formationgot back the previous response without the new flags. Mirrors the Python service: addsNAMED_SECTORS(the OFAC FAQ 1148 / 1151 five sectors),NEWLY_FORMED_COUNTERPARTY_CUTOFF(2022-02-24), andTRANSSHIPMENT_HUB_JURISDICTIONS(Kazakhstan, China, Hong Kong, Cyprus) constants; addsnamedSectorCounterparties()andnewlyFormedCounterparties()helpers; extendstopRisksForStructuredRequest,exposureLayersForStructuredRequest, anddealRiskContractResponseForRequestto surface"counterparty operates in an OFAC-named sector under EO 14024"and"counterparty newly formed in a transshipment-risk jurisdiction"intop_risks+ matchingforeign_sanctions_exposure_layerentries + matchinglimitationslines, byte-identical to the Python output. Worker JS only; no Python service, schema, dual-copy path, ordecision_readiness_score/risk_signal/ triage / counterparty-readiness touched. 4 new worker tests assert sector positive + sector-other-only negative + newly-formed positive + pre-2022 formation negative on structureddealRiskContractResponseForRequestround-trips, all matching the Python contract-test names and string assertions. Activation:wrangler deploy --env middle-corridor-deal-risk-gate(no deploy workflow runs on merge; until then the live route keeps the prior strings). -
feat(middle_corridor_deal_risk): optional
counterparty.specified_sectors[]andcounterparty.date_of_formationfor OFAC FFI sanctions-exposure flagging. Two non-breaking additive optional fields on the request and responsecounterparty$defs(and dual-copied undersrc/agenda_intelligence/data/schemas/v1/), drawn from the OFAC Sanctions Advisory "Updated Guidance for Foreign Financial Institutions on OFAC Sanctions Authorities Targeting Support to Russia's Military-Industrial Base" (June 12, 2024) and OFAC FAQs 1148 / 1151.specified_sectors[]enumerates the five named sectors of the Russian Federation economy (technology,defense_and_related_materiel,construction,aerospace,manufacturing) plus anothervalue; a counterparty operating in any non-othervalue triggers a newtop_risksentry"counterparty operates in an OFAC-named sector under EO 14024", a matchingexposure_layers.foreign_sanctions_exposure_layerline, and alimitationsentry citing EO 14024 as amended by EO 14114.date_of_formation(ISO 8601 date); when on or after the 2022-02-24 cutoff (Russia's further invasion of Ukraine) and the counterparty's jurisdiction matchesHIGH_RISK_JURISDICTIONS,CIRCUMVENTION_WATCH_JURISDICTIONS, or the newTRANSSHIPMENT_HUB_JURISDICTIONSlist (Kazakhstan, China, Hong Kong, Cyprus — drawn from U.S. Treasury and BIS designations of third-country transshipment hubs), the response surfaces"counterparty newly formed in a transshipment-risk jurisdiction"mirroring the OFAC advisory's"EXAMPLE OF HIGHER RISK CUSTOMER: A microelectronics exporter formed in March 2022 located in a high-risk jurisdiction"red flag. Both are presence flags routed to human review — never a sanctions determination, never an end-use ruling. Neither field changesdecision_readiness_score/risk_signal/triage_recommendation; neither alters existing high-risk / circumvention-watch flagging. Touches: request + response schemas + dual-copies, two new helpers (_named_sector_counterparties,_newly_formed_counterparties), extended signatures of_middle_corridor_top_risksand_middle_corridor_exposure_layers, 4 new contract tests (sector positive + sector-other-only negative + newly-formed positive + pre-2022 formation negative), and a use-case doc paragraph. ADR 0003 v1.0.x freeze intact — fields are optional and additive. Deferred: Cloudflare Worker JS parity for the livemessage/sendendpoint, following the deferred-deploy pattern used for Caspian capacity language andrun_provenance; until that ships the live route does not surface the new flags. -
docs(use-cases/kazakhstan-middle-corridor): sync sample
top_risks/watch_nextto the new Caspian capacity / draft language. The use-case doc's "Output shape" example block still carried the pre-fix strings ("Caspian chokepoint dependency"intop_risks, no Caspian-capacity item inwatch_next), so the public-facing illustration disagreed with what the Python service and the deployed Worker now emit. Updates the example to"Caspian crossing capacity and draft exposure"and inserts"Caspian ferry-slot, tonnage, or draft notice"into the samplewatch_nextarray, matching the now-live output. Docs only; no code, schema, or contract touched. -
fix(worker): Cloudflare Worker JS parity for the Caspian capacity / draft language fix. Companion to the Python text fix on the same templates (preceding entry). The deployed A2A Worker's JS port of
middle_corridor_deal_riskcarried the same generic strings —topRisksForStructuredRequestset"Caspian chokepoint dependency"and thewatch_nexttemplate named only"port delays or operator notices"— so a caller hitting the livemessage/sendendpoint still got the boilerplate wording after the Python service was fixed. Replaces the top-risk string with"Caspian crossing capacity and draft exposure"and inserts"Caspian ferry-slot, tonnage, or draft notice"into the Workerwatch_nexttemplate, matching the Python output. Worker JS only; no Python service, schema, dual-copy path, ordecision_readiness_score/risk_signal/ triage touched. 1 new worker test asserts both strings on a structuredmessage/sendround-trip. Activation:wrangler deploy --env middle-corridor-deal-risk-gate(no deploy workflow runs on merge; until then the live route keeps the prior strings). -
fix(middle_corridor_deal_risk): surface practitioner-named Caspian capacity language in
top_risksandwatch_next. Output of a 2026-06-07 pain-discovery pass against a LinkedIn write-up of a Trans-Caspian Corridor practitioner discussion (CPCS / TRANSEXPEDITION / BBM Logistics / GreenLine / TransConsulting / Hegelmann / TURKSIB Magistral). Practitioners name three concrete Caspian failure modes — ferry-slot scarcity, ferry tonnage shortage, climate-driven sea-level / draft decline — that the worker already accepts asport_operator_notice/rail_capacity_or_border_wait_sourceevidence and triages under a generic "Caspian chokepoint dependency" risk and "port delays or operator notices" watch item. Generic wording did not echo the practitioner vocabulary back, so the output read as boilerplate rather than relevant. Replaces"Caspian chokepoint dependency"with"Caspian crossing capacity and draft exposure"in the hardcodedtop_riskstemplate and inserts"Caspian ferry-slot, tonnage, or draft notice"intowatch_next. No schema change, no new field, no change todecision_readiness_score/risk_signal/ triage / counterparty-readiness; two contract example fixtures + schema examples (dual-copied) updated to match the new output strings. Text-only relevance fix; ADR 0003 freeze intact. -
feat(middle_corridor_deal_risk): deterministic
run_provenancecontent-provenance stamp on responses (ADR 0018). As generation gets cheaper, the scarce layer is verifiability of process, not the analysis text. The response was evidence-rich but did not record which contract produced it from which input, so a downstream reviewer (compliance committee, correspondent bank, auditor) handed the artifact could not confirm it is reproducible. New optionalrun_provenanceobject onmiddle-corridor-deal-risk-response.schema.json(dual-copied), emitted by a shared service-layer helper:contract_version(theagenda_intelligencepackage / ruleset version),schema_id(the response schema$id), andinput_digest(sha256:over the canonicalized request JSON — UTF-8, keys sorted, no insignificant whitespace, so the same input + same contract reproduces the same digest). Digest is over the request (the reproducible relation "this output came from this exact input under this ruleset"), not the response. Deliberately carries no timestamp — wall-clock time is a transport concern (the A2A JWS envelope already timestamps, ADR 0017); the stamp stays purely deterministic so it is reproducible. Reproducibility / traceability only — explicitly not a signature of authenticity (that is the JWS transport layer), and not a factuality, clearance, or compliance attestation; the non-advice and human-review boundaries are unchanged. No change todecision_readiness_score/risk_signal/ routing. Additive, optional → ships in a minor version under the ADR 0003 freeze (new optional field; existing responses and callers remain valid). 2 new contract tests (stamp emitted + schema-valid with correct version / schema_id / digest shape; digest is deterministic for the same request and changes when the input changes). Deferred (each its own change, recorded in ADR 0018): Cloudflare Worker JS parity for the live endpoint (the JS port must implement the same canonicalization to reproduce byte-identical digests, not a bareJSON.stringify), and extendingrun_provenanceto the other three vertical workers via the same helper. -
fix(worker): accept the four newer EDD source types on the live Middle Corridor A2A surface (enum parity). The deployed Cloudflare Worker's
MC_SOURCE_TYPESenum (used bymiddleCorridorEnumErrorsto validatedated_sources[].source_type) was narrower than the Pythonmiddle-corridor-deal-risk-request.schema.json: it omittedend_user_or_reexport_evidence,source_of_funds_or_wealth_evidence,pep_screening_evidence, andbusiness_substance_evidence. The response-side checklist logic (reexport_control_indicators,source_of_funds_indicators,pep_screening_indicators,front_company_indicators) and constants were already ported and surface correctly when evidence is absent — but a structuredmessage/sendrequest that supplied one of these types to mark the evidence present was rejected with an off-enum error before reaching the contract builder, so a caller could not suppress a checklist or present that evidence on the live endpoint. Adds the four values to the worker enum (now matching the schema). No change todecision_readiness_score/risk_signal(these types remain outsiderequired_before_go), and the Python service / schemas were already correct and are untouched. 1 new test exercises the fullhandleJsonRpcenum-validation path (the existing omit-when-supplied tests call the builder directly and bypassed it): supplying all four types is accepted (TASK_STATE_COMPLETED, not invalid) and each corresponding checklist is omitted. Activation:wrangler deploy --env middle-corridor-deal-risk-gate(no deploy workflow runs on merge). Worker JS + test only; no Python, schema, or dual-copy path touched. -
fix(services, http, product): distinguish "could not validate" from "invalid", and label keyless
analyzeas host-completion. Two robustness fixes on error/edge paths; no success-path contract change. (1)_validate_json's missing-jsonschema branch returned the reason undererror(singular) while every caller readerrors(plural), so a validation-infrastructure failure surfaced asvalid: False, errors: []— indistinguishable from "invalid request, no reason given", and the vertical-worker wrappers collapsedvalid is NoneintoFalse. The branch now useserrors; a new_validation_failurehelper makes the four vertical workers (middle_corridor_deal_risk,agentic_interaction_trust,cis_secondary_sanctions_exposure,gulf_maritime_exposure) andaudit_claimspropagate the tri-state (True/False/None) with the reason always inerrors; response-side validation stopsbool()-collapsingNonetoFalse. The HTTP shell now maps validation-unavailable (valid is None, a server fault) to 500, keeping schema-invalid requests at 400. (2)analyzenow returns amodefield —"host_completion"when no model was invoked (ANTHROPIC_API_KEY unset / SDK absent; the caller completes fromsystem_prompt) and"server_completed"when the model ran here — and the keyless skeleton'smemo_errorsmessage states plainly this is expected, not a failure. Python-only; no schema file, request/memo contract, dual-copy path, or Worker JS touched (the JS Worker does not use jsonschema). 9 new tests (tri-state helper + infra-reason surfacing + worker validation-unavailable; HTTP 500-vs-400 mapping; analyzemodeboth branches). Additive, non-breaking; ADR 0003 freeze intact. -
docs: surface all live vertical-worker A2A endpoints in README + sync worker count. All four vertical workers (Middle Corridor Deal Risk Gate, CIS Secondary-Sanctions Exposure, Agentic Interaction Trust Gate, Gulf Maritime Exposure) plus the general-triage wrapper are deployed and live on Cloudflare Workers, each serving its own profile agent-card; the README live-wrapper block listed only two. Adds the CIS / Agentic / Gulf live endpoints and their Agenstry listings to the live block, updates the intro inventory ("three" -> "four vertical workers"), and corrects the Status table deployment count (2 -> 5 workers). Also updates AGENTS.md (Gulf Worker JS parity is shipped + endpoint live) and llms.txt (adds
gulf_maritime_exposureto the worker list). Docs only; no code, schema, or contract change. -
feat(middle_corridor_deal_risk):
front_company_indicatorsbusiness-substance checklist +business_substance_evidencesource type. Closes a gap surfaced in a 2026-06-04 practitioner pain-discovery pass against the EU Sanctions Helpdesk red-flags guidance: the counterparty-legitimacy / front-company cluster (recently established or no business background, little or no web presence, addresses shared with multiple companies, goods that do not fit the line of business, contact only via an intermediary with broad power of attorney) was the one red-flag cluster the worker did not represent — the ownership chain and shell/layered-structure facets live on thecis_secondary_sanctionsworker, but the Middle Corridor counterparty-substance signals did not. Same non-breaking pattern aspep_screening_indicators/source_of_funds_indicators(ADR 0015): newbusiness_substance_evidencevalue added to the request + responsesource_typeenums and the taxonomyhelpful_context/supporting_sources(+ abusiness substance or front-company concernwatch indicator); when that evidence is not supplied, the response surfaces an optionalfront_company_indicatorschecklist routed to human review — never a shell-company or ownership determination. Deliberately NOT added torequired_before_go/must_check, preserving thedecision_readiness_scoredenominator and ADR 0003 score comparability (a contract test asserts supplying the new source does not move the score). Worker JS kept in parity. Schemas + taxonomy dual-copied. Use-case doc updated. 4 new contract tests (Python + Worker: checklist surfaced + boundary wording; omitted + score-unchanged when supplied). Additive, non-breaking. -
docs(glossary): anchor the attribution/citation/quotation vocabulary to the external literature. Adds a glossary section mapping the portfolio's evidence mechanisms onto the unified taxonomy in a 2025 survey of evidence-based text generation with LLMs (arXiv:2508.15396): quotation →
verify-quotes/supporting_quotes, citation →evidence_ids, attribution →audit-claims+evidence_mode. States which of the survey's seven evaluation dimensions the toolkit addresses (Attribution, Citation, Preservation) versus deliberately does not (Correctness = factuality; Retrieval / Relevance not scored), and places the runtime as post-hoc / in-context in the survey's timing scheme (with thecis_secondary_sanctionsper-profile retrieval exception, ADR 0014). Restates the existing faithfulness-not-factuality boundary in field-standard vocabulary — no behavior, schema, or contract change. Docs only. -
feat(verify-quotes): harvest span-level
supporting_quotesand check them against source text. Completes the deferred half of the span-grounding work:verify_quotes(MCP tool +verify-quotesCLI) now accepts an evidence-audit-shaped doc, not just an evidence pack. It harvests eachclaims[].supporting_quotesentry, resolves source text by the entry'sevidence_id(caller-suppliedtextsmap for the MCP tool;--texts-dirfile or--fetchfor the CLI, reusing the evidence item'surl), and reportspresent/absent/missing_source_textfor the span — each span result carries the originatingclaim_id. Summary gainsfrom_supporting_quotes(count of span-derived checks). Evidence-packsources/evidenceitems with aquoteare still checked exactly as before (items without aquoteare skipped, so an audit doc'sevidence[]does not double-count). This closes the document→span faithfulness check end to end:audit-claimsvalidates the structural link,verify-quoteschecks the span text is actually present. Still presence-only — no factual-truth verification, no source-reputation scoring, no live discovery (CLI--fetchretrieves only already-specifiedurls). Backward-compatible (existing packs have noclaims, so harvesting yields nothing); the CLI's empty-input guard now also accepts aclaims-only doc. stdio tool description +pack_jsonschema hint updated. 2 new tests (MCP: 2 spans on one claim → 1 present + 1 absent,from_supporting_quotes=2,claim_idon every result; CLI: audit doc +--texts-dir→ present span carriesclaim_id). Tool wiring + docs only; no schema-file, request/memo contract, or dual-copy path touched. -
feat(evidence-audit): optional span-level
supporting_quotesgrounding on claims. The claim→evidence link inevidence-audit.schema.jsonwas document-level only: a claim citedevidence_idsbut recorded no which-span-backs-it. Following the fine-grained-grounded-citation pattern (cf. FRONT, arXiv:2408.04568), each claim may now carry an optionalsupporting_quotesarray of{evidence_id, quote}entries that name the exact span in cited evidence backing the claim.audit_claimsvalidates this structurally only — it addsgrounded_claim_countand aspan_orphanslist (flagging anysupporting_quote.evidence_idnot among that claim'sevidence_ids, distinguishing "not in claim.evidence_ids" from "not in evidence"), mirroring the existingorphan_evidence_refssignal. A span orphan is a summary signal, not a schema error — the audit staysvalid. The structural layer deliberately does NOT check that the quote text appears in the source (that isverify-quotes' job) and neither verifies factual truth; this raises the faithfulness check from document to span granularity, not factuality. Additive, non-breaking; ADR 0003 freeze intact (new optional field, no change to existing fields). Schema dual-copied to package data. 2 new contract tests (clean grounding →grounded_claim_count+ emptyspan_orphans; orphan span → flagged, audit still valid). Deferred: wiringverify-quotesto harvestsupporting_quotesand check the span text against source — a separate follow-up. -
feat(worker): Cloudflare Worker JS parity for
gulf_maritime_exposure. Ports the fourth vertical worker to the deployed A2A Worker (the surface listings point to), so the live endpoint emits the same triage as the Python service. Adds thegulf_maritime_exposureprofile detection (AGENT_PROFILE/gulf-maritime-exposure-a2ahost),applyGulfMaritimeProfileagent card (skill, description, schema/taxonomy URLs, boundaries, commercial positioning), structured request extraction + enum validation, the JS port of the service logic (gulfMaritimeExposureResultand helpers — readiness, exposure signal, triage, top dimensions, chokepoint disruption watch — mirroring the Python exactly),a2aResultForGulfMaritimeExposure, and themessage/senddispatch branch. Newwrangler.tomlenvgulf-maritime-exposure. 3 new worker tests (card exposes gulf skill; message/send escalates before fixture with high signal — Python parity; non-gulf shape rejected). Worker JS + wrangler + tests only; no Python service, schema, or dual-copy path touched. Activation:wrangler deploy --env gulf-maritime-exposure(no deploy workflow runs on merge; the env was subsequently deployed and the endpoint is live). -
feat(gulf_maritime_exposure): new vertical worker — contract core (Python). Fourth vertical worker, built on the same service layer and evidence-discipline pattern as
middle_corridor_deal_risk/cis_secondary_sanctions. Triages maritime sanctions and chokepoint-disruption exposure for a vessel or voyage transiting the Strait of Hormuz, Persian/Arabian Gulf, Gulf of Oman, Bab-el-Mandeb, or Red Sea: caller supplies vessel/voyage/cargo/counterparties + exposure facets (Iran-oil, Russia price-cap, dark-fleet, STS transfer, flag-hopping, P&I gap, AIS manipulation, ownership/control, dual-use cargo, chokepoint disruption) + dated sources; the worker returns an evidence-sufficiency triage (insufficient_information/escalate_before_fixture/escalate_before_voyage/not_decision_ready/ready_for_human_review), exposure signal, decision-readiness score, evidence gaps, top exposure dimensions, a chokepoint-specific disruption watch, and mandatory human-review escalation. No live retrieval (caller-supplied evidence only); does not resolve vessel ownership or verify identity — explicit boundary, not advice. Ships the full worker per the AGENTS.md vertical-worker checklist: newschemas/v1/gulf-maritime-exposure-request|response.schema.json(dual-copied to package data),source-requirements/gulf-maritime-exposure.json(dual-copied),services.gulf_maritime_exposure+ helpers, HTTP routePOST /v1/gulf-maritime/exposure, A2A profilegulf_maritime_exposure(capability + aliases + card skill + dispatch + artifact text),docs/use-cases/gulf-maritime-exposure.md,examples/gulf-maritime-exposure/contract/request+response fixtures, and anexamples/a2a/round-trip fixture. Tests: 6 contract tests (taxonomy/constant parity, schema-example conformance, golden escalation with high signal, full-evidence routes to review, invalid-request rejection, no clearance wording) + an A2A round-trip case + updated capability-list assertions. No live retrieval (caller-supplied evidence only); does not resolve vessel ownership or verify identity — explicit boundary, not advice. Additive, non-breaking; ADR 0003 freeze intact (new schema family, not a change to frozen schemas). Deferred: Cloudflare Worker JS parity + awranglerenv for the deployed A2A endpoint (deploy-time follow-up; the Python service / HTTP / A2A surfaces are live in-package). Built as a portfolio / topical artifact — no paying customers, no pilots; demand-gated for go-to-market. -
docs(middle-corridor): reposition as a pre-screening evidence triage layer. Output of a 2026-06-02 competitive scan: the funded landscape splits into data/network-intelligence platforms and real-time screening engines/APIs, both of which own ground the worker cannot (proprietary lists, ownership graphs, name-matching, live retrieval). Repositions the worker — as a complement that sits before those tools, surfacing which due-diligence documents are still missing so the dossier is complete before the expensive screening/data step, rather than implicitly competing with them head-to-head. Agent-card
commercial_positioning(Kazakhstan profile) and the use-case-doc proposition now lead with this framing and state plainly that it performs no screening, name-matching, or data retrieval and holds no lists or graph. Deliberately phrased at the category level — no competitor brand names are hardcoded into public card/repo text. Positioning text only; no schema, service, request/response contract, or score change. Live agent-card text updates on the next worker deploy. -
feat(middle_corridor_deal_risk):
pep_screening_indicatorsPEP checklist +pep_screening_evidencesource type. Closes the last "easy" gap from the 2026-06-02 practitioner-guidance field-map: politically-exposed-person (PEP) screening is a core FATF Recommendation 12 / 22 EDD element the worker did not represent. Modeled as an evidence gap, not a presence-flag — the worker cannot and must not determine PEP status itself (that would be a fabricated determination per the honesty rules), so it surfaces a checklist of what to screen, routed to human review. Same non-breaking pattern assource_of_funds_indicators/reexport_control_indicators/vessel_due_diligence_indicators(ADR 0015): newpep_screening_evidencevalue in the request + responsesource_typeenums and the taxonomyhelpful_context/supporting_sources(+ aPEP status or political-exposure changewatch indicator); when that evidence is not supplied, the response surfaces an optionalpep_screening_indicatorschecklist (counterparty + beneficial-owner screening, family / close associates, senior-management approval, enhanced SOF/SOW, ongoing monitoring). Deliberately NOT added torequired_before_go/must_check, preserving thedecision_readiness_scoredenominator and ADR 0003 score comparability (a contract test asserts supplying the new source does not move the score). Worker JS kept in parity. Schemas + taxonomy dual-copied. Use-case doc updated. 4 new contract tests (Python + Worker). Additive, non-breaking. -
feat(middle_corridor_deal_risk):
source_of_funds_indicatorsSOF/SOW checklist +source_of_funds_or_wealth_evidencesource type. Closes the next gap from the 2026-06-02 practitioner-guidance field-map: source-of-funds and source-of-wealth (SOF/SOW) is a core FATF Recommendation 10 EDD element (transaction-fund evidence, wealth origin, profile/size consistency, payer match) the worker did not represent. Same non-breaking pattern asreexport_control_indicators/vessel_due_diligence_indicators(ADR 0015): newsource_of_funds_or_wealth_evidencevalue added to the request + responsesource_typeenums and the taxonomyhelpful_context/supporting_sources(+ asource of funds or payer changewatch indicator); when that evidence is not supplied, the response surfaces an optionalsource_of_funds_indicatorschecklist routed to human review — never a financial determination or AML clearance. Deliberately NOT added torequired_before_go/must_check, preserving thedecision_readiness_scoredenominator and ADR 0003 score comparability (a contract test asserts supplying the new source does not move the score). Worker JS kept in parity. Schemas + taxonomy dual-copied. Use-case doc updated. 4 new contract tests (Python + Worker). Additive, non-breaking. -
feat(middle_corridor_deal_risk):
reexport_control_indicatorsend-use verification checklist +end_user_or_reexport_evidencesource type. Closes a gap surfaced in the 2026-06-02 practitioner-guidance field-map: end-user statements / certificates and no-re-export clause acceptance are a prescribed EDD/trade element (EU Sanctions Helpdesk red flags, US end-user diversion guidance) the worker did not represent as a first-class item — especially material for this re-export / diversion-exposed corridor. Newend_user_or_reexport_evidencevalue added to the request + responsesource_typeenums and to the taxonomyhelpful_context/supporting_sources(with a newend-user or onward-destination changewatch indicator). When that evidence is not supplied, the response surfaces an optionalreexport_control_indicatorschecklist (signed end-user statement, no-re-export clause acceptance, end-use consistency, onward-destination disclosure, order-vs-destination match), mirroring thevessel_due_diligence_indicatorspattern (ADR 0015): an evidence-gap checklist routed to human review, never an end-use or sanctions determination. Deliberately NOT added torequired_before_go/must_check, so thedecision_readiness_scoredenominator is unchanged and score comparability under the ADR 0003 freeze is preserved (a contract test asserts supplying the new source does not move the score). Worker JS kept in parity. Schemas + taxonomy dual-copied. Use-case doc updated. 4 new contract tests (Python: checklist surfaced + boundary + schema conformance; omitted + score-unchanged when supplied. Worker: same two parity assertions). Additive, non-breaking. -
feat(middle_corridor_deal_risk): per-document
document_ledgerinsidecounterparty_readiness. Driven by a 2026-06-02 practitioner-guidance pass (FATF / OFAC maritime guidance, ACAMS-style EDD checklists, EU Sanctions Helpdesk): EDD guidance prescribes tracking each required item with the date it was requested / received and maintaining a time-stamped chain of custody, so a flatoutstanding_documentslist under-serves the outward dossier view. New optionaldocument_ledgersub-field (additive within the already-optionalcounterparty_readinessobject;schemas/v1/middle-corridor-deal-risk-response.schema.json, dual-copied) emits one entry per required-before-go source type:source_type,status(received/missing), anddate_received(the earliest supplied dated source of that type, when present). Derived from existingdated_sources— no new request fields, no change todecision_readiness_score/risk_signal/statuscounts. Status tracking only — explicitly not verification of any document's contents or authenticity; the boundary and human-review requirement are unchanged. Worker JS port kept in parity in the same change. Example artifact07-counterparty-readiness.json+ use-case doc updated. 2 new contract tests (Python: ledger has one entry per required type, supplied sourcereceivedwithdate_received, restmissingwith none, received count reconciles withsupplied_count, schema conformance; Worker: same parity assertions). Additive, non-breaking; ADR 0003 freeze intact. -
feat(worker): Cloudflare Worker JS parity for
counterparty_readiness. Ports the outward dossier-completeness view (added to the Python service in the companioncounterparty_readinessentry) to the deployed A2A Worker — the surface the Agenstry listing actually points to — so the live endpoint emits the same field.counterpartyReadinessForStructuredRequestmirrors the Python helper exactly:statusderived fromdated_sources/ supplied required-before-go sources (insufficient_information/incomplete/partial/complete_for_review),required_total/supplied_count/missing_count,outstanding_documents, and the identicalpresentable_note. Wired intodealRiskContractResponseForRequest. Worker JS + tests only; no Python service, schema, or dual-copy path touched. 2 new worker tests (partial: counts reconcile + outstanding equalsminimum_sources_before_go+ clearance-wording boundary; complete_for_review when all required supplied). Activation: requires a manualwrangler deploy --env middle-corridor-deal-risk-gate(no deploy workflow runs on merge; until then the live route keeps the prior shape). -
feat(middle_corridor_deal_risk): outward
counterparty_readinessdossier-completeness view. Driven by a 2026-06-02 market pain-discovery pass: the dominant stated pain for Kazakhstan / Central Asia counterparties under tightened enhanced due diligence is the outward one — "demonstrate to a bank / insurer who owns the business, who the partners are, where goods originate, how the deal is structured." The worker already encoded the right checklist (required_before_go) but framed its entire output for the internal analyst ("should we escalate before signature?"), so the second actor (the party that must present a dossier) got no first-class answer. New optionalcounterparty_readinessresponse field (schemas/v1/middle-corridor-deal-risk-response.schema.json, dual-copied) reframes the same evidence-gap picture outward:status(insufficient_information/incomplete/partial/complete_for_review),required_total/supplied_count/missing_count,outstanding_documents(the still-needed required-before-go source types), and apresentable_note. Derived entirely from the existing required-before-go contract and supplied sources — no new evidence logic, no change todecision_readiness_score/risk_signal. Additive, non-breaking; ADR 0003 freeze intact (optional field, minor surface). Dossier-completeness only — explicitly not clearance, approval, a sanctions determination, or compliance advice; human review still required. New example artifactexamples/kazakhstan-middle-corridor/07-counterparty-readiness.json+ README. 2 new contract tests (partial when sources missing: counts reconcile + outstanding equalsminimum_sources_before_go+ schema conformance; complete_for_review when all required supplied + clearance-wording boundary). Python service + schema + example only; the deployed Worker JS port is brought to parity in the companion worker entry above. -
feat(worker): extend the per-profile Bearer access model to the Agentic Interaction Trust Gate (
agentic_interaction_trust), off by default. The Bearer enforcement path (isProductionAuthorized, 401 +WWW-Authenticate: Bearer, conditionalproductionBearercard requirement) was already profile-generic, butproductionAuthKeyresolved a secret only for thekazakhstanprofile, so the trust gate'smessage/sendroute could never be gated.productionAuthKeynow also reads theAGENTIC_INTERACTION_TRUST_API_KEYsecret on theagentic-interaction-trustenv; per-profile keys stay scoped (the Middle Corridor secret never gates the trust profile and vice-versa). When the secret is unset the route stays an open free demo and the card advertises no requirement (current state);agent/carddiscovery stays public regardless. Worker JS + tests only; no Python service, schema, or dual-copy path touched. The per-profile-key test was widened to assert both directions of scope and the new key resolution. Activation:wrangler secret put AGENTIC_INTERACTION_TRUST_API_KEY --env agentic-interaction-trustthenwrangler deploy --env agentic-interaction-trust(no deploy workflow runs on merge; until then the route stays open). -
feat(worker): explicit, enforceable Bearer access model for the Middle Corridor production route (
message/send), off by default. The deployed agent card previously declared onlyoptionalClientId— anX-Client-Idheader used purely for observability and abuse triage, never an access credential — and the worker enforced no authentication on any route. This graduates the security model to an explicit Bearer scheme without breaking the free live demo. The agent card now always definesproductionBearer(httpAuthSecurityScheme,scheme: bearer) alongsideoptionalClientId, but only advertises it as a requirement (security/securityRequirementspopulated) when the operator actually configures theMIDDLE_CORRIDOR_API_KEYsecret on themiddle-corridor-deal-risk-gateenv — so the card stays truthful in both states (open demo vs gated). Enforcement (isProductionAuthorized) mirrors the existingSTATS_TOKENprecedent:message/send/tasks/send/SendMessageon thekazakhstanprofile returns HTTP 401 withWWW-Authenticate: Bearerand a JSON-RPC-32001error when a key is set and theAuthorization: Bearer …token is absent or wrong; when the secret is unset the route remains an open free demo (current state, no paying customers).agent/carddiscovery stays public regardless. Scoped to thekazakhstanprofile only — the other three workers are unaffected (productionAuthKeyreturns""for them even if the env leaks). CORSaccess-control-allow-headersnow includesauthorization. Worker JS + tests only; no Python service, schema, or dual-copy path touched. 11 new worker tests (key resolution per profile, open-when-unset, Bearer match/mismatch, conditional card shape both states, 401 +WWW-Authenticate, success with valid Bearer, publicagent/card). Activation:wrangler secret put MIDDLE_CORRIDOR_API_KEY --env middle-corridor-deal-risk-gatethenwrangler deploy --env middle-corridor-deal-risk-gate(no deploy workflow runs on merge; until then the route stays open).
[1.1.0] – 2026-06-01
- feat(a2a): migrate the A2A wire contract to A2A protocol v1.0 (ADR 0017). Both A2A surfaces — the Python
a2a_adapterand the deployed Cloudflare Worker — advertisedprotocolVersion: "1.0"in the agent card while still emitting v0.3-shaped response bodies (kind-discriminated parts, lowercasestatus.state). The card claimed conformance the body did not meet — an honesty-rule violation and a strict-validator failure, and it left the Agenstryprotocol_version(+10) score asserted rather than earned. This migrates the response wire to v1.0: parts are now member-discriminated withmediaType({"text": …, "mediaType": "text/markdown"}/{"data": …, "mediaType": "application/json"}, nokind);status.stateemitsTASK_STATE_COMPLETED/TASK_STATE_FAILED; and the Python card gainssupportedInterfaces[](JSONRPC,protocolVersion: "1.0") to match the Worker card already in production. Inbound request parsing is unchanged — it was already member-based, so both v0.3 and v1.0 request shapes are still accepted (back-compat); doc/example request payloads are updated to the v1.0 form. Scope is the A2A wire surface only: theschemas/v1/request/memo/product schemas and the ADR 0003 freeze are untouched, so this ships as a minor bump (1.0.2 → 1.1.0) with the breaking-for-A2A-consumers detail in ADR 0017. Worker and package versions realigned to 1.1.0 (the Worker had drifted to 1.0.1). Deferred (no consumer): streaming-event wrapper discrimination, cursor pagination,google.rpc.Statuserrors, OAuth/multi-tenancy/extension checks. Tests: 52 Python A2A/contract tests + 62 Worker tests updated and green. Activation: Worker change requires a manualwrangler deploy(no deploy workflow runs on merge). - feat(worker): Cloudflare Worker JS parity for the Middle Corridor jurisdiction flags, exposure decomposition, and vessel checklist. The deployed A2A Worker (what the Agenstry listing points to) runs its own JS port of
middle_corridor_deal_risk, which had drifted behind the Python service: it emitted neither the ADR 0015 high-risk jurisdiction flag, nor the re-export / circumvention-watch flag, norexposure_layers, norvessel_due_diligence_indicators. So features shipped in the Python package were not live on the A2A surface a practitioner would actually call. This ports all four todeploy/cloudflare-worker/src/index.jswith identical wording and the same boundary discipline (presence-flagging routed to human review, never a determination; structural score / risk_signal unchanged):HIGH_RISK_JURISDICTIONS,CIRCUMVENTION_WATCH_JURISDICTIONS(high-risk takes precedence — no double-flag),exposureLayersForStructuredRequest, and the OFAC-groundedVESSEL_DUE_DILIGENCE_INDICATORSchecklist surfaced when vessel/carrier history is missing. The Kazakhstan agent-card description and README are updated to reflect the now-live outputs, with the non-determination disclaimer.dealRiskContractResponseForRequestis exported for direct testing; 4 new worker tests (high-risk flag, circumvention/Armenia not-as-sanctioned, two-layer exposure + vessel checklist + clearance-wording boundary, vessel checklist omitted when history supplied). Worker JS + README only; no Python service, schema, or dual-copy path touched. Activation: requires a manualwrangler deploy --env <middle-corridor>(no deploy workflow runs on merge). - feat(worker): per-task cost accounting + budget thresholds in
/stats. The Worker tracked call counts, prompt chars, clients, and modules but had no per-task cost visibility. No LLM is called on the Worker path, so the only real per-request spend is paid live-retrieval upstreams; per ADR 0014 the OpenSanctions hosted API (€0.10/call) is the sole billable upstream (Watchman self-host and the deterministic triage path cost €0). Each usage event now records alive_retrievalblock (status/upstream/billable/cost_eur); a call is billed only when a paid upstream actually returned data (status: success) —degraded(failed call) anddisabled(no key) are not billed, conservative on the side of not over-reporting.usageStatsaggregatescounters.billable_callsand a newcostblock:estimated_cost_eur(rounded),billable_upstreamsbreakdown, and abudgetsub-block that compares daily spend against the optional plaintext varUSAGE_BUDGET_EUR_PER_DAYand emits analert_levelofnone/50/75/90. The Worker never blocks on budget — it only reports; when no cap is set,budget.configuredisfalse.scripts/stats.jsand the worker README document the new fields. 1 new contract test (6 billable + 1 degraded + 1 disabled → €0.60 est., plus 50% and 90% budget-tier assertions). Worker-only change; no schema, request/memo contract, or dual-copy path touched. - fix(mcp): constrain
categorytool args to the packaged enum + correct a stale slug. Thesource_plan/source_coverageMCP tools tookcategoryas a free-form string, so a model could pass a hallucinated slug; thesource_plandescription also gave a non-existent example (energy-markets— the real slug isenergy)._tool_definitions()now injects anenumof the packaged source-requirement category slugs onto anycategoryproperty at the livetools/listsurface. The enum is computed from the same data source aslist_source_categories(thesource-requirements/files), so it never drifts — no hardcoded list to keep in sync. The staticTOOLSdict (mirrored intoagent-manifest.jsonunder the ADR 0012 parity invariant) stays a lighter catalog without the data-derived enum; the corrected description example is synced to both manifest copies. 1 new test asserts the livecategoryenum equals the packaged slug set. No schema-file, request/memo contract, or transport change. - feat(middle_corridor_deal_risk): re-export / circumvention-watch jurisdiction flag + two-layer exposure decomposition. Driven by a market pain-discovery pass against a public Kazakhstan trade-sanctions practitioner page whose stated pain is "a transaction can be fully compliant with Kazakhstani domestic law and simultaneously trigger [foreign] sanctions." Two additive, non-breaking changes (no request/memo contract change; ADR 0003 freeze intact). (1) A dogfood run surfaced that an intermediary counterparty in Armenia — a documented parallel-import / re-export corridor — was not flagged, because
HIGH_RISK_JURISDICTIONS(ADR 0015) deliberately lists only comprehensively / sectorally sanctioned jurisdictions. Folding Armenia into that list would mislabel it as sanctioned. Instead, a separate, softerCIRCUMVENTION_WATCH_JURISDICTIONSset (Armenia, Georgia, Kyrgyzstan, Uzbekistan, Turkey, UAE + variants) now presence-flags re-export / diversion-watch counterparties via a distincttop_risksentry ("counterparty in a re-export / circumvention-watch jurisdiction") and alimitationsline worded as "a diversion watch item for human review, not a sanctions determination." A high-risk-list match takes precedence (no double-flag). The structuraldecision_readiness_score/risk_signalare unchanged, per the ADR 0015 boundary. (2) New optionalexposure_layersresponse field (schemas/v1/middle-corridor-deal-risk-response.schema.json, dual-copied) decomposes the risk picture into the two layers a practitioner separates:domestic_legal_layer(home-jurisdiction legal / licensing / documentation posture — explicitly not assessed by this product) andforeign_sanctions_exposure_layer(secondary / extraterritorial exposure signals). Structural decomposition only; never asserts clearance. 4 new contract tests (circumvention positive + high-risk-precedence + clean-jurisdiction negative control + exposure-layers separation & schema conformance). - feat(middle_corridor_deal_risk): vessel deceptive-shipping-practice (DSP) verification checklist. Third market pain-discovery pass (marine / underwriter side: OFAC maritime guidance names the P&I insurer as responsible for spotting deceptive shipping practices). The worker handled the maritime leg only as a binary
vessel_or_carrier_historysource gap; it did not surface what a sanctions reviewer / underwriter actually checks. New optionalvessel_due_diligence_indicatorsresponse field (schemas/v1/middle-corridor-deal-risk-response.schema.json, dual-copied) is populated whenvessel_or_carrier_historyis among the missing sources, with an OFAC-grounded checklist: AIS continuity / disablement, MMSI / name / IMO identity manipulation, certificate-of-origin integrity, undisclosed ship-to-ship transfers, and flag history. Additive, non-breaking; an evidence-gap checklist routed to human review — not vessel adjudication, AIS analysis, live retrieval, or insurance advice (ADR 0015 boundary). The structuraldecision_readiness_score/risk_signalare unchanged. 2 new contract tests (checklist surfaced when vessel history missing + schema conformance + boundary wording; negative control when vessel history supplied).
[1.0.2] – 2026-05-31
Multi-surface presentation + deployment automation, plus a new vertical worker (cis_secondary_sanctions) and per-profile live retrieval (ADR 0014, with runtime activation deferred per the 2026-05-27 update). The v1.0 request/memo contract surface is unchanged; new schemas under schemas/v1/ are additive per ADR 0003.
-
feat(mcp): expose the three vertical workers as MCP tools.
middle_corridor_deal_risk,cis_secondary_sanctions_exposure, andagentic_interaction_trustwere callable over HTTP and A2A but not via the stdio MCP server, which exposed only the 11 validation + 5 product tools. They are now MCP tools (19 total), each taking a structured request matching itsschemas/v1/contract and returning the same triage recommendation, decision-readiness score, evidence gaps, and mandatory human-review flag as the other surfaces. The local stdio transport runs the CIS worker withallow_live_retrieval=False(user-supplied evidence only).agent-manifest.jsonmcp.toolsmirrors the newTOOLSentries (ADR 0012 invariant); dual-copied to packaged data;llms.txttool list updated. 5 new contract tests (golden per worker + missing-argument tool error + tools/list coverage). No schema or request/memo contract change. -
ADR 0015 + feat(middle_corridor_deal_risk): high-risk jurisdiction presence flag. Third dogfood run (2026-05-28) on the flagship Deal Risk Gate: a
counterparties[].jurisdiction = "Russia"on a dual-use cargo was not flagged — the most material fact in that case. ADR 0015 records the deliberate structural-triage boundary: workers may flag the presence of a known high-risk attribute (undisclosed UBO, sanctions-relevant jurisdiction) as an evidence/escalation signal routed to human review, but must NOT adjudicate substance or fold content into the structuraldecision_readiness_score/risk_signal(that would be a fabricated determination per the honesty rules + ADR 0006). This retroactively makes the 2026-05-28 cis UBO flag principled rather than ad-hoc. Implementation:middle_corridor_deal_risknow scanscounterparties[].jurisdictionagainst a small explicitly-labeled sanctions-relevant list (Russia, Belarus, Iran, North Korea, Syria, Crimea, Donetsk, Luhansk + variants); a match surfaces atop_risksentry ("counterparty in a sanctions-relevant / high-risk jurisdiction") and alimitationsline that names the counterparty and states explicitly it is "an escalation flag for human review, not a sanctions determination." The structural score is unchanged. 2 new contract tests (positive + negative control). Deferred under the same ADR principle (not done): free-textnotesuncertainty scan, cargo dual-use detection. Explicitly rejected: content-aware scoring. -
fix(cis_secondary_sanctions): surface undisclosed UBO + stop leaking internal env-var names. Two dogfood findings (2026-05-28, running the worker on a synthetic CIS metals-trader case). (1) An undisclosed / unverified ultimate beneficial owner in the supplied
ownership_layersis now detected (token scan:undisclosed,unknown,nominee,tbd, etc.) and surfaced both as an explicittop_exposure_dimensionsentry ("undisclosed or unverified ultimate beneficial owner") and alimitationsline ("the counterparty cannot be fully screened until the UBO is resolved"). Stays within the pre-compliance triage boundary — it flags an evidence gap, does not analyze ownership. (2) The user-facinglimitationsarray no longer echoes internal env-var names (OPENSANCTIONS_DISABLED/OPENSANCTIONS_API_KEY); the degrade note is now derived fromlive_retrieval_statusin user-safe language ("Live sanctions-list retrieval is not currently enabled / was unavailable; triage is based on user-supplied evidence only"). 3 new contract tests (UBO positive + negative control + env-leak guard). No schema or contract change; the response shape is unchanged (existing fields, new content only). -
skill: temporal-premise check in
agenda-intelligenceSKILL.md. Added a Core-rule instruction: check the question's temporal premise (asserted elapsed time / effective date / "since X" / "N-month effect") against the current date before analyzing, and re-anchor to the actual timeline rather than silently adopting the caller's date. Surfaced during dogfooding (2026-05-28): a memo prompt asserted a "12-month effect" when ~23 months had elapsed; the analysis caught it but the skill did not previously instruct it. New soft anchortemporal-premise-checkinevals/skill-improvement/anchors/agenda-intelligence.json(12 anchors total, all present). Dual-copied to packaged data. No schema or contract change. -
Structural skill-anchor gate for skill-improvement iterations (
evals/skill-improvement/tools/eval_gate.py+evals/skill-improvement/anchors/agenda-intelligence.json). Inspired bymicrosoft/SkillOpt's validation-gate pattern but scoped to the actual failure mode of LLM-driven skill editing: silent removal of the discipline anchors the rubric depends on (e.g. droppingNever imply live verification, collapsing the signal-classification enum, or removing required default-output fields). The gate hard-rejects an edit when a critical anchor is missing, before any LLM-judge or human rubric scoring — exit 0 accept / 1 reject / 2 config error. 11 anchors declared, mapped onto the 7 rubric dimensions; each carriesseverity(critical/soft),any_of/all_ofregex patterns,rubric_dimensions, andrationale. Currentskills/agenda-intelligence/SKILL.mdpasses 11/11. 7 new pytest cases pin the contract: well-formed config, current skill passes, plus four regression scenarios (boundary anchor stripped, signal enum value removed, default output field renamed, signal-markers collapse-warning removed) — each must trigger reject. CI runs the gate viatests/test_skill_anchors_gate.py; drifts that slip past local iteration are blocked at merge time. Skill-improvement README updated with the gate workflow step. -
Cloudflare Worker: JWS-signed agent cards +
/.well-known/jwks.json(Agenstry conformance criterionjws_signature, +10). Per Agenstry's 9-criterion conformance schema, the worker now serves agent cards with an ES256 detached JWS signature (RFC 7515 / 7797 / 8785). New moduledeploy/cloudflare-worker/src/jws.jsprovides JCS canonicalisation, base64url encoding,signCardDetached()andpublicJwkFromPrivate()helpers built on Cloudflare WebCrypto (no external deps). New routeGET /.well-known/jwks.jsonderives the public key from the operator-configuredAGENT_CARD_SIGNING_KEYsecret at request time and serves it as a JWKS document;GET /.well-known/agent-card.jsoncallsmaybeSignCard()which adds the compact detached JWS tocard.signature(or returns the card unsigned when no key is configured — graceful default).scripts/generate-signing-key.jsis a one-shot ES256 keypair generator that prints the private JWK + kid + activation steps. Worker README gains a "JWS-signed agent cards" section with the full setup flow and the verifier algorithm. Agent card also gains asupportblock (email, hoursMon–Fri 09:00–18:00 Asia/Almaty, timezone, response SLA — honest "best-effort, solo maintainer, not paid support"). 10 new tests cover JCS determinism, public-JWK derivation, JWKS document shape, sign+verify roundtrip, prior-signature stripping, no-op when key absent, andsupportblock presence. Activation hand-off:node scripts/generate-signing-key.js→wrangler secret put AGENT_CARD_SIGNING_KEY --env <each-env>→wrangler deploy --env <each-env>. No code change required after that —/jwks.jsonandcard.signaturepopulate automatically. -
ADR 0014 update (second 2026-05-27 entry) — Watchman added to the upstream whitelist as the free option. Discovered via github.com/topics/sanctions that
moov-io/watchmanis a production-grade open-source (Apache-2.0) self-hosted OFAC / EU / UK OFSI / UN sanctions search engine, used by Moov Financial. This invalidates the prior "self-host = toy-grade homebrew matching" argument.LIVE_RETRIEVAL_PROFILES.cis_secondary_sanctionsnow declares two upstream options (upstream_optionsarray): Watchman (activation_env_var: WATCHMAN_URL, free) and OpenSanctions (activation_env_var: OPENSANCTIONS_API_KEY, paid €0.10/call). The runtime dispatcher picks the first active option (free before paid). New JS moduledeploy/cloudflare-worker/src/upstream_watchman.jsmirrors the existing OpenSanctions adapter (thin client over/v2/search, KV cache withwatchman:prefix onAGENDA_USAGE, AbortSignal timeout, graceful degrade, Apache-2.0 attribution). Agent cards and/status.live_retrievalnow exposeactive_upstream(which option is currently wired, ornull) andupstream_options[*].active(per-option flag), plus a per-optioncost_modeldescription. Pythona2a_adaptermirrors the multi-option shape (new helpersactive_upstream_option(profile)and_is_upstream_option_active(option)). Re-activation path: self-host watchman on free-tier container (~30 min,moov/watchmanDocker image),wrangler secret put WATCHMAN_URL --env cis-secondary-sanctions, done — no code change, no redeploy. Tests: 6 new (3 Python: multi-option capability registration, env-var dispatch + Watchman-preferred-over-OpenSanctions ordering, agent-card active_upstream / per-option active fields; 3 JS: agent card with WATCHMAN_URL, dispatch preference when both env vars set, /status active_upstream flip). -
ADR 0014 update (2026-05-27) — runtime activation deferred, capability preserved. Discovered after the original ADR shipped that the OpenSanctions hosted API is paid (€0.10/call, pay-as-you-go) and not free as initially assumed. With zero confirmed buyers for
cis_secondary_sanctions(/statsshows zero external non-probe traffic in the 7 days since shipping), per-call vendor fees are the classic sunk-cost trap.LIVE_RETRIEVAL_PROFILESin bothsrc/agenda_intelligence/a2a_adapter.pyanddeploy/cloudflare-worker/src/index.jsnow declares capability rather than activation. New helperis_live_retrieval_active(profile)(Python) /isLiveRetrievalActive(profile, env)(JS) is env-derived and currently always returnsFalse(noOPENSANCTIONS_API_KEYconfigured on any deployed worker). Agent cards and/statusnow expose{capability_declared, active, ...}instead of{live_retrieval: True, ...};boundaries.live_retrievalreflects actual activation (currentlyfalseforcis_secondary_sanctions). When deferred,/status.live_retrievalincludes adeferral_noteexplaining why. Re-activation is onewrangler secret put OPENSANCTIONS_API_KEYaway — no schema change, no redeploy of code. Schemas, source-requirements, service function, A2A profile, deployedcis-secondary-sanctions-a2aWorker, and the SOURCE_POLICY upstream whitelist all remain in place. 4 new tests cover the env-aware shape (2 Python:is_live_retrieval_active, agent-card per-profile block; 3 JS: agent-card with/without key, /status flip with key). -
New vertical worker:
cis_secondary_sanctions— second vertical worker under the< 3rule in AGENTS.md. Structured secondary-sanctions exposure evidence triage for CIS-domiciled counterparties (Kazakhstan, Uzbekistan, Kyrgyzstan, Tajikistan, Turkmenistan, Georgia, Armenia, Azerbaijan, Moldova). Targets enhanced due diligence in EU / UK / UAE / Singapore institutions screening counterparties against OFAC EO 14114, EU 14th sanctions package, UK OFSI, and FATF / EAG typologies. Ships with: new request/response schemas underschemas/v1/cis-secondary-sanctions-{request,response}.schema.json(with dual-copied packaged data), source-requirements taxonomy undersource-requirements/cis-secondary-sanctions.json, service functionservices.cis_secondary_sanctions_exposure, HTTP routePOST /v1/cis-secondary-sanctions/exposure, A2A capabilitycis_secondary_sanctions_exposurewith thecis_secondary_sanctionsproduct profile, three contract fixtures underexamples/cis-secondary-sanctions/contract/, use-case doc atdocs/use-cases/cis-secondary-sanctions.md, and 8 contract tests. Honest traction: zero paying customers, zero named pilots — shipped as a portfolio-grade vertical worker for technical evaluators and as a contract real practitioners can inspect. -
ADR 0014 — per-profile live retrieval (OpenSanctions for
cis_secondary_sanctions) (docs/adr/0014-per-profile-live-retrieval.md). The runtime default remainslive_retrieval: false. The newcis_secondary_sanctionsprofile opts in to live retrieval against the OpenSanctions consolidated dataset (CC-BY 4.0) for counterparty name matches; matches are merged into the evidence pack as auto-fetcheddated_sourceentries with attribution. Graceful degrade on any upstream failure (network error, 429, 5xx, timeout, missing API key) — response returned withlive_retrieval_status: degraded(ordisabled) and triage based on user-supplied evidence only. New modulesrc/agenda_intelligence/upstream_opensanctions.py(thin urllib client, in-process TTL cache, attribution helper). Agent cards andx_agenda_intelligence.per_profile_live_retrievalnow expose per-profile live-retrieval metadata; previously-deployedagendaandkazakhstanprofile claims are unchanged. SOURCE_POLICY.md gains a "Per-profile live retrieval" section with the upstream whitelist and the success/degraded/disabled status taxonomy. Live retrieval requires anOPENSANCTIONS_API_KEYenv var (free tier at https://www.opensanctions.org/api/); without it, the profile still functions on user-supplied evidence only. -
Cloudflare Worker JS-side OpenSanctions live retrieval for
cis_secondary_sanctionsprofile. Mirrors the Python adapter for the Workers runtime. New JS moduledeploy/cloudflare-worker/src/upstream_opensanctions.js(fetch +AbortSignal.timeout, attribution helper, dataset-to-source-type mapping). Cache uses the existingAGENDA_USAGEKV namespace with theopensanctions:prefix (no new namespace).wrangler.tomlgains anenv.cis-secondary-sanctionsstanza for the newcis-secondary-sanctions-a2asubdomain — operator runswrangler secret put OPENSANCTIONS_API_KEY --env cis-secondary-sanctionsbeforewrangler deploy --env cis-secondary-sanctions. Worker JS now: (1) detectscis_secondary_sanctionsprofile from host (cis-secondary-sanctions-a2a) or env (AGENT_PROFILE=cis_secondary_sanctions); (2) emits a per-profile agent card withlive_retrieval: {enabled: true, upstreams: [OpenSanctions], license: CC-BY-4.0}block inx_agenda_intelligence; (3) exposes per-profilelive_retrievalflag in/status, withlive_retrievalsub-object listing upstreams + license + ADR link when enabled; (4) dispatches structuredcis_secondary_sanctions_exposurerequests frommessage/sendto a JS port ofservices.cis_secondary_sanctions_exposurewith OpenSanctions live retrieval and graceful degrade.handleJsonRpcis nowasync; tests updated toawaitit. Theagendaandkazakhstanprofile boundaries (live_retrieval: false) are preserved. 6 new worker tests underdeploy/cloudflare-worker/test/worker.test.jscovering profile detection, agent card shape, per-profile/statusflags, dispatch withOPENSANCTIONS_DISABLED=1, and missing-structured-request failure mode. -
Cloudflare Worker: HTML landing on
GET /+ newGET /statusJSON endpoint (#66). Browser visitors (Accept: text/html) now see a clean inline-styled landing page with agent name, live/version/A2A/profile badges, "what this is" with explicit non-advice + no-live-retrieval + no-factuality disclaimers, a profile-specific curl example, an endpoints list, and links to source / PyPI / Agenstry. API clients still get the JSON health payload.GET /healthstays JSON-only regardless of Accept, so existing scripts and uptime checkers are unaffected. NewGET /statusreturns a compact JSON status doc suitable for uptime monitors and presales discovery: name, version, profile, A2A protocol version, agent-card / message-send URLs, repository / package links, and the four boundary flags (not_advice,live_retrieval,factual_verification,human_review_required). Profile-aware: general worker surfaces strategic-risk triage framing; the kazakhstan worker surfaces Deal Risk Gate framing and escalation language. -
AGENTS.md rewritten for multi-surface architecture (#63). Project identity reframed from "MCP server + validation infrastructure" to "Product runtime + four surfaces". New Vertical workers inside this repo section legalizes the Middle Corridor Deal Risk Gate as a first-class artifact with a
< 3spin-off rule for the next worker. The blanket "no new schemas / MCP tools / CLI subcommands without explicit approval" clause is replaced with a proportionate Change discipline rule: additive changes are allowed without prior approval if they ship behind a v1 schema, have a contract test, get a CHANGELOG entry, and respect the dual-copy invariant. Breaking changes to v1 schemas / public HTTP endpoints / A2A profiles still require an ADR and a version bump. -
README aligned with multi-surface framing (#64, #68). Hero, fit-in-stack table, "What this is" list, and Status table now reflect MCP + HTTP + A2A + Cloudflare Worker as four delivery surfaces over one core service layer. New Self-host via HTTP API section for shops whose stack does not run MCP: six endpoints listed, one curl probe against the Middle Corridor
pre_signature_escalate.request.jsoncontract fixture, container build commands, and an honest "not a hardened internet-facing server" boundary. The Status row honestly statesno paying customers yet — illustrative usage onlyper the new AGENTS.md honesty rules. -
Hardened the README token guard in
scripts/validate.py(#65). The guard previously asserted the literal pre-multi-surface hero string and failed onmainthe moment #64 landed. The token now asserts the durable substring"evidence-discipline layer for strategic intelligence agents"so future hero polish does not break CI. -
Automated MCP registry publish on tag push (#67). New
.github/workflows/publish-mcp-registry.ymltriggers onv*tag push, syncsserver.jsonversion to the tag viajq(defensive against stale release commits), authenticates via GitHub OIDC (no PAT), and runsmcp-publisher publish.workflow_dispatchwith aversioninput is available for manual catch-up runs. The v1.0.1 registry entry was published manually via localmcp-publisheron 2026-05-26 (during a GitHub Actions outage) to close the v0.8.2 → v1.0.1 drift before the automation went live. -
Skill-improvement eval layer added for packaged runtime skills. New
evals/skill-improvement/introduces a lightweight SkillOpt-style loop for validation-gated edits toskills/agenda-intelligence/SKILL.md: JSONL cases, a manual rubric, baseline/after reports, and a local case validator.docs/evaluation.mdnow lists this as a separate eval layer from deterministic benchmarks and agent-eval deltas. The first accepted skill edit tightens composed regional + sector lens loading, source-as-data handling, stale/conflicting-source disclosure, signal classification versus marker semantics, and no-advice boundaries. No schemas, CLI, MCP, HTTP, or A2A contracts changed.
Operational changes outside the package itself (recorded here for audit, not for PyPI release notes):
- Branch protection on
mainacross all four portfolio repos now enforces required CI checks before merge;allow_auto_mergeis enabled at the repo level sogh pr merge --auto --squash --delete-branchwaits for CI rather than fast-pathing. - Agenstry agent cards verified live across all three Cloudflare Workers (general + kazakhstan + middle-corridor-deal-risk-gate) using
deploy/cloudflare-worker/scripts/verify-agent-card.jsafter the landing-page deploy.
[1.0.1] – 2026-05-23
Metadata-only patch release for MCP directories and agent registries.
- Expanded the 16 stdio MCP tool descriptions with clearer "when to use", input, output, and boundary guidance so directories such as Glama can present the server more accurately.
- Added non-validation
descriptionannotations to MCPinputSchemaproperties and mirrored them in both agent-manifest copies. - No runtime behavior, schema validation semantics, CLI behavior, or tool names changed.
[1.0.0] – 2026-05-23
First v1.0 release. Locks the contract surface defined by ADRs 0011–0013 per ADR 0003: future breaking changes to schemas, MCP tools, or the manifest contract fields (name, version, schemas, mcp, cli) require a v2.0 bump.
No new product behavior versus 1.0.0rc1; the RC was verified end-to-end via the post-release smoke workflow against the published PyPI wheel.
Also included
- CI smoke regex relaxed to accept PEP 440 pre/post/dev versions (#59).
[1.0.0rc1] – 2026-05-23
First release candidate for the v1.0 contract-freeze line. No new product behavior; this RC packaged the contract surface defined by ADRs 0011–0013 and the three follow-up fixes (#54, #55, #56) for end-to-end verification before the final v1.0.0.
The contract surface is: name, version, schemas (map of {path, schema_version} per ADR 0011), mcp ({spec, tools[*]} per ADR 0012), cli. See the manifest's _contract_fields and _informational_fields arrays for the authoritative split.
Pre-release publication: pip install agenda-intelligence-md==1.0.0rc1 (default pip install agenda-intelligence-md still resolved to the latest stable, 0.9.3, at the time of release).
Pre-v1.0 contract-freeze follow-ups
Three small fixes closing gaps left after PRs #50–#53 (ADR 0011–0013 contract freeze). No behavior change for callers; all changes are to the manifest contract surface or its CI guards.
- fix(manifest): correct stale
clientrypoint string (#54) — ADR 0013 flagged the manifestclifield as still pointing at the backward-compat shimscripts/agenda_intelligence.py; the correction was scheduled for the ADR 0013 impl PR (#53) but missed. Both dual-copy manifests now point at the real entrypoint (python3 -m agenda_intelligence.cli). Informational string correction per ADR 0013, not a contract change. - fix(schemas): restore dual-copy parity for
agent-manifest.schema.json(#55) — PR #52 added the schema only undersrc/agenda_intelligence/data/schemas/v1/without the paired top-level copy required by the dual-copy invariant inCLAUDE.md. Top-level copy restored andtest_packaged_schemas_match_top_level_schemasis now bidirectional via set equality on filenames, so asymmetric adds fail CI in either direction. - feat(schemas): align
agent-manifest.schema.jsonwith ADR 0013 contract (#56) — The manifest schema predated ADR 0013 and still required the legacy shape (entrypoint, protocols, lenses);validate-manifestpassed by accident. Rewritten to require the ADR 0013 contract surface (name, version, schemas,mcp,cli) plus_contract_fields/_informational_fieldsarrays. Adds$idper ADR 0011 andx-schema-versionper repo convention. New tests pin the canonical contract-field set and liftvalidate-manifestinto pytest so a stale schema fails CI directly.
[0.9.3] – 2026-05-22
Docs — v0.9 release gate closed (all 9/9 acceptance criteria ✅)
Two final v0.9 acceptance items shipped in this release.
Phase 4b — evidence-mode discipline extended to 5+5 with full docs (#43)
tests/fixtures/evidence_mode/now ships 5 golden and 5 failure fixtures (was 3+3). Two new golden cases cover vessel SDN attribution with caller-supplied source and EU CBAM regulatory[verify]-marker; two new failure cases cover sanctions designations and EU AI Act effective-date claims stated as bare facts. Fixtures are generated deterministically bytests/fixtures/evidence_mode/build.pyfrom one baseline memo. Test count: 131 → 142.docs/evidence-modes.md— canonical reference for the three schemaevidence_modevalues (reasoning_only,user_provided,mixed), the post-hoccheck_evidence_mode_disciplinerule, and the full 5+5 fixture table. Clarifies relationship to the four-mode documentation labels indocs/glossary.md.docs/rubric.md— 10-dimension product-shell rubric (decision frame, routing, evidence mode, fact/assessment separation, mechanism specificity, actor incentives, watch-next indicators, source/audit integrity, no unsupported determinative claims, schema validity) plus 6-point human review checklist. Complements (does not replace) the deterministic heuristic scorer inevals/rubric.mdand the reviewer checklist inevals/human_checklist.md. Not a CI gate in v0.9.
Phase 8 — 4-layer map deduplicated across the portfolio (#44)
- The "Where this fits in the Agenda Intelligence stack" 4-row table is now canonical in this repo's
README.mdonly. The three skill repos drop their local duplicates and link to the canonical anchor: global-think-tank-analyst#10, central-asia-caspian-hybrid-intelligence-skill#12, gulf-middle-east-hybrid-intelligence-skill#11.
ROADMAP
- All 9 v0.9 acceptance criteria now ✅. Sections marking criteria #4 (🟡 → ✅) and #8 (⬜ → ✅) updated with PR references.
No schema, CLI, or MCP tool changes. No new dependencies.
[0.9.2] – 2026-05-21
Docs — canon alignment with product-shell role
AGENTS.mdProject identity rewritten: this repo is the product entry point and evidence-discipline layer, not just an infrastructure layer. New section documents the four product MCP tools (analyze,validate_memo,list_signals/get_signal,deep_divestub) and the geography routing term sets backinganalyze. Vendoredskills/agenda-intelligence/**now explicitly described as lighter derived copies; canonical reasoning and regional depth still live in the GTTA and vertical-specialist repos.llms.txt(and packaged copy undersrc/agenda_intelligence/data/) rewritten to match: drops the legacy "evidence and eval infrastructure layer" framing, lists the four product MCP tools, and documents the geography routing term sets verbatim.
Added — AnalyzeRequest public example and routing-canon sync guard
examples/agenda-request.json— minimal AnalyzeRequest for copy-paste integration; validated againstagenda-request.schema.jsonbyscripts/validate_public_examples.py, which gained a routing rule foragenda-request.jsonand*.request.jsonfiles.tests/test_product_shell.py::test_routing_terms_documented_in_canon— parametrised overCA_CASPIAN_TERMS/GULF_ME_TERMS/EU_TERMS/SANCTIONS_TERMS. Every term in the authoritative Python constants must appear verbatim in bothAGENTS.md(Geography routing) andllms.txt. Test count: 121 → 125.
[0.9.1] – 2026-05-21
Added — audience_detail freeform field on agenda-request (ADR 0009)
schemas/agenda-request.schema.json(and packaged copy) gains an optionalaudience_detailstring (minLength: 1). The existing enum-boundaudiencefield stays as the prompt-routable signal;audience_detailcarries the caller's original framing (e.g."AI company leadership, product and compliance teams") so it is not silently coerced to the closest prototype._format_request_contextinsrc/agenda_intelligence/product.pyrendersaudience_detailinto the verified request-context block alongsideaudiencewhen present.- Additive change per ADR 0003: existing requests remain valid; no migration required.
- Closes the second observation from
evals/agent-eval/gtta-global-policy.mdabout silent caller-intent loss at theaudienceboundary. - 3 new unit tests in
tests/test_product_shell.py. Test count: 118 -> 121.
Added — EU geography and term routing in route_modules
src/agenda_intelligence/product.pynow routes geography"EU"/"Europe"(exact) and question text containing long-form EU terms (european union,european commission,eu ai act,gdpr,cbam,cjeu,nis2,brussels,ecb,schrems, etc.) to theeuregional specialist. The bare two-letter"eu"is matched only as an exact geography token to avoid false-positive substring hits inside words likeexposureorqueue.MODULE_PATHS["eu"]resolves to the existingskills/agenda-intelligence/references/regional/eu.md(already shipped in v0.9.0 and present in the packaged data mirror); this commit makes the lens reachable fromanalyzerather than only via the GTTA SKILL's load-list.tests/test_product_shell.pygains seven direct unit tests forroute_modules, including a regression guard against substring false positives, an EU + sanctions composition case, and a module-content-loadable check. Test count: 111 -> 118.- Closes the gap surfaced by
evals/agent-eval/gtta-global-policy.mdobservation 3: the GTTA SKILL listed EU as a loadable lens butroute_moduleshad no EU branch, someta.modules_usednever recorded EU even when the question was EU-centric.
[0.9.0] – 2026-05-20
Changed — v0.9 scope: agent-eval delta and product-shell narrative alignment
- ROADMAP
v0.9rewritten from "verify-quotes network mode improvements" to "agent-eval delta and product-shell narrative alignment". Verify-quotes patches moved to a newv0.9.xdeferred-patches section. v0.9 explicit non-goals: factual verification schema, source reputation scoring, live news gathering, crawler,deep_diveimplementation, new MCP tools. - README headline rewritten: drops "trusted geopolitical intelligence layer" framing for "MCP product shell and evidence-discipline layer for strategic intelligence agents". States no live retrieval and no factual verification as explicit non-goals before v1.0.
- ADOPTION MCP section now lists the product-shell tools (
analyze,validate_memo,list_signals,get_signal,deep_dive) alongside the 11 validation tools, with a one-paragraph product-shell summary. llms.txtand packaged copy:Source Acquisition Layerrenamed toSource Planning Layerto match CONTEXT canon. Thesource_acquisitionmanifest key is unchanged (compatibility wire name).
Added — Agent-Eval Delta glossary and ADR 0008
CONTEXT.mdadds glossary entries for Agent-Eval Delta (per-case structural delta from the agent-integrator perspective; not factual, not aggregate, not a model-quality comparison) and Practitioner Review (optional, audience-gated). Two new rules in Flagged ambiguities make the boundary explicit.docs/adr/0008-agent-eval-delta-is-structural-product-validation.mdrecords the validation-story decision for v0.9.docs/agent-eval-methodology.mdtightened: live-source-backed examples map touser_providedormixedforanalyze;live_source_backedis intentionally absent fromagenda-request.schema.jsonbecause live retrieval is upstream of Agenda Intelligence.evals/agent-eval/scaffolded with three case files (gtta-global-policy.mdintended as the v0.9 full case;ca-caspian-sanctions.mdandgulf-me-hormuz-shipping.mdas stubs not to be cited until run).
Added — Agent-eval case template
- README and evaluation docs now link the agent-eval methodology as the agent-first structural delta method.
evals/agent-eval/now contains a README and reusable case template for skill-repo evals.
Added — Request-context prompt guardrails
analyzenow injects a server-verified request context block into the system prompt, carrying question, decision context, audience, geography, time horizon, evidence mode, and depth.- The prompt now explicitly tells the model not to invent citations when
evidence_modeisuser_providedormixedbut no source material is present in the request.
Fixed — Product shell contract alignment
- README now describes the full 16-tool MCP surface in both the overview and MCP table.
analyzenow honorsoutput_format: markdownby returning a server-renderedrendered_memoalongside the structuredmemo.sanctions-sectornow uses thesector_specialistmodule role, andagenda-memo.schema.jsonaccepts that role.
[0.8.2] – 2026-05-20
Added — Official MCP Registry ownership marker
- README footer adds
mcp-name: io.github.vassiliylakhonin/agenda-intelligence-mdso the official Model Context Protocol Registry (registry.modelcontextprotocol.io) accepts the publishedserver.jsonagainst the PyPI package. No functional change.
[0.8.1] – 2026-05-20
Fixed — machine-verified audit replaces LLM self-grading
analyzenow overwritesaudit.validation_scoreandaudit.validation_detailswith values computed from six observable structural checks (schema valid, fact/assessment separation, unknowns acknowledged, modules match routing, watch_next present, evidence_mode within contract). The model can no longer self-assign a 0.99 audit score.- The model's self-grade is preserved as
audit.self_assessed_scorefor transparency, andaudit.machine_verified: trueflags the rewrite explicitly. audit.provenance(per-claim basis labels) is substantive content and is preserved as the model wrote it.
Changed — system prompt enforces output format
assemble_system_promptappends a dedicated===== OUTPUT FORMAT — STRICT =====block that forbids markdown fences and surrounding prose, lists required keys, and provides a compact JSON skeleton. Improves first-pass parse rate for weaker host models.
Added — schema fields for machine-verified audit
agenda-memo.schema.json: optionalaudit.machine_verified(bool) andaudit.self_assessed_score(number 0-1). Clarified thatvalidation_scoreis structural only.
Added — README quickstart explains [llm] extra
- Quickstart shows
pip install "agenda-intelligence-md[llm]"+ANTHROPIC_API_KEYto enable direct API calls fromanalyze. Without it,analyzestill returns the assembledsystem_promptfor the host model to complete.
Tests
tests/test_product_shell.py::test_analyze_overrides_self_graded_audit_scoreexercises the audit rewrite, the self-grade preservation, and the provenance pass-through.
[0.8.0] – 2026-05-20
Added — Agenda Intelligence product shell
- Five new MCP tools turning this repository into the product entry point:
analyze,validate_memo,list_signals,get_signal,deep_dive. MCP tool count: 11 → 16. analyzevalidates the request againstagenda-request.schema.json, routes geography to in-repo regional / sector references (Central Asia + Caspian, Gulf + Middle East, sanctions), assembles a system prompt from the bundled SKILL.md and reference files, and — whenANTHROPIC_API_KEYis set and the optionalanthropicSDK is installed — calls the Anthropic API and validates the returned memo againstagenda-memo.schema.json. Without an API key, returns a skeleton memo plus the assembledsystem_promptso a host model can complete the analysis.validate_memoschema-checks memos againstagenda-memo.schema.json.list_signals/get_signalexpose a vendored snapshot of the Global Think Tank Analyst signal archive underdata/signals/.deep_diveis a v2 stub returning a planned-status message.
Added — Product request and memo schemas
schemas/agenda-request.schema.jsondefines the input contract (question, decision_context, audience, geography, time_horizon, evidence_mode, depth, output_format).schemas/agenda-memo.schema.jsondefines the output contract (meta with modules_used and gtta_version, risk_summary, decision_frame, analysis with fact/assessment/assumption/unknown separation, scenarios with probability ranges, options, recommended_actions, failure_modes, watch_next, audit with validation_score and provenance).- Both schemas are draft 2020-12, strict (
additionalProperties: false), and include validated examples. agent-manifest.jsongains aproductblock surfacing the request/response schemas, the five MCP tools, the signal source, and the explicitlive_source_retrieval: falseflag.
Added — Optional LLM dependency
pip install agenda-intelligence-md[llm]installsanthropic>=0.40soanalyzecan call the Anthropic API directly viaANTHROPIC_API_KEY. No new hard dependency.
Added — Vendored signal archive
scripts/sync_signals.pymirrors the GTTAsignals/directory intosrc/agenda_intelligence/data/signals/, following the same dual-copy pattern asschemas/↔data/schemas/.tests/test_signal_sync.pyenforces parity when a local GTTA checkout is present.
Added — Product-shell integration tests
tests/test_product_shell.pycovers geography routing (Kazakhstan → CA-Caspian, global → GTTA only), validate_memo happy and negative paths, the LLM-invocation branch with mocked Anthropic responses, and signals / deep_dive coverage. Tests do not require network or credentials.
Changed — Repository positioning
- README now leads with the product framing (Agenda Intelligence — trusted geopolitical intelligence layer for agentic workflows). The "What this is" list opens with the MCP product shell. Companion READMEs (Global Think Tank Analyst, Central Asia + Caspian, Gulf + Middle East) name Agenda Intelligence and document automatic activation rules.
MCP.mddocuments the five new product-layer tools and updates the tool-count header (11 → 16).
Added — Agenda brief data integrity notes
- Optional
data_integrity_notesfield added toagenda-brief.schema.jsonfor prompt-injection, source-anomaly, stale/conflicting-source, retrieval-limit, or other integrity concerns surfaced by an analyst or agent. data_integrity_notesis a recording surface only: validators check field shape, but do not detect integrity risks or verify factual truth.
CI & release
- GitHub Actions workflow dependencies moved to Node 24-compatible
actions/checkout@v6andactions/setup-python@v6. - PyPI publish steps now explicitly disable attestations while token-based publishing remains active, matching the documented Trusted Publishing migration path.
Docs
- Use-case and integration docs now frame source plans as evidence expectations, not live retrieval or factual verification.
- MCP and adoption docs now list the full 16-tool surface, including the product-shell layer.
[0.7.5] – 2026-05-20
Added — Source-plan coverage diagnostics
source-coverageCLI command and MCPsource_coveragetool report covered and missing category-specificmust_checksource types.source-categoriesCLI command and MCPlist_source_categoriestool expose packaged source requirement categories for agents and CI.source_coverage.required_source_detailsexplains which evidence source entries matched each required source type and which terms or aliases matched.- Optional
source_categoryfield added to evidence packs so coverage diagnostics can select the packaged source plan without a separate category argument. benchnow includes source-plan coverage diagnostics in Markdown and JSON output when evidence packs includesource_category.
Changed — Benchmark baseline
- Bundled source-backed baseline remains 20 cases, with 100% schema-valid, 100% evidence packs, and 100% claim-level audit.
- Baseline now also reports 100% source-category coverage, mean source-plan coverage of 14.8%, and 20 cases with diagnostic source-plan gaps.
Boundary
- Source-plan coverage remains diagnostic before v1.0. It does not discover sources, score reputation, verify factual truth, replace analyst judgment, or redefine
validate-evidenceas category completeness. source-coverage --strictis opt-in and separate from base schema validation.
[0.7.4] – 2026-05-17
Added — Source Ingest skill
- New source-ingest skill: normalizes user-supplied documents (PDF, DOCX, XLSX, URL, article, transcript) into a structured source record with metadata, Axis A/B provenance tags, key-claims table, excerpts, and limitations.
- Live retrieval failure handling: fallback path when a URL fetch fails.
- Source-ingest routing references vertical source guides (Central Asia + Caspian, Gulf + Middle East) instead of duplicating regional source tier content.
Added — Threat model
docs/threat-model.md— explicit statement of what the validator catches and what it does not.- Adversarial fixtures + pytest suite codifying the documented threat-model gaps.
Added — Bench
- EU-CBAM case added to bundled bench; baseline now covers 5 source-backed cases (was 3).
Docs
- Stack positioning synced across
pyproject.toml,llms.txt,agent-manifest.json, andADOPTION.md. CLAUDE.mdscope tightened to evidence/eval infrastructure framing.README.md: stack-role tag, audience-first first screen, stack-context block, MCP framed as distribution surface.- Bench baseline counts in docs aligned with committed benchmark output.
Chore
.claudeignoreadded with build, OS, and historical release-notes exclusions.
[0.7.3] – 2026-05-14
Added — Signal lifecycle
- Signal lifecycle tracker: schema, reference, and workflow for tracking
observability signals across runs (
docs/signal-lifecycle.md,schemas/signal-tracker.schema.json).
Added — Provenance tags
- Per-claim inline provenance tags rendered in Markdown output, surfacing Axis-A source type and Axis-B action flags directly in generated reports.
Added — Cases & lenses
- BIS AI Diffusion Rule flagship case study (
cases/bis-ai-diffusion) with primary-source evidence. - Gulf + Middle East added as the second vertical specialist in the Regional lenses set, alongside Central Asia + Caspian.
Added — Evals
- Trust-layer evaluation parameters added to the human review checklist.
Added — Docs & policy
AGENTS.mdand Claude Code working rules formalised.- Release-artifact process documented.
CI & packaging
- CI smoke-tests built package artifacts post-build.
- CI guard prevents tracked generated artifacts from re-entering the tree.
audit_claimsadded to MCP smoke run (full 8-tool wire-protocol coverage).- Packaged data assets kept in sync with top-level sources via test gate.
Fixed
- README status block: stale MCP wording corrected.
cli.py: flake8 E501 lint violation.
Removed / cleaned
- Stale
experimentallabels removed from README docs table. - Generated package artifacts no longer tracked in the repo.
[0.7.2] – 2026-05-12
Repositioned
- Project repositioned as evidence & eval layer for strategic intelligence agents. README rewritten: "What this is / What this is not", 60-second quickstart, status table, limitations, Mermaid architecture diagram.
docs/evaluation.mdrewritten around four explicit eval layers; factual truthfulness marked not implemented.
Added — CLI
agenda-intelligence check/audit/report/evalaliases for common workflows.agenda-intelligence audit-claims <audit.json> [--strict] [--format json]— validates claim-level evidence-audit JSON;--strictexits non-zero on orphan refs.agenda-intelligence bench <dir> [--strict] [--min-score N] [--format json]— discovers*.brief.jsonwith sibling.evidence.json/.audit.json, runs validate + audit + score across all cases, emits Markdown or JSON report.agenda-intelligence verify-quotes <pack.json> [--strict] [--texts-dir DIR]— experimental local-text quote verification.agenda-intelligence scoregains--format jsonand--min-score Nflags.
Added — Schemas & Examples
- Experimental
schemas/evidence-audit.schema.jsonfor claim-level evidence audit (claim_id,claim_type,evidence_ids,support_level,uncertainty,risk_if_wrong). - Three flagship source-backed example sets with brief + evidence + claim-level audit:
eu-ai-act,red-sea-shipping,sanctions-routing.
Added — MCP
audit_claimsMCP tool (8th tool): validates claim-level audit JSON via wire protocol.scripts/smoke_mcp.pynow exercises all 8 tools includingaudit_claimsvia full JSON-RPC cycle (initialize → tools/list → 3× tools/call).- MCP wire-protocol verification added to
make ci.
Added — Evals & CI
agenda_intelligence.benchmodule:discover_cases,run_case,summarize,render_markdown,to_json— deterministic, LLM-free structural harness.evals/run_benchmark.pyscript and committed baselines:evals/baselines/source-backed.{md,json}..github/workflows/bench.yml— CI bench gate (--strict --min-score 80) with baseline drift check.- 13 new pytest tests covering all new commands and MCP tool.
make ciextended: MCP smoke + bench;make ci-fastfor inner loop.scripts/install-hooks.shpre-push hook (runsmake ci-fastbefore every push).
Added — Doctor & Config (from 0.7.2 base)
agenda-intelligence doctorfor local package and MCP self-diagnosis.agenda-intelligence doctor --jsonfor machine-readable diagnostics.
Bundled baseline
- 5 cases (eu-ai-act, eu-cbam, red-sea-shipping, sanctions-routing, bis-ai-diffusion), mean 87.0/100, 100% schema-valid, 100% with evidence, 100% with audit, 0 orphan refs.
[0.7.1] – 2026-05-06
Added
agenda-intelligence mcp-config --clientfor generic, Claude Desktop, Cursor, and Codex local MCP config output.- Client-specific MCP setup blocks in the integration docs.
[0.7.0] – 2026-05-06
Added
- MCP
score_outputtool for before/after protocol-marker quality scoring. - Shared MCP smoke coverage now verifies
score_outputin addition to source-plan lookup.
Changed
- The before/after evaluation script now uses the package scorer as its single source of rubric logic.
[0.6.1] – 2026-05-06
Added
agenda-intelligence mcp-configfor copy-pasteable MCP stdio client configuration.- Post-release smoke coverage for
agenda-intelligence-mcp.
[0.6.0] – 2026-05-06
Added
agenda-intelligence-mcpconsole command for a minimal stdio MCP server.- MCP JSON-RPC handlers for
initialize,ping,tools/list, andtools/call. - MCP tool exposure for
validate_brief,validate_evidence,get_protocol,list_lenses,get_lens, andsource_plan.
[0.5.5] – 2026-05-06
Added
agenda-intelligence --versionfor direct CLI version checks.
Fixed
- Release and manual publish workflows now clean
dist/andbuild/before building, preventing old tracked artifacts from being rechecked or reuploaded.
[0.5.4] – 2026-05-06
Fixed
- Package version drift:
agenda_intelligence.__version__, package metadata, and both manifests now report the same release version. - README GitHub Release install snippet now tracks the current release artifact.
Added
- Regression coverage for package/manifest/README version consistency.
[0.5.3] – 2026-05-05
Added
- Evaluation toolkit: rubric, LLM judge prompt, human checklist, sample cases.
- Heuristic 0-100 JSON brief scoring via
agenda-intelligence score brief.json. - Evidence-linked scoring via
agenda-intelligence score brief.json --evidence evidence-pack.json. - Source‑backed examples (EU AI Act, sanctions routing, Red Sea shipping).
- Use‑case docs for policy monitoring, sanctions compliance, market risk, founder operating context.
- Tutorial for end‑to‑end quickstart (5‑10 min “aha” moment).
- Demo output section in README.
startcommand now the primary onboarding CLI entry‑point.
Changed
- Version drift eliminated:
pyproject.toml(0.5.3),agent‑manifest.json(0.5.3), packaged manifest data (0.5.3), removedsetup.cfg. - Top-level and packaged agenda brief schemas are now kept in sync.
- MCP read tools now return packaged protocol, lens, and source-plan data instead of stubs.
- README cleaned: removed old release notes, consolidated into a single coherent document.
- MCP transport/server marked as planned while read-only Python tool functions are documented as implemented.
[0.5.1] – 2026‑05‑05
Fixed
- Version sync across files.
setup.cfgremoved to avoid trust smells.- Agent‑manifest version updated to 0.5.1.
- README wheel link updated to v0.5.1.
[0.5.0] – 2026‑05‑04
Added
- Source Acquisition Layer:
source‑plan,source‑types,list‑source‑packscommands. startcommand for guided analysis.memory‑searchfor AnalysisBank.- Expanded
source‑requirements/with more categories. - CI workflow updates.
[0.4.0] – 2026‑04‑28
Added
- Source Acquisition Layer (initial) – tells agents which source types to check before making claims.
source‑plancommand (stub).technology‑ai,sanctions,regulation,elections,conflict‑security,energy,trade,financial‑market,regional‑risksource requirement files.- AnalysisBank memory cards (failures & successes).
- Regional lenses: Central Asia & Caspian, Middle East, EU.
- Sector lenses: sanctions, export controls.
- Revised
Agenda‑Intelligence.mdprotocol (v0.4.0) with stronger evidence discipline.
[0.3.0] – 2026‑04‑20
Added
- Agent‑first package contracts:
agent‑manifest.json, JSON schemas for briefs, evidence packs, memory cards. - CLI validation commands:
validate‑brief,validate‑evidence,validate‑manifest. list‑lenses,get‑lens,get‑protocolcommands.scorecommand (stub) for before/after evaluation.
[0.2.0] – 2026‑04‑12
Added
- AnalysisBank reasoning memory layer: stores reusable patterns from good/bad outputs.
analysis‑bank/directory with failures and successes.eval_before_after.pyscript for before/after scoring.- Sample
before‑after/examples.
[0.1.0] – 2026‑04‑05
Added
- Initial release of
Agenda‑Intelligence.mdprotocol. - Core reasoning workflow: signal classification, what changed, why it matters, who is affected, main uncertainty, watch‑next indicators.
- Basic CLI skeleton (
agenda‑intelligence). examples/folder with sample briefs.schemas/folder with JSON schemas.skills/agenda‑intelligence/OpenClaw skill wrapper.