diff --git a/.memory-bank/guides/reference/npm-package-release-runbook.md b/.memory-bank/guides/reference/npm-package-release-runbook.md index 02925a8..4226aeb 100644 --- a/.memory-bank/guides/reference/npm-package-release-runbook.md +++ b/.memory-bank/guides/reference/npm-package-release-runbook.md @@ -2,7 +2,7 @@ file: .memory-bank/guides/reference/npm-package-release-runbook.md description: Practical runbook for versioning, verifying, publishing and post-release checking the `@dd-bot-platform/*` npm packages. purpose: Read when preparing or executing a real npm release for the first publishable framework packages so maintainers can follow one short canonical checklist instead of reconstructing the process from workflow files, Changesets config, and protocol notes. -version: 1.2.0 +version: 1.3.0 date: 2026-04-20 status: ACTIVE parent: .memory-bank/guides/reference/index.md @@ -14,6 +14,9 @@ related_files: - .github/workflows/release-packages.yml - scripts/publish-private-packages.mjs history: + - version: 1.3.0 + date: 2026-04-26 + changes: Added `@dd-bot-platform/channel-runtime` to the explicit runbook package set and pack/post-publish checklist after PRT-043 release readiness proved it is already controlled by the publish script allowlist. - version: 1.2.0 date: 2026-04-22 changes: Widened the allowed publish set to include `@dd-bot-platform/core` after the broader Wave 2 runtime-helper pack made the package a real framework seam rather than a bootstrap-only stub, and added package-cleanliness guidance for stale `dist` prevention before `pack`/publish. @@ -27,6 +30,7 @@ history: ## Use this runbook when - releasing `@dd-bot-platform/api-contract`; +- releasing `@dd-bot-platform/channel-runtime`; - releasing `@dd-bot-platform/core`; - releasing `@dd-bot-platform/scenario-system`; - confirming whether a merged framework package change is actually ready to go to npm. @@ -53,6 +57,7 @@ If both packages change together, bump each package according to its own consume This runbook currently applies only to: - `@dd-bot-platform/api-contract` +- `@dd-bot-platform/channel-runtime` - `@dd-bot-platform/core` - `@dd-bot-platform/scenario-system` @@ -68,6 +73,7 @@ Do not widen publication beyond this allowlist until the owning protocol wave ex - `pnpm build` 4. Run package artifact proof: - `pnpm --filter @dd-bot-platform/api-contract pack --pack-destination ` + - `pnpm --filter @dd-bot-platform/channel-runtime pack --pack-destination ` - `pnpm --filter @dd-bot-platform/core pack --pack-destination ` - `pnpm --filter @dd-bot-platform/scenario-system pack --pack-destination ` - inspect `package/package.json` from each tarball @@ -136,6 +142,9 @@ For each released package: 1. Check the registry version: - `npm view @dd-bot-platform/api-contract version` + - `npm view @dd-bot-platform/channel-runtime version` + - `npm view @dd-bot-platform/core version` + - `npm view @dd-bot-platform/scenario-system version` 2. Check dist-tags if needed: - `npm dist-tag ls @dd-bot-platform/api-contract` 3. Verify installability from a clean temp project. diff --git a/.memory-bank/plans/index.md b/.memory-bank/plans/index.md index 3c9148b..8632996 100644 --- a/.memory-bank/plans/index.md +++ b/.memory-bank/plans/index.md @@ -2,8 +2,8 @@ file: .memory-bank/plans/index.md description: 'Plans hub для bot-platform: framework epics, ADRs, protocols, current status и verification planning.' purpose: Читать для понимания delivery contour `bot-platform`, не смешивая framework delivery с SellerAgent и Docoved product waves. -version: 0.7.0 -date: 2026-04-25 +version: 0.11.0 +date: 2026-04-26 status: DRAFT tags: [plans, bot-platform, adr, epics, protocols, delivery] parent: .memory-bank/index.md @@ -14,6 +14,18 @@ children: - protocols/index.md - verification-matrix.md history: + - version: 0.11.0 + date: 2026-04-26 + changes: Marked PRT-043 phase-2 implementation planning complete and linked the subagent execution companion and task workspace. + - version: 0.10.0 + date: 2026-04-26 + changes: Marked PRT-043 phase-1 review complete and noted new ownership, boundary contract, MBB routing, verification, release/rollback, and no-storage safeguards. + - version: 0.9.0 + date: 2026-04-26 + changes: Noted that PRT-043 phase-0 elaboration is complete and expanded the plans hub summary with command normalization, safe failures, config compatibility, idempotency, anti-abuse, and observability requirements. + - version: 0.8.0 + date: 2026-04-26 + changes: Added PRT-043 as the draft follow-up for channel interaction runtime after PRT-042 closed the canonical response document first wave. - version: 0.7.0 date: 2026-04-25 changes: Marked PRT-042 closed after first-wave channel-runtime implementation and retained publication/product direct-consumption as explicit follow-up. @@ -76,11 +88,38 @@ history: - `protocols/PRT-040-governed-content-source-processing-and-workflow-backed-import-substrate.md` - `protocols/PRT-041-cross-repo-contract-dependency-boundary-realignment.md` - `protocols/PRT-042-channel-runtime-canonical-document-command-and-rendering.md` +- `protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `protocols/PRT-043-channel-interaction-runtime-review-details.md` - `verification-matrix.md` ## Immediate planning priorities -### 1. Closed channel-runtime first wave +### 1. Draft channel interaction runtime follow-up + +`protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` is the draft follow-up to closed `PRT-042`. + +Phase state: +- стадия проработки протокола: фаза 0 выполнена. +- стадия проработки протокола: фаза 1 выполнена. +- стадия проработки протокола: фаза 2 выполнена. + +Draft scope: +- actor-aware command runtime policy for system admins, workspace admins, employees/members, known external users, unknown external users, and anonymous actors; +- channel-neutral command input normalization and typed safe command failures; +- canonical command responses through `CanonicalResponseDocument`; +- channel-owned rendering from canonical markdown-compatible content; +- channel-instance threading behavior such as email `Re:` and Telegram reply-to-message; +- outbound delivery intent/result contracts; +- command-policy compatibility migration from legacy product fields such as `commandAccessPolicy`; +- idempotency, anti-abuse/rate-limit hooks, fallback diagnostics, and logging-first observability with no framework DB/UI in the first implementation; +- Docoved and SellerAgent adoption waves with beta verification. + +The protocol must reuse `spec/runtime/command-framework-contract.md` and must not create a second command framework inside `channel-runtime`. +Implementation code must not start until the pre-code gates in `PRT-043` are resolved. +Implementation task packets and subagent execution rules live in `protocols/PRT-043-channel-interaction-runtime-implementation-plan.md`. + +### 2. Closed channel-runtime first wave `protocols/PRT-042-channel-runtime-canonical-document-command-and-rendering.md` is closed for the first-wave shared channel-runtime seam. @@ -108,7 +147,7 @@ Still deferred by design: The stable runtime vocabulary belongs in `spec/runtime/channel-runtime-contract.md`; product mappings belong in product-local Memory Banks. -### 2. Closed dependency-boundary cleanup +### 3. Closed dependency-boundary cleanup `protocols/PRT-041-cross-repo-contract-dependency-boundary-realignment.md` is now closed for the concrete post-handoff package-boundary defect. @@ -118,7 +157,7 @@ Closed result: - Memory Bank navigation treats adoption packets as closed baselines; - `sales-agent` links remain lineage rather than normative sources. -### 3. Keep closed convergence docs as baseline +### 4. Keep closed convergence docs as baseline `protocols/PRT-036-platform-framework-and-product-repo-split.md` остается closed lineage for the repo split. `protocols/PRT-038-platform-product-line-convergence-and-shared-substrate-extraction.md` остается closed baseline for the three-layer handoff. @@ -127,7 +166,7 @@ Closed detailed child packets: - `protocols/PRT-039-shared-control-plane-access-channel-and-management-substrate.md` - `protocols/PRT-040-governed-content-source-processing-and-workflow-backed-import-substrate.md` -### 4. Separate framework epics from product epics +### 5. Separate framework epics from product epics В `epics/index.md` должны остаться только инициативы, которые после split-а по-настоящему принадлежат `bot-platform`, например: - foundation/repo topology; @@ -139,7 +178,7 @@ Closed detailed child packets: SellerAgent и Docoved epic families здесь быть не должны. -### 5. Keep one framework status snapshot +### 6. Keep one framework status snapshot `current-status-report.md` нужен сразу, чтобы не потерять ответ на вопросы: - какие packages уже существуют в skeleton; diff --git a/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md b/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md new file mode 100644 index 0000000..8850186 --- /dev/null +++ b/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md @@ -0,0 +1,803 @@ +--- +file: .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md +description: Framework protocol for channel interaction runtime: actor-aware command runtime, canonical response rendering, threading intent, and outbound delivery intent across Docoved and SellerAgent. +purpose: Define the next shared platform contract after PRT-042 so commands, canonical responses, reply/thread behavior, and outbound delivery semantics are configured consistently across Telegram, email, web, and future channels without moving product logic into bot-platform. +version: 0.5.0 +date: 2026-04-26 +status: DRAFT +epic: EP-022 +tags: [protocol, channel-runtime, command-runtime, rendering, threading, delivery, docoved, selleragent] +parent: .memory-bank/plans/protocols/index.md +related_files: + - .memory-bank/plans/protocols/PRT-042-channel-runtime-canonical-document-command-and-rendering.md + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md + - .memory-bank/spec/runtime/channel-runtime-contract.md + - .memory-bank/spec/runtime/command-framework-contract.md + - .memory-bank/spec/project/feature-area-boundaries.md + - .memory-bank/spec/operations/observability-and-incident-diagnostics.md + - .memory-bank/spec/operations/git-flow.md + - .memory-bank/spec/operations/deployment-architecture.md + - .memory-bank/spec/operations/hosted-beta-acceptance-contract.md + - .memory-bank/plans/verification-matrix.md + - .memory-bank/mbb/principles.md + - .memory-bank/mbb/delivery-docs-guide.md + - .memory-bank/mbb/indexing-guide.md + - /Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md + - /Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md + - /Users/deksden/Documents/_Projects/seller-agent/.memory-bank/plans/protocols/PRT-007-telegram-privileged-command-surface-bot-level-release-control-and-runtime-diagnostics.md +history: + - version: 0.5.0 + date: 2026-04-26 + changes: Recorded platform implementation progress for T-043-02/T-043-03: core command-framework contracts and channel-runtime threading/delivery summary contracts landed with subagent reports, verification, and local checks. + - version: 0.4.0 + date: 2026-04-26 + changes: Completed phase-2 implementation planning by linking the subagent execution companion, task workspace, task-packet discipline, dependency graph, verification-by-subagent rules, and local/hosted test lanes. + - version: 0.3.0 + date: 2026-04-26 + changes: Completed phase-1 protocol review with subagent reports, added entity ownership matrix, boundary-step contracts, pre-code gates, MBB routing, lean scope guards, release/rollback gates, no-storage statement, and stronger product/scenario verification. + - version: 0.2.0 + date: 2026-04-26 + changes: Completed phase-0 protocol hardening by adding policy precedence, actor/capability boundaries, command input normalization, safe failure rendering, config SSoT, migration compatibility, idempotency, anti-abuse, observability events, task graph, and deeper verification requirements. + - version: 0.1.0 + date: 2026-04-26 + changes: Opened the follow-up protocol for actor-aware commands, canonical channel rendering, configurable threading intent, outbound delivery intent, logging-first diagnostics, and Docoved/SellerAgent adoption. +--- + +# Protocol: Channel Interaction Runtime + +## Why this protocol exists + +`PRT-042` proved the first shared channel-runtime seam: +- products can map answer artifacts into a `CanonicalResponseDocument`; +- public/operator/debug visibility can be represented without product field leakage; +- minimal pure rendering helpers can live in `@dd-bot-platform/channel-runtime`; +- Docoved can consume the published package without depending on SellerAgent. + +The next drift risk is higher-level interaction behavior: +- commands are still shaped by Telegram-era code paths in product repos; +- email needs command parity without becoming a special channel exception; +- channels need a common way to receive canonical answers and render them for transport; +- reply/thread behavior should be configurable per concrete channel instance; +- outbound delivery outcomes need consistent correlation without introducing premature shared DB tables. + +This protocol opens that follow-up work. + +## Protocol elaboration state + +стадия проработки протокола: фаза 0 выполнена + +стадия проработки протокола: фаза 1 выполнена + +стадия проработки протокола: фаза 2 выполнена + +стадия реализации протокола: платформа T-043-02/T-043-03 выполнена + +Phase 0 reviewed platform contracts/product lineage; phase 1 reviewed the protocol through focused subagent reports in `.tasks/prt-043-protocol-review-phase-1/`; phase 2 defined subagent-based implementation planning in [PRT-043 implementation plan](PRT-043-channel-interaction-runtime-implementation-plan.md). +The first platform implementation slice was executed through `.tasks/prt-043-channel-interaction-runtime/`: +- `T-043-02` landed command-framework typed contracts in `@dd-bot-platform/core`; +- `T-043-03` landed provider-neutral threading and delivery result-summary contracts in `@dd-bot-platform/channel-runtime`; +- orchestrator hardened command availability to default deny when command policy is missing; +- both tasks have implementation reports, verifier reports, and local typecheck/test evidence in the task workspace. + +## Core decision + +`bot-platform` owns shared interaction mechanics. + +Product repos own product behavior. + +Therefore: +- command parsing, dispatch envelope, registry primitives, failure classes, and diagnostics must reuse the existing [Command framework contract](../../spec/runtime/command-framework-contract.md); +- channel-runtime may add interaction-facing contracts only where they connect command results, canonical response documents, render intents, threading intents, and delivery intents; +- Docoved owns Docoved commands, grounded-answer semantics, knowledge-source binding, and provider credentials; +- SellerAgent owns SellerAgent commands, commerce/conversation semantics, release-control behavior, and provider credentials; +- Telegram, email, web, and future channel adapters render and deliver provider payloads from the same canonical result instead of deciding answer semantics. + +No new framework-owned UI or DB tables are part of this protocol. +The current platform slice also intentionally does not ship product command catalogs, provider senders, hosted deploys, or product adoption changes. + +Phase 0 and phase 1 review found that the direction is sound, but implementation must be guarded by explicit ownership, policy precedence, safe failure rendering, config compatibility, idempotency, observability, and product adoption gates. +The accepted phase-1 findings are summarized in `.tasks/prt-043-protocol-review-phase-1/001-orchestrator-consolidated-review.md`. +This protocol still intentionally excludes framework DB tables, framework UI/admin, provider SDK senders, full universal HTML rendering, and product command catalogs in `bot-platform`. + +## Target architecture + +The intended flow is: + +1. A channel adapter receives an inbound event. +2. The adapter resolves actor context, channel instance config, and transport refs. +3. The command parser may normalize a command into a framework `CommandEnvelope`. +4. The command dispatcher checks command availability for the actor, product, channel kind, and channel instance. +5. The product-owned handler executes business logic. +6. The handler returns a `CanonicalResponseDocument` or a typed command failure. +7. The channel adapter renders the canonical document for the transport. +8. The adapter applies `ThreadingIntent` and `OutboundDeliveryIntent`. +9. The adapter logs structured delivery outcome and preserves correlation identifiers. + +The framework contract must make this flow typed and repeatable. +The product repos decide which handlers exist and what side effects they perform. + +Detailed boundary-step contracts are kept in [PRT-043 review details](PRT-043-channel-interaction-runtime-review-details.md) so this protocol stays lean and below the MBB decomposition threshold. + +## Interaction contract boundaries + +The platform should expose contracts, not own every step implementation. + +Entity ownership summary: +- command invocation, actor context, availability policy, availability decision, execution result, parser, registry, dispatch, and command failures belong to `command-framework`; +- canonical response document, visibility, citations/source refs, and existing pure rendering helpers belong to `channel-runtime`; +- threading and outbound delivery intent/result are candidate channel-runtime extensions only after the pre-code boundary gate proves they remain provider-neutral summary contracts; +- product repos own actor lookup, role/capability derivation, command catalog, handlers, persistence lookup for transport refs, provider retry behavior, and product-specific traces; +- adapters own provider syntax extraction, reply/header mapping, final provider payloads, and final send. + +The detailed ownership matrix is in [PRT-043 review details](PRT-043-channel-interaction-runtime-review-details.md). + +Product-owned implementations: +- actor lookup; +- role/capability derivation; +- command catalog and handlers; +- persistence lookup for transport refs; +- provider send/retry behavior; +- product-specific audit or trace artifacts. + +Current code anchors: +- command framework: `packages/core/src/command-framework`; +- channel threading: `packages/channel-runtime/src/threading.ts`; +- channel delivery summary: `packages/channel-runtime/src/delivery.ts`. + +Adapter-owned implementations: +- inbound event parsing; +- provider command syntax extraction; +- provider-specific reply/thread mapping; +- rendering to provider payloads; +- final transport send. + +## Actor-aware command model + +Commands must be configurable for different actor classes. + +Minimum actor classes: +- `system_admin`; +- `workspace_admin`; +- `workspace_member`; +- `verified_employee`; +- `external_known_user`; +- `external_unknown_user`; +- `anonymous`; +- product-defined extensions through a namespaced extension field. + +The exact role and membership resolution remains product-owned. +The framework owns only the command-availability contract and the stable actor-class vocabulary needed for cross-channel decisions. + +Actor classes are coarse categories, not a replacement for product capabilities. + +Resolution rule: +- product auth/membership code resolves the concrete actor; +- product policy maps that actor into one framework actor class plus optional product capability tags; +- the command runtime evaluates actor class and product capability tags through one typed policy decision; +- a product may deny a command even if the actor class is broadly allowed. + +The actor class must be logged as bounded metadata. +Raw emails, Telegram usernames, message bodies, auth tokens, or provider payloads must not be logged by the framework helper. + +Command availability must support: +- allow/deny by actor class; +- allow/deny by channel kind such as Telegram, email, web, CLI, or API; +- allow/deny by concrete channel instance, for example a specific Telegram bot or email address; +- product-level defaults; +- channel-instance overrides; +- explicit denial overriding broad allow rules; +- server-side enforcement independent of menu/help visibility. + +Policy precedence: +1. hard framework safety denial, for example malformed command envelope or unsupported channel capability; +2. product command-specific explicit denial; +3. concrete channel-instance explicit denial; +4. concrete channel-instance explicit allow; +5. channel-kind policy; +6. product default policy; +7. framework default deny. + +Rules: +- deny beats allow at the same specificity level; +- unknown actor class defaults to deny; +- missing channel instance config defaults to product default only if product config explicitly allows fallback; +- every fallback must emit a structured `compat_fallback_used` or policy-resolution diagnostic event. + +Examples: +- a system admin can receive `/diagnostics` in Telegram and email; +- a workspace admin can use release or binding commands where the product allows them; +- a normal employee can use read-only commands; +- an external unknown user can be denied all commands or allowed only public-safe commands; +- a command can be visible in Telegram but disabled for email, or vice versa, if product config says so. + +Command menu projection is not authority. +Menus/help are derived projections of the same server-side policy. + +## Command input normalization + +The platform must not canonize Telegram slash syntax as the only command grammar. + +Command parsing should produce the same `CommandEnvelope` from channel-specific inputs: +- Telegram slash command, bot mention, or direct-bot text; +- email subject command, first-line command, or structured inbound marker when product enables it; +- web/API structured command request; +- CLI command invocation. + +Channel adapters may own the first extraction step. +The command framework owns normalized parse results and parse failures. + +Required parse outcomes: +- `not_a_command` — continue ordinary message flow; +- `parse_error` — command-like input could not be parsed; +- `unknown_command` — parsed command key is not registered for this product/runtime; +- `valid_command` — dispatch may proceed to policy evaluation. + +Email command parsing must be conservative: +- ordinary user questions must not accidentally become commands; +- command recognition must be product-configurable per inbound address; +- parsing must not require special casing after dispatch. + +Telegram command parsing must preserve existing provider behavior: +- bot mentions and direct-chat command formats remain adapter-owned; +- Telegram menu projection is derived from server-side policy, not the other way around. + +## Command ownership boundaries + +`bot-platform` owns: +- command envelope and invocation source vocabulary; +- parser/dispatcher/registry contracts; +- command availability policy shape; +- actor-class vocabulary and extension point; +- typed command failure classes; +- generic command diagnostics and correlation fields. + +Product repos own: +- command names; +- handler implementations; +- argument semantics; +- permission mapping from memberships/roles into actor classes and capabilities; +- end-user help copy; +- provider menu synchronization such as Telegram command menus. + +Channel adapters own: +- transport tokenization quirks; +- provider-specific reply syntax; +- provider-specific menu apply/readback calls; +- transport payload size limits and send mechanics. + +Forbidden: +- adding `TelegramCommand*` as the shared platform abstraction; +- making email command behavior a separate product-only workaround when the behavior is actually channel-neutral; +- relying on hidden UI/menu visibility instead of server-side command authorization. + +## Command result and failure model + +Command execution must return a typed result, not throw opaque channel strings across boundaries. + +Minimum result kinds: +- `success` with `CanonicalResponseDocument`; +- `not_a_command` when ordinary answer flow should continue; +- `parse_error`; +- `unknown_command`; +- `validation_error`; +- `access_denied`; +- `dispatch_error`; +- `unsupported_channel`; +- `rate_limited`. + +User-facing failures should be renderable as `CanonicalResponseDocument` with public-safe wording. + +Rules: +- access denial must not reveal hidden command existence to external/unknown users unless product policy explicitly allows it; +- validation errors may include bounded field-level details only when safe for the actor class; +- dispatch errors should log incident-grade diagnostics but return safe user text; +- operator/debug details must stay in operator/debug visibility sections or trace artifacts; +- command results should carry `commandId`, `responseId`, `runId`, `traceId`, `channelRef`, and `transportMessageRef` where available. + +## Canonical response and universal rendering + +Universal rendering means the product/core emits one canonical response document, and each channel renders it for its transport. + +It does not mean that the framework owns one universal provider renderer. + +Target rule: +- command handlers and answer pipelines return `CanonicalResponseDocument`; +- public text remains markdown-compatible canonical content; +- citations/source refs remain channel-neutral; +- operator/debug content remains visibility-gated; +- channel adapters convert the document to provider payloads. + +Channel rendering examples: +- Telegram renders compact markdown/plain text, applies escaping, splits long messages, and can attach reply parameters; +- email renders HTML and plaintext alternatives, sets subject/thread headers, and can include compact citations; +- web renders a view model or components; +- CLI renders plaintext or markdown. + +The framework may provide pure helpers when they remove real duplication. +It must not absorb provider-specific HTML policies, Telegram parse modes, or product-specific source semantics unless two real consumers prove the shared shape. + +Rendering side-effect rules: +- rendering must not change answer/source semantics; +- rendering must filter visibility before provider payload creation; +- rendering must degrade explicitly when a provider cannot represent a markdown construct; +- long-message splitting must preserve citation/readback coherence where possible; +- render failures must be typed and logged with correlation ids, not silently downgraded to partial content. + +The framework may define render intents and result envelopes. +Adapters own final provider payloads. + +## Threading intent + +Threading is a channel-instance behavior setting. + +The framework should expose a provider-neutral `ThreadingIntent` vocabulary: +- `reply_to_origin` — answer as a reply to the inbound client message; +- `continue_thread` — continue the current conversation/thread without necessarily replying to one message; +- `new_message` — send as a new outbound message; +- `none` — no threading behavior requested. + +Concrete adapters map the intent: +- email maps `reply_to_origin` to `Re:`, `Message-ID`, `In-Reply-To`, and `References`; +- Telegram maps `reply_to_origin` to provider reply parameters; +- web maps it to conversation/thread identifiers; +- CLI/API may ignore or expose the intent in structured output. + +Configuration must be per concrete channel instance. +Examples: +- Docoved beta email `ask@beta-mail.docoved.pro` replies to the inbound email by default; +- a specific Telegram bot can reply to the source message by default; +- another channel instance can disable reply-to-origin and send standalone messages. + +The framework owns the intent vocabulary. +Product adapters own the transport mapping and persistence lookup needed to find provider message references. + +Threading fallback rules: +- if `reply_to_origin` is requested but no valid provider target exists, the adapter must choose either configured fallback to `continue_thread`/`new_message` or a typed failure; +- fallback must be logged with reason code; +- missing/stale/deleted provider references must not block the core answer unless product config marks reply-to-origin as required; +- incoming reply metadata should be normalized into canonical conversation/message refs before answer generation when the product has conversation persistence. + +Threading config should be part of channel-instance configuration, not a global product constant. + +Minimum config shape: +- default outbound threading mode; +- whether fallback is allowed; +- whether reply-to-origin is required for this channel instance; +- provider-specific options under namespaced adapter config, not framework fields. + +## Outbound delivery intent and outcome + +Outbound delivery is useful, but this protocol should start lean. + +First shared layer: +- `OutboundDeliveryIntent` describes what should be delivered; +- `OutboundDeliveryResult` describes what happened; +- `deliveryId`, `attemptId`, `responseId`, `runId`, `traceId`, `channelRef`, and `transportMessageRef` preserve correlation. + +The first implementation should not introduce framework-owned queues, schedulers, retry stores, or provider senders. + +Product adapters continue to own: +- provider SDK calls; +- retry mechanics; +- idempotency keys; +- provider-specific failures; +- delivery persistence if the product already has it. + +Idempotency rules: +- every delivery intent should carry a stable idempotency key or enough correlation fields for the adapter to derive one; +- retries must not duplicate customer-visible sends unless the provider contract makes that unavoidable and the outcome is logged; +- command results and ordinary answers should share delivery correlation semantics; +- delivery retry ownership must be one layer deep for a given failure class to avoid runtime retry plus adapter retry plus provider retry amplification. + +The shared contract should distinguish at least: +- `delivered`; +- `suppressed`; +- `failed`; +- `partial_failure`; +- `skipped`; +- `simulated`. + +SellerAgent's existing delivery outcome vocabulary is useful migration input, not automatic platform truth. +Extraction is allowed only for provider-neutral concepts used by both Docoved and SellerAgent. + +The first shared result should be summary-level. +Per-step delivery plans remain product-local unless both products prove the same multi-step provider-neutral structure. + +Storage boundary: +- transport-ref lookup, idempotency state, provider delivery records, and effective-config snapshots are product-local persistence concerns; +- this protocol does not introduce framework storage artifacts for those concerns; +- if a product captures a config snapshot during dispatch, it must document the snapshot owner in the product Memory Bank rather than implying a shared platform store. + +## Configuration source of truth and compatibility + +Channel interaction behavior must have one effective configuration path. + +Required effective config inputs: +- product instance; +- workspace or tenant where applicable; +- channel kind; +- concrete channel ref; +- channel transport config summary; +- pipeline binding; +- command policy; +- threading policy; +- delivery policy; +- product capability mapping. + +Compatibility rules: +- existing Docoved/SellerAgent `commandAccessPolicy` fields may be read as legacy inputs during migration; +- `commandAccessPolicy` is migration input only unless a product Memory Bank explicitly declares it the canonical writable authority for that product; +- legacy fields must be mapped to the new effective policy through an explicit compatibility adapter; +- compatibility fallback must be logged; +- no second editable command-policy authority may be introduced without migration plan; +- after adoption, docs must state which field/config object is canonical. + +Config failure rules: +- invalid command policy disables command dispatch for the affected channel instance; +- invalid threading policy falls back only if configured fallback is allowed; +- invalid delivery policy suppresses send only when safe; otherwise it fails loudly with typed diagnostics. +- effective config readback should include enough version/snapshot information for investigation, but that snapshot remains product-local unless a later storage protocol says otherwise. + +## Logging-first diagnostics + +This protocol does not create DB/read-model tables. + +Default diagnostics path: +- structured logs; +- runtime trace refs; +- response/delivery correlation ids; +- product-local artifacts where the product already has governed trace storage. + +Framework-owned tables or read models require a later protocol and a proven use case: +- replaying delivery; +- operator audit with queryable history; +- long-term delivery lifecycle inspection; +- legal/compliance-grade audit; +- shared UI that cannot operate from logs/traces/product-local state. + +Until then: +- logs are for triage and correlation; +- traces/artifacts are for explainability; +- product persistence remains product-owned. + +Required structured events, diagnostic fields, and redaction checklist are maintained in [PRT-043 review details](PRT-043-channel-interaction-runtime-review-details.md). + +Incident-monitoring rule: +- product adapters may capture unexpected exceptions or exhausted retries in product-local tools such as Sentry; +- framework helpers must not depend on a specific incident-monitoring provider; +- incident events must carry safe correlation ids so logs, traces, and product-local monitors can be joined during investigation. + +## Anti-abuse and external-user controls + +Command support for external or unknown users creates an abuse surface. + +Required hooks: +- product-local rate limit decision before dispatch; +- command policy support for denying external unknown and anonymous actors by default; +- bounded error messages that do not reveal private command catalogs; +- structured event when a rate limit or abuse guard blocks execution; +- no provider menu/help projection for unknown users unless product explicitly enables public commands. + +Anti-abuse implementation stays product-owned. +The framework owns hook shape and result vocabulary only if both products need the same contract. + +## UI/Admin stance + +No framework UI/admin surface is part of this protocol. + +The contracts should not block a future UI, but the protocol must not add: +- shared admin screens; +- POM objects; +- framework read-model tables; +- channel command management UI; +- delivery inspection UI. + +If a real operator workflow later requires shared UI, it must open a separate UI protocol with scenario anchors and MBB UI documentation. + +Current scope adds no UI docs, POM objects, screen contracts, or stable `data-testid` requirements. +If UI is later introduced, the owning repo must create a separate UI protocol with screen contracts, POM mapping, stable selectors/test ids, scenario anchors, and explicit accessibility/UX acceptance. + +## Storage and migration stance + +This protocol introduces no DB schema migrations, backup steps, restore procedures, framework queues, framework delivery tables, or shared read models. + +If storage/read-model work later enters scope, it requires a separate storage protocol that: +- cites the persistence interface and store-boundary spec; +- names schema, migration, index, transaction, idempotency, backup, and rollback responsibilities; +- explains beta/prod rollout safety; +- defines read-model ownership and retention; +- updates product and platform Memory Banks before implementation. + +## Product adoption: Docoved + +Docoved adoption should prove: +- Telegram and email command execution use the same command runtime contract; +- command availability respects actor class, channel kind, channel instance config, and product policy; +- command results return canonical response documents; +- email channel can process commands without special command-only plumbing; +- beta email `ask@beta-mail.docoved.pro` answers as `Re:` when configured to reply to origin; +- Telegram replies can be configured to reply to the inbound message; +- hosted beta verification covers both normal answers and command answers. + +Docoved migration details to resolve: +- decide the minimum command set for parity, likely diagnostics/source/help-style commands before mutation commands; +- map existing Telegram `commandAccessPolicy` into effective command availability; +- define how email command input is recognized without intercepting ordinary legal/document questions; +- preserve knowledge-source binding and conversation context before command dispatch; +- ensure command denial for unauthorized email senders and Telegram users is public-safe; +- prove ordinary email questions are classified as `not_a_command` and continue normal answer flow; +- prove repeated webhook/email delivery is idempotent or visibly suppressed; +- prove policy fallback emits diagnostics; +- treat Telegram command menu projection as derived from server policy and verify menu drift does not grant authority; +- record beta proofs for both authorized and unauthorized actors. + +Docoved must keep local: +- grounded-answer semantics; +- knowledge-source binding; +- Docoved command catalog and handlers; +- email and Telegram provider credentials; +- hosted beta runbooks and proofs. + +Docoved Memory Bank must route readers to this protocol for platform interaction contracts and to Docoved specs for product behavior. + +## Product adoption: SellerAgent + +SellerAgent adoption should prove: +- existing Telegram privileged command behavior can map to the shared command runtime contract; +- actor-class policy covers system admin, workspace admin, employee/member, external known user, and external unknown user cases; +- command results can be represented as canonical response documents where the result is user-facing text; +- existing SellerAgent delivery outcome concepts are either product-local or cleanly mapped to shared delivery result vocabulary; +- beta SellerAgent verification still proves privileged command gating and does not regress release-control or diagnostics commands. + +SellerAgent migration details to resolve: +- inventory command families from the Telegram privileged command protocol; +- classify commands as read-only diagnostics, release-control mutation, product workflow mutation, or debug-only; +- adopt read-only diagnostics/readback commands as the minimum first proof slice before touching mutation or release-control commands; +- map existing actor/access resolver output into framework actor classes plus product capabilities; +- preserve server-authoritative checks for release-control commands; +- verify command naming consistency between code and planning prose before publishing product docs; +- keep existing UI/admin surfaces as product-owned surfaces, not platform UI. + +SellerAgent must keep local: +- command catalog and business semantics; +- release-control command handlers; +- commerce/customer/conversation logic; +- existing product UI/admin behavior; +- product-specific delivery persistence and workflows. + +SellerAgent Memory Bank must document the adoption and explain which former Telegram-shaped concepts now map to platform contracts. + +## Package strategy + +Preferred first implementation: +- evolve `@dd-bot-platform/channel-runtime` for interaction-adjacent response, render, threading, and delivery intent contracts; +- implement command-framework code/types in the existing framework command area or a clearly named package only if current package boundaries require it; +- avoid a new package unless import boundaries prove that `channel-runtime` and command-framework contracts must remain separately versioned. + +Hard rule: +- do not duplicate command contracts inside channel-runtime if they already belong to the command framework. + +Acceptable shape: +- command framework owns `CommandEnvelope`, `CommandRegistry`, `CommandDispatcher`, command availability, and command failures; +- channel-runtime owns `CanonicalResponseDocument`, render target vocabulary, and response metadata; +- channel-runtime may own threading intent and delivery intent/result only after the Phase 1 boundary gate confirms they are provider-neutral summary contracts and do not include threading state, provider senders, retries, or delivery orchestration; +- channel-runtime may reference command identifiers and command result documents, but not own command dispatch. + +Semver and release rules: +- adding public exported types requires package version bump and changelog/history note; +- changing existing exported type semantics requires explicit migration note in product adoption docs; +- product repos must pin the released package version, not a sibling-path bridge, unless a documented bridge is approved for local proof only; +- no package release should happen before import-boundary and typecheck proof pass. + +Open package-boundary decision after phase 0: +- if command runtime is still documentation-only in code, materialize it in the command-framework-owned package/module rather than hiding it inside channel-runtime; +- if no command-framework package exists yet, choose between `@dd-bot-platform/core` command exports and a new small package based on dependency direction, not naming taste. + +Pre-code gates: +- choose the command-framework implementation/export location; +- decide whether threading/delivery intent types belong in channel-runtime now or stay product-local until a second proof; +- define the exact Docoved first parity command set; +- define the SellerAgent first read-only/diagnostic adoption subset; +- classify which delivery result fields are shared versus SellerAgent-only; +- define the minimum channel-instance threading config shape. + +Code must not start until these gates are resolved in this protocol or in task packets linked from this protocol. + +## Implementation phases + +Detailed implementation execution rules, subagent task packet format, required context-readiness pass, dependency graph, verification-by-subagent workflow, and local/hosted test lanes are defined in [PRT-043 implementation plan](PRT-043-channel-interaction-runtime-implementation-plan.md). + +### Completed planning phases + +- Phase 0: discovery/protocol hardening completed on 2026-04-26. +- Phase 1: subagent review completed on 2026-04-26; reports live in `.tasks/prt-043-protocol-review-phase-1/`. +- Phase 2: implementation/subagent planning completed on 2026-04-26; task workspace lives in `.tasks/prt-043-channel-interaction-runtime/`. + +## Task graph for implementation planning + +The implementation task graph is maintained in [PRT-043 implementation plan](PRT-043-channel-interaction-runtime-implementation-plan.md), with phase-1 review detail in [PRT-043 review details](PRT-043-channel-interaction-runtime-review-details.md). + +Implementation must begin with the package-boundary decision and must not start DB/read-model, UI/admin, provider-sender extraction, or mutation-command expansion tasks in the first proof slice. + +### Phase 1: platform contracts + +Tasks: +- add or materialize typed command runtime contracts where the existing command framework is currently documentation-only; +- add actor-aware command availability policy types; +- add command input normalization and result/failure types; +- add threading intent types; +- add threading resolution/fallback result types; +- add outbound delivery intent/result types; +- extend canonical response metadata only where necessary for correlation; +- add deterministic tests for actor/channel allow-deny behavior and render/thread/delivery intent shapes. + +Exit criteria: +- platform package typecheck/build passes; +- no product imports enter platform packages; +- tests cover system admin, workspace admin, employee/member, external known user, external unknown user, and denied anonymous scenarios; +- tests cover policy precedence and deny-over-allow behavior; +- tests cover safe command failure result shapes; +- tests cover idempotency/correlation fields on delivery intent/result; +- docs cite the owning specs and this protocol. + +### Phase 2: Docoved adoption + +Tasks: +- map existing Docoved command support to shared command runtime contracts; +- remove Telegram-only command assumptions from paths that should be channel-neutral; +- make email command handling use the same command dispatcher path; +- implement channel-instance threading behavior for email and Telegram; +- render command responses from canonical documents; +- update Docoved Memory Bank and hosted beta scenarios. + +Exit criteria: +- Docoved local checks pass; +- beta Telegram command/runtime proof passes; +- beta email command/runtime proof passes; +- beta email reply proof confirms `Re:` behavior for `ask@beta-mail.docoved.pro`; +- no Docoved product logic moved into `bot-platform`. + +### Phase 3: SellerAgent adoption + +Tasks: +- map SellerAgent command catalogs to shared command runtime contracts; +- preserve existing privileged command gates while replacing Telegram-shaped shared assumptions; +- map user-facing command results to canonical response documents where applicable; +- align delivery result vocabulary without replacing SellerAgent product workflows; +- update SellerAgent Memory Bank and beta verification. + +Exit criteria: +- SellerAgent local checks pass; +- beta privileged command scenarios pass; +- beta delivery/diagnostics behavior does not regress; +- SellerAgent command handlers remain product-owned. + +### Phase 4: closure + +Tasks: +- promote useful lessons/insights into the correct Memory Bank sections; +- close product adoption notes; +- record package versions and deployment evidence; +- leave no uncommitted/unpushed local tails. + +Exit criteria: +- `bot-platform`, `docoved-agent`, and `seller-agent` Memory Banks point to the correct SSoT; +- CI/package checks are green where releases were pushed; +- beta evidence is linked from product repos; +- this protocol is marked `CLOSED` only after both product adoption waves are complete or explicitly split into follow-up protocols. + +## Verification matrix + +Verification is split into framework local/package, Docoved local, Docoved hosted beta, SellerAgent local, and SellerAgent hosted beta lanes. + +Minimum acceptance: +- framework checks cover policy precedence, parse/result/failure envelopes, import boundaries, and package build/typecheck/prepack where applicable; +- Docoved checks cover Telegram/email command parity, ordinary-email-not-command behavior, unauthorized sender/user denial, reply threading, duplicate delivery/idempotency, and beta `ask@beta-mail.docoved.pro` reply behavior; +- SellerAgent checks preserve privileged command gates, menu projection as derived state, release-control safety, and `SCN-053`-anchored Telegram actor verification where applicable; +- hosted checks run only when live lane proof is needed and must include stable alias/readback verification. + +The detailed verification lane checklist and verifier-agent workflow are in [PRT-043 implementation plan](PRT-043-channel-interaction-runtime-implementation-plan.md) and [PRT-043 review details](PRT-043-channel-interaction-runtime-review-details.md). + +## Operations and git-flow + +Implementation must follow repository-local git-flow and deployment rules. + +Before coding: +- inspect current branch and uncommitted changes in each repo; +- do not mix unrelated tails into protocol commits; +- create work branches/worktrees only if the repo runbook requires it. + +During implementation: +- commit documentation, platform contracts, Docoved adoption, and SellerAgent adoption as separate meaningful commits; +- push only when a commit is ready for CI/review/deploy; +- do not trigger hosted builds just to “see what happens”; +- deploy beta only when hosted beta scenarios are ready to run. + +Before closure: +- verify GitHub/CI checks where pushes were made; +- verify Vercel/hosting checks where deployments were made; +- verify stable hosted aliases/readbacks before accepting hosted beta/prod evidence; +- record beta evidence in product Memory Banks; +- ensure no uncommitted or unpushed tails remain. + +## Release, deploy, and rollback sequence + +When package or hosted adoption is part of a PRT-043 wave, use this order: +1. local framework/package checks; +2. package-boundary decision and version bump when public exports change; +3. package `prepack` or pack dry-run; +4. commit, push, and wait for CI/package readiness; +5. publish/release platform package only after readiness is green; +6. update products by pinned released version, then run product-local checks; +7. deploy beta only when hosted scenarios are ready; +8. verify hosted status, stable alias/readback, and live proof artifacts; +9. promote to main/prod only after product Memory Bank evidence is updated. + +Rollback rule: +- consumer rollback starts by reverting the pinned package version or hosted alias/config assignment; +- do not rollback by copying source code between repos; +- if a hosted provider send/config change caused customer-visible effects, record the rollback lesson in the owning product runbook and Memory Bank. + +## Lessons learned and insights + +During implementation, record durable lessons and insights when: +- documentation is missing, misleading, or contradicted by code; +- product behavior reveals a platform contract gap; +- a provider constraint affects the generic model; +- a test catches a scenario not documented in MBB; +- debugging requires non-obvious knowledge worth preserving. +- release, deployment, package publish, rollback, or hosted-alias behavior reveals a runbook gap. + +Use `.tasks/prt-043-channel-interaction-runtime/` for temporary task artifacts. + +File naming: +- `NNN-lessons-learned.md`; +- `NNN-insights.md`; +- task reports named by task id. + +End-of-stage rule: +- promote accepted lessons into the owning Memory Bank section; +- release/deploy/rollback lessons must be promoted into the owning runbook or operations spec; +- do not leave important knowledge only in `.tasks/`. + +## Memory Bank documentation rules + +This protocol follows the MBB Single Source of Truth model. + +Routing: +- stable command envelope, parser, registry, dispatch, availability, and failure contracts belong in `spec/runtime/command-framework-contract.md`; +- stable canonical response, visibility, rendering vocabulary, and any accepted thread/delivery intent vocabulary belong in `spec/runtime/channel-runtime-contract.md`; +- sequencing, task graph, review evidence, and closure criteria belong in this protocol; +- Docoved adoption details belong in Docoved Memory Bank; +- SellerAgent adoption details belong in SellerAgent Memory Bank; +- `.tasks/prt-043-protocol-review-phase-1/` reports are review evidence, not canonical contract truth. + +Documentation updates required by implementation: +- update runtime specs when a candidate contract becomes stable; +- update `plans/index.md` and `plans/protocols/index.md` when protocol phase/status changes; +- update product indexes and scenario docs when Docoved or SellerAgent adoption starts; +- document the canonical writable command-policy authority in each product repo before deprecating legacy fields. + +## Non-goals + +- No shared UI/admin implementation. +- No framework-owned DB/read-model tables. +- No DB migrations, backups, restore workflows, framework queues, or framework delivery-status storage in this protocol. +- No product command catalog migration into `bot-platform`. +- No provider SDK senders in platform packages. +- No universal renderer that hides provider-specific constraints. +- No Telegram-shaped abstraction presented as channel-neutral. +- No weakening of server-side authorization in favor of command menu visibility. + +## Pre-code open gates + +1. Should actor-class vocabulary live in command-framework package/types or in shared control-plane vocabulary? +2. Does `@dd-bot-platform/channel-runtime` remain the only published package touched, or should command-framework get its own package surface? +3. Which Docoved commands are required for first email/Telegram parity proof? +4. Which SellerAgent command subset is the minimum beta proof: diagnostics/readback only, or release-control too? +5. Which delivery outcome fields are genuinely shared versus SellerAgent-specific? +6. What exact channel-instance config shape should represent default threading behavior? + +These gates remain open after phase 1 review. +They must be resolved before implementation code starts, either by updating this protocol or by linking approved task packets from `.tasks/prt-043-channel-interaction-runtime/`. diff --git a/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md b/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md new file mode 100644 index 0000000..f348c8b --- /dev/null +++ b/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md @@ -0,0 +1,239 @@ +--- +file: .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md +description: Implementation plan companion for PRT-043, covering subagent task packets, dependency graph, verification-by-subagent, local/hosted checks, and documentation closure. +purpose: Use before implementing PRT-043 so work is sliced into bounded subagent tasks with clear context, ownership, verification, and Memory Bank evidence rules. +version: 0.2.0 +date: 2026-04-26 +status: DRAFT +tags: [protocol-detail, implementation-plan, subagents, channel-runtime, command-runtime] +parent: .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md +related_files: + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md + - .memory-bank/spec/runtime/command-framework-contract.md + - .memory-bank/spec/runtime/channel-runtime-contract.md + - .memory-bank/spec/project/feature-area-boundaries.md + - .memory-bank/spec/operations/observability-and-incident-diagnostics.md + - .memory-bank/spec/operations/git-flow.md + - .memory-bank/spec/operations/hosted-beta-acceptance-contract.md + - .memory-bank/mbb/templates/feature.md + - .memory-bank/mbb/templates/protocol.md + - .memory-bank/mbb/delivery-docs-guide.md + - .memory-bank/mbb/scenario-docs-guide.md + - .tasks/prt-043-channel-interaction-runtime/000-index.md + - .tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md +history: + - version: 0.2.0 + date: 2026-04-26 + changes: Recorded execution progress for platform code tasks T-043-02/T-043-03, verifier outcomes, and remaining product adoption gates. + - version: 0.1.0 + date: 2026-04-26 + changes: Added phase-2 implementation planning for subagent-based execution, task packet format, dependency graph, verifier workflow, checks, hosted beta gates, and documentation closure. +--- + +# PRT-043 Channel Interaction Runtime Implementation Plan + +## Phase state + +стадия проработки протокола: фаза 2 выполнена + +This companion turns PRT-043 from architectural protocol into an executable implementation plan. +It does not authorize coding by itself: pre-code gates in PRT-043 still must be resolved before implementation tasks start. + +## Subagent operating model + +Workspace: +- `.tasks/prt-043-channel-interaction-runtime/` + +Required files already created: +- `000-index.md` — workspace navigation and rules; +- `001-task-packet-template.md` — template for implementation and verification task packets. + +Rules: +- every subagent task starts from a dedicated task packet file in the workspace; +- every subagent writes a report file in the same workspace; +- task packets must be similar in discipline to MBB feature/protocol templates: goal, context, grounding, scope, non-goals, risks, acceptance, checks, and report format; +- every task packet must require an explicit context-readiness pass before edits: docs read, searches run, files inspected, existing seams/helpers/tests found, assumptions listed, and unresolved gates reported; +- a subagent must not edit code or canonical docs until it has formed and recorded task context in its report or notes; +- orchestrator must close agents that are no longer needed before launching new work; +- new work should prefer a new subagent rather than reusing stale context; +- full context fork must not be combined with model override; +- reports are evidence, not canonical Memory Bank truth; +- durable lessons/insights must be promoted to the owning Memory Bank before closure. + +## Task packet requirements + +Each task packet must include: +- task id and title; +- suggested agent type/model, for example `gpt-5.5` for architecture/package-boundary tasks, `gpt-5.3-codex` for code-heavy implementation, `gpt-5.4-mini` for bounded inventory/verification; +- read/write scope, with disjoint write ownership when tasks run in parallel; +- context docs to read before work; +- concrete code searches to run before editing; +- a `Context readiness checklist` requiring the subagent to verify repository status, gather missing context, inspect relevant seams/tests/helpers, and decide whether the task is ready or blocked; +- implementation steps and non-goals; +- rationale for why the task is sliced this way; +- relevant coding/documentation standards; +- risks, tricky points, and rollback/abort conditions; +- completion criteria; +- required local/hosted checks; +- exact report path and report format. + +Task packets must cite relevant standards: +- `spec/project/feature-area-boundaries.md` for framework/product ownership; +- `spec/runtime/command-framework-contract.md` for command contract ownership; +- `spec/runtime/channel-runtime-contract.md` for canonical response/render ownership; +- `spec/operations/observability-and-incident-diagnostics.md` for logs/errors/redaction; +- `spec/operations/git-flow.md` and deployment docs for commit/push/deploy flow; +- `mbb/delivery-docs-guide.md`, `mbb/scenario-docs-guide.md`, and relevant templates for documentation discipline. + +Context readiness is part of task completion. +If a subagent discovers missing docs, unclear ownership, absent tests/helpers, or a pre-code gate that affects its task, it must stop and report the blocker instead of guessing. + +## Implementation dependency graph + +Pre-code gates: +- `G-043-01`: command-framework implementation/export location decided; +- `G-043-02`: threading/delivery intent scope decided: channel-runtime now or product-local until second proof; +- `G-043-03`: Docoved first parity command set defined; +- `G-043-04`: SellerAgent first read-only/diagnostic subset defined; +- `G-043-05`: shared vs SellerAgent-only delivery fields classified; +- `G-043-06`: minimum channel-instance threading config shape defined. + +Implementation tasks: +- `T-043-01`: platform package-boundary decision packet; depends on no other task; blocks code tasks. +- `T-043-02`: command-framework typed contracts and tests; depends on `T-043-01`. +- `T-043-03`: channel-runtime candidate intent/result contracts and tests; depends on `T-043-01` and `G-043-02`. +- `T-043-04`: platform observability/error/idempotency helper tests; depends on `T-043-02` and/or `T-043-03` depending on final package split. +- `T-043-05`: Docoved command/email/threading inventory; can run in parallel after `G-043-03` is drafted. +- `T-043-06`: SellerAgent command/delivery inventory; can run in parallel after `G-043-04` and `G-043-05` are drafted. +- `T-043-07`: Docoved adoption implementation; depends on platform package release or approved prerelease bridge plus `T-043-05`. +- `T-043-08`: SellerAgent adoption implementation; depends on platform package release or approved prerelease bridge plus `T-043-06`. +- `T-043-09`: cross-repo docs, scenario, release, and closure evidence; depends on at least one product adoption and all touched package checks. + +Execution status: +- `T-043-01`: completed; package-boundary decision accepted. +- `T-043-02`: completed; `packages/core/src/command-framework` landed, missing command policy was hardened to default deny, and verifier accepted after orchestrator hardening. +- `T-043-03`: completed after orchestrator fix; `packages/channel-runtime/src/threading.ts` and `packages/channel-runtime/src/delivery.ts` landed, delivery intent is reference-only, and verifier accepted after fix. +- `T-043-04`: not opened in this slice; no extra observability helper was needed beyond typed result diagnostics and existing package tests. +- `T-043-05` / `T-043-06`: completed as inventory reports; product adoption remains gated by first parity subset decisions. +- `T-043-07` / `T-043-08` / `T-043-09`: not executed in this platform slice. + +Parallelism: +- inventories for Docoved and SellerAgent can run in parallel; +- command-framework contracts and channel-runtime intent/result contracts can run in parallel only if write scopes are disjoint; +- product adoption tasks should wait for the platform package version unless a documented prerelease bridge is approved; +- verifier tasks can run in parallel with non-overlapping final polish once implementation reports exist. + +Do not create tasks for: +- framework DB/read-model tables; +- UI/admin screens; +- provider SDK sender extraction; +- mutation command expansion before read-only/diagnostic proof is stable. + +## Verification by subagent + +Every implementation task that changes code or canonical docs needs verification. + +Verifier task packet input: +- original task packet; +- subagent implementation report; +- actual changed files/diff; +- relevant tests/check outputs; +- relevant Memory Bank docs. + +Verifier responsibilities: +- check the implementation against the original task scope and non-goals; +- inspect actual code/docs, not only the report; +- confirm no product logic leaked into platform packages; +- confirm no framework DB/UI/provider sender scope was introduced; +- confirm checks/evidence match acceptance criteria; +- list defects as required fixes or accepted follow-ups; +- write a verifier report to `.tasks/prt-043-channel-interaction-runtime/T-043-XX-verification.md`. + +Orchestrator responsibilities: +- read verifier report and implementation report; +- make final acceptance decision; +- patch or assign follow-up for any accepted defect; +- close subagents that are no longer needed. + +## Testing and scenario plan + +Framework local/package lane: +- package typecheck/build for touched packages; +- package `prepack` or pack dry-run when public package surface changes; +- tests for policy precedence, deny-over-allow, parse/result/failure envelopes, import boundaries, and redaction-safe observability helpers when added; +- tests for threading/delivery intent only if those types are added to the platform package. + +Docoved local lane: +- Telegram/email command parser and dispatcher behavior; +- ordinary email question classified as `not_a_command`; +- unauthorized email sender and Telegram user denied safely; +- reply/threading fallback and required-target behavior; +- duplicate webhook/email handling idempotent or visibly suppressed; +- canonical response rendering parity across Telegram/email. + +Docoved hosted beta lane: +- normal Telegram answer still works; +- normal email answer still works; +- authorized and unauthorized command behavior works in Telegram/email; +- beta email `ask@beta-mail.docoved.pro` replies as `Re:`; +- stable beta alias/readback confirms deployed target; +- evidence maps to Docoved scenario anchors such as `SCN-201`, `SCN-202`, `SCN-204`, and `SCN-211` where present. + +SellerAgent local lane: +- privileged command gates preserve actor/capability distinctions; +- read-only/diagnostic subset adopted before mutation commands; +- Telegram menu/help projection remains derived, not authoritative; +- release-control mutation commands keep existing product permission gates; +- delivery outcome mapping does not replace product workflows. + +SellerAgent hosted beta lane: +- `SCN-053`-anchored Telegram observed-user/employee verification remains valid where applicable; +- privileged command denial for external/unknown users still works; +- release readback/control commands respect actor policy if included in the adoption slice; +- hosted evidence includes stable alias/readback and traceable logs. + +Do not run hosted deploys just to exercise CI. Hosted deploy happens only when hosted beta scenarios are ready. + +Current platform slice evidence: +- `pnpm --filter @dd-bot-platform/core typecheck`; +- `pnpm --filter @dd-bot-platform/channel-runtime typecheck`; +- `node --test packages/core/dist/command-framework.spec.js packages/channel-runtime/dist/channel-runtime.spec.js`; +- 18 Node tests passed after the command default-deny hardening and post-verification delivery-intent fix. + +## Documentation closure + +Before closing any stage: +- update platform runtime specs if a candidate contract becomes stable; +- update product Memory Banks for Docoved/SellerAgent adoption details; +- update scenario docs and verification matrices touched by the adoption; +- promote durable lessons/insights from `.tasks/` into owning Memory Bank sections; +- record package versions, commit ids, CI statuses, deployment URLs/aliases, and hosted proof artifacts when relevant; +- leave no uncommitted or unpushed local tails. + +## Report expectations + +Implementation subagent report: +- summary; +- context readiness: docs read, searches run, files inspected, seams/helpers/tests found, assumptions/unknowns; +- files changed; +- decisions/deviations; +- checks run and results; +- risks/follow-ups; +- lessons/insights candidates. + +Verifier subagent report: +- task verdict: accepted / needs fixes / blocked; +- scope compliance; +- code/doc findings; +- checks/evidence review; +- required fixes; +- optional follow-ups. + +Orchestrator closeout report: +- tasks completed; +- subagent reports accepted; +- fixes applied; +- checks/evidence; +- docs promoted; +- open pre-code gates or follow-ups. diff --git a/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md b/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md new file mode 100644 index 0000000..08b5dfc --- /dev/null +++ b/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md @@ -0,0 +1,185 @@ +--- +file: .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md +description: Companion details for PRT-043 phase-1 review: boundary step contracts, entity ownership matrix, observability event checklist, and verification lanes. +purpose: Keep PRT-043 lean while preserving phase-1 review details needed before implementation task packets are opened. +version: 0.1.0 +date: 2026-04-26 +status: DRAFT +tags: [protocol-detail, channel-runtime, command-runtime, review, verification] +parent: .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md +related_files: + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md + - .memory-bank/spec/runtime/command-framework-contract.md + - .memory-bank/spec/runtime/channel-runtime-contract.md + - .tasks/prt-043-protocol-review-phase-1/001-orchestrator-consolidated-review.md +history: + - version: 0.1.0 + date: 2026-04-26 + changes: Extracted detailed phase-1 review tables from PRT-043 to keep the main protocol below the MBB decomposition threshold. +--- + +# PRT-043 Channel Interaction Runtime Review Details + +This companion file is not the canonical protocol. + +Canonical sequencing and scope remain in: +- [PRT-043 Channel Interaction Runtime](PRT-043-channel-interaction-runtime-command-render-thread-delivery.md) + +## Boundary step contracts + +| Step | Input | Output | Owner | Failure/result | Required event | Side effects | +| --- | --- | --- | --- | --- | --- | --- | +| Receive inbound event | Provider webhook/API/CLI input | Normalized inbound context | Product adapter | provider validation failure | `channel_event_received` / `channel_event_failed` | Provider read only | +| Extract command candidate | Inbound context and channel config | Raw command candidate or ordinary message | Product adapter | `not_a_command` | `command_input_received` | None | +| Normalize command | Raw command candidate | `CommandEnvelope` or parse result | Command framework | `not_a_command`, `parse_error`, `unknown_command` | `command_parse_completed` | None | +| Resolve actor and policy | Envelope, actor context, effective config | `CommandAvailabilityDecision` | Product auth plus command framework policy contract | `access_denied`, `unsupported_channel`, `rate_limited` | `command_policy_evaluated` | Product-local auth/rate-limit read | +| Dispatch handler | Valid envelope and policy decision | `CommandExecutionResult` | Product handler through command framework dispatch path | `validation_error`, `dispatch_error`, `success` | `command_dispatch_started` / `command_dispatch_completed` / `command_dispatch_failed` | Product-owned side effects only | +| Build canonical response | Product result or safe failure | `CanonicalResponseDocument` | Product mapper using channel-runtime document contract | safe public/operator/debug document | command dispatch/render events | None unless product records artifacts | +| Render for channel | Canonical document and render target | Provider payload draft | Product adapter, pure helpers where shared | render failure or degraded render | `channel_render_completed` / `channel_render_failed` | None | +| Resolve threading | `ThreadingIntent`, inbound refs, product lookup | `ThreadingResolution` | Product adapter | typed fallback or failure | `threading_intent_resolved` / `threading_intent_failed` | Product-local lookup | +| Deliver outbound | Payload draft, threading resolution, idempotency key | `OutboundDeliveryResult` summary | Product adapter/provider | delivered, suppressed, failed, partial_failure, skipped, simulated | `outbound_delivery_started` / `outbound_delivery_completed` / `outbound_delivery_failed` | Provider send | + +Rules: +- `not_a_command` returns to ordinary product answer flow, not command dispatch. +- User-facing failures become safe `CanonicalResponseDocument` only when feedback is required. +- `ThreadingIntent` must be resolved before final provider send. +- `OutboundDeliveryIntent` must carry or derive an idempotency key before any transport call. +- Product adapters may log provider-specific details only after applying product redaction policy. + +## Entity ownership matrix + +| Entity | Owning feature area | Stable spec owner | Implementation package/module candidate | Product-owned inputs | Adapter-owned inputs | +| --- | --- | --- | --- | --- | --- | +| `CommandInvocationSource` | `command-framework` | `command-framework-contract.md` | command-framework-owned module, not hidden in channel-runtime | workspace/product/channel refs, actor lookup refs | provider message refs, request refs | +| `CommandActorContext` | `command-framework` with auth/control-plane vocabulary reuse | `command-framework-contract.md` and control-plane vocabulary | command-framework-owned module | memberships, roles, product capability tags | transport identity evidence | +| `CommandAvailabilityPolicy` | `command-framework` | `command-framework-contract.md` | command-framework-owned module | product defaults, command-specific rules | channel-kind/instance config input | +| `CommandAvailabilityDecision` | `command-framework` | `command-framework-contract.md` | command-framework-owned module | product capability mapping | channel capability facts | +| `CommandExecutionResult` | `command-framework` result bridge | `command-framework-contract.md`; success payload uses `channel-runtime-contract.md` | command-framework-owned type referencing canonical response types | handler result and safe failures | none | +| `CanonicalResponseDocument` | `channel-runtime` | `channel-runtime-contract.md` | `@dd-bot-platform/channel-runtime` | product answer/command result mapping | render target only | +| `ThreadingIntent` / `ThreadingResolution` | candidate `channel-runtime` extension | promote to `channel-runtime-contract.md` only after Phase 1 boundary gate | channel-runtime-adjacent type if provider-neutral | channel-instance threading policy, product conversation lookup | provider reply/header refs | +| `OutboundDeliveryIntent` / `OutboundDeliveryResult` | candidate `channel-runtime` extension | promote to `channel-runtime-contract.md` only after Phase 1 boundary gate | channel-runtime-adjacent type if summary-only/provider-neutral | delivery policy, idempotency/correlation refs | provider send outcome | + +Reuse rule: +- workspace, product, channel, run, trace, capability, and observability refs must reuse existing `core` / `api-contract` / control-plane vocabulary where it exists. +- New public types are allowed only for missing provider-neutral concepts proven by Docoved and SellerAgent needs. +- No command-framework public type may be newly owned by `@dd-bot-platform/channel-runtime`; channel-runtime may reference or re-export only when dependency direction is documented. + +## Observability checklist + +Required structured events: +- `command_input_received` +- `command_parse_completed` +- `command_policy_evaluated` +- `command_dispatch_started` +- `command_dispatch_completed` +- `command_dispatch_failed` +- `channel_render_completed` +- `channel_render_failed` +- `threading_intent_resolved` +- `threading_intent_failed` +- `outbound_delivery_started` +- `outbound_delivery_completed` +- `outbound_delivery_failed` +- `compat_fallback_used` +- `rate_limit_triggered` + +Required diagnostic fields where applicable: +- `request_id` +- `correlation_id` +- `workspace_ref` +- `product_instance_ref` +- `channel_ref` +- `channel_kind` +- `actor_class` +- `principal_ref` when safe and available +- `command_key` when safe to expose +- `command_result_kind` +- `response_id` +- `run_id` +- `trace_id` +- `delivery_id` +- `attempt_id` +- `transport_message_ref` +- bounded reason code + +Redaction rules: +- do not log full command arguments by default; +- do not log full email bodies or Telegram messages; +- do not log provider tokens, headers, cookies, or secret-bearing URLs; +- do not log full canonical response bodies; +- log lengths/counts/hashes only when needed for triage. + +## Verification lanes + +Framework local/package checks: +- typecheck/build for touched packages; +- package `prepack` or pack dry-run for publishable packages; +- unit tests for command availability policy; +- unit tests for policy precedence and fallback diagnostics; +- unit tests for command parse/result/failure envelopes; +- unit tests for `not_a_command`, `access_denied`, `rate_limited`, and `unsupported_channel` result kinds; +- unit tests for threading intent and delivery result serialization if those types are added; +- unit tests for redaction-safe observability event construction if helper code is added; +- import-boundary proof: no product imports in platform packages; +- docs/index validation by review. + +Docoved local checks: +- command parser/dispatcher tests for Telegram and email inputs; +- tests proving ordinary email questions are not misclassified as commands; +- unauthorized actor tests for email sender and Telegram user; +- repeated webhook/email duplicate tests proving idempotency or visible suppression; +- policy fallback diagnostics tests; +- render tests proving identical canonical command result semantics across Telegram/email; +- email threading tests for `Re:` / `Message-ID` / `In-Reply-To` / `References`; +- Telegram reply parameter tests where feasible. + +Docoved hosted beta checks: +- normal Telegram answer still works; +- normal email answer still works; +- Telegram command answer works for authorized actor and denies unauthorized actor; +- email command answer works for authorized actor and denies unauthorized actor; +- beta email answer is sent as reply from `ask@beta-mail.docoved.pro`; +- ordinary beta email question is not misclassified as a command; +- hosted checks route to Docoved scenario anchors such as `SCN-201`, `SCN-202`, `SCN-204`, and command-policy/projection anchor `SCN-211` where those docs are present; +- stable beta alias/readback verifies the deployed target before hosted proof is accepted; +- structured logs contain correlation ids and no secrets/full raw payloads. + +SellerAgent local checks: +- privileged command gates preserve system-admin/workspace-admin/member/external distinctions; +- release-control mutation commands remain server-authoritative and require the existing product permission gate; +- Telegram menu/help projection remains derived from server policy; +- menu projection drift cannot grant command authority; +- delivery outcome mapping tests preserve existing semantics; +- no regression in release-control command handlers. + +SellerAgent hosted beta checks: +- existing Telegram privileged command scenarios pass; +- route hosted proof to `SCN-053` for Telegram observed-user/employee verification and privileged-command safety where applicable; +- release readback/control commands respect actor policy; +- external/unknown users cannot access privileged commands; +- delivery diagnostics remain traceable. + +## Implementation task graph + +Dependency graph: +- `T-043-01 platform package boundary decision` blocks all code tasks. +- `T-043-02 command contract types` depends on `T-043-01`. +- `T-043-03 channel intent/result types` depends on `T-043-01`. +- `T-043-04 policy resolution tests` depends on `T-043-02`. +- `T-043-05 render/thread/delivery tests` depends on `T-043-03`. +- `T-043-06 Docoved command inventory` can run in parallel after protocol approval. +- `T-043-07 SellerAgent command inventory` can run in parallel after protocol approval. +- `T-043-08 Docoved adoption` depends on `T-043-02`, `T-043-03`, `T-043-04`, `T-043-05`, and `T-043-06`. +- `T-043-09 SellerAgent adoption` depends on `T-043-02`, `T-043-03`, `T-043-04`, `T-043-05`, and `T-043-07`. +- `T-043-10 cross-repo docs and release` depends on platform contracts and at least one product adoption. + +Parallel opportunities: +- Docoved and SellerAgent inventories can run in parallel. +- Command contract types and channel intent/result types can run in parallel only if write scopes are separated. +- Product adoption waves should not run in parallel until the platform package version is fixed, unless each product pins the same local prerelease explicitly. + +Do not start: +- DB/read-model task. +- UI/admin task. +- Provider sender extraction. +- Mutation-command expansion before read-only/diagnostic command proof is stable. diff --git a/.memory-bank/plans/protocols/index.md b/.memory-bank/plans/protocols/index.md index 613df27..95e04b0 100644 --- a/.memory-bank/plans/protocols/index.md +++ b/.memory-bank/plans/protocols/index.md @@ -2,12 +2,27 @@ file: .memory-bank/plans/protocols/index.md description: 'Framework protocol hub for bot-platform.' purpose: Hold cross-epic migration, extraction, and hardening protocols for the framework repo. -version: 0.13.0 -date: 2026-04-25 +version: 0.18.0 +date: 2026-04-26 status: ACTIVE tags: [protocols, bot-platform, planning] parent: .memory-bank/plans/index.md history: + - version: 0.18.0 + date: 2026-04-26 + changes: Recorded PRT-043 platform implementation progress for core command-framework contracts and channel-runtime threading/delivery summary contracts. + - version: 0.17.0 + date: 2026-04-26 + changes: Added PRT-043 phase-2 implementation companion for subagent task packets, dependency graph, verification workflow, and local/hosted test lanes. + - version: 0.16.0 + date: 2026-04-26 + changes: Marked PRT-043 phase-1 protocol review complete after subagent review reports and documentation hardening for ownership, boundary contracts, MBB routing, verification, release/rollback, and UI/DB scope. + - version: 0.15.0 + date: 2026-04-26 + changes: Marked PRT-043 phase-0 protocol elaboration complete after hardening policy precedence, command normalization, safe failures, configuration compatibility, idempotency, anti-abuse, observability, and implementation task graph. + - version: 0.14.0 + date: 2026-04-26 + changes: Added draft PRT-043 for channel interaction runtime covering actor-aware commands, canonical rendering, threading intent, outbound delivery intent, logging-first diagnostics, and Docoved/SellerAgent adoption. - version: 0.13.0 date: 2026-04-25 changes: Marked PRT-042 closed after the first-wave channel-runtime package, publish-readiness proof, Docoved mapping proof, SellerAgent readiness review, and Memory Bank lesson promotion landed. @@ -61,6 +76,9 @@ Protocol anchors: - `PRT-040-governed-content-source-processing-and-workflow-backed-import-substrate.md` - `PRT-041-cross-repo-contract-dependency-boundary-realignment.md` - `PRT-042-channel-runtime-canonical-document-command-and-rendering.md` +- `PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `PRT-043-channel-interaction-runtime-implementation-plan.md` +- `PRT-043-channel-interaction-runtime-review-details.md` Follow-up protocol families will likely include: - package publication and release; @@ -72,4 +90,5 @@ Current rule: - `PRT-039` and `PRT-040` are closed child protocols for the wave-1 shared control-plane and governed-content/import substrata. - `PRT-041` is the closed dependency-boundary cleanup protocol after the handoff; it removed Docoved accidental dependencies on SellerAgent package namespaces and classified retained future extraction questions. - `PRT-042` is the closed first-wave shared channel-runtime protocol. It landed the `@dd-bot-platform/channel-runtime` package, local publish-readiness proof, Docoved mapping proof, SellerAgent readiness review, and Memory Bank lesson promotion. Command/delivery orchestration remains deferred until a later protocol opens it. +- `PRT-043` is the draft follow-up protocol for channel interaction runtime. Phase-2 implementation planning is complete and the first platform code slice has landed: typed command-framework contracts in `@dd-bot-platform/core` plus provider-neutral threading/delivery summary contracts in `@dd-bot-platform/channel-runtime`. Product adoption, hosted beta scenarios, and any package release/publish flow remain gated follow-up work. Subagent execution rules live in `PRT-043-channel-interaction-runtime-implementation-plan.md`; detailed phase-1 tables live in `PRT-043-channel-interaction-runtime-review-details.md`. - future SellerAgent, Docoved, or shared-substrate expansion outside channel-runtime should open a new protocol rather than extending the closed `PRT-038` or `PRT-041` packets. diff --git a/.memory-bank/plans/verification-matrix.md b/.memory-bank/plans/verification-matrix.md index 8642df7..6880efa 100644 --- a/.memory-bank/plans/verification-matrix.md +++ b/.memory-bank/plans/verification-matrix.md @@ -2,12 +2,15 @@ file: .memory-bank/plans/verification-matrix.md description: 'Framework verification matrix for bot-platform.' purpose: Track the relationship between framework feature groups, repo-local contract anchors, extracted packages, and framework verification coverage. -version: 0.14.0 +version: 0.15.0 date: 2026-04-24 status: ACTIVE tags: [verification, matrix, scenarios, bot-platform] parent: .memory-bank/plans/index.md history: + - version: 0.15.0 + date: 2026-04-26 + changes: Updated runtime and command-framework rows after PRT-043 landed the first typed command-framework package surface in `@dd-bot-platform/core`. - version: 0.14.0 date: 2026-04-24 changes: Finalized convergence verification rows after SellerAgent `PRT-008` closed: the shared control-plane and governed-content/import substrates now record linked downstream owner-side proof and wave-1 closure rather than pending product adoption. @@ -67,12 +70,12 @@ Canonical planning sources: | --- | --- | --- | --- | --- | | `client-contracts` | [SCN-001](../scenarios/SCN-001-typed-sdk-parity.md)
`spec/client-api/index.md`, `spec/client-api/api-namespace-registry.md`, `spec/client-api/typed-client-api-and-sdk.md` | `packages/api-contract` (`@dd-bot-platform/api-contract@0.2.0`) | `scenarios/contracts/index.md` + [Scenario matrix](../scenarios/scenario-matrix.md) | contract docs landed; first flat framework scenario doc is now landed | | `scenario-system` | `spec/scenarios/index.md`, `spec/scenarios/scenario-system-and-evidence.md`, `spec/scenarios/hosted-beta-execution-model.md`, `spec/runtime/scenario-system-framework-contract.md` | `packages/scenario-system` (`@dd-bot-platform/scenario-system@0.2.0`) | `scenarios/hosted/index.md` + [Scenario matrix](../scenarios/scenario-matrix.md) | core contracts landed; hosted layering is specified; repo-local hosted/auth workflow anchors now exist, while deeper scenario-system coverage remains later-wave | -| `runtime-kernel` | [SCN-168](../scenarios/SCN-168-openai-runtime-provider-registration-and-readiness-projection.md)
[SCN-170](../scenarios/SCN-170-cross-provider-fail-fast-on-schema-or-prompt-error.md)
[SCN-175](../scenarios/SCN-175-explicit-model-policy-and-config-resolution-diagnostics-without-silent-fallback.md)
`spec/runtime/index.md`, `spec/runtime/agent-execution-kernel.md`, `spec/runtime/pipeline-registry-and-binding-contract.md`, `spec/runtime/decision-explanation-envelope.md`, `spec/runtime/execution-traces-and-token-accounting.md`, `spec/runtime/trace-artifact-governance.md` | `packages/core` (`@dd-bot-platform/core`, repo-local execution-kernel plus runtime-helper slices: `execution-result`, `provider-result`, `pipeline-registry`, `provider-stage`) plus earlier `api-contract`/`scenario-system` bridge packages | [SCN-168](../scenarios/SCN-168-openai-runtime-provider-registration-and-readiness-projection.md) + [SCN-170](../scenarios/SCN-170-cross-provider-fail-fast-on-schema-or-prompt-error.md) + [SCN-175](../scenarios/SCN-175-explicit-model-policy-and-config-resolution-diagnostics-without-silent-fallback.md) | contract docs landed; provider-registration/readiness and cross-provider fail-fast anchors are now repo-local; the broader generic runtime-helper pack is framework-owned in `packages/core`, `core` is now release-allowlisted, and the next proof should focus on narrow mixed consumer adoption instead of broad runtime replacement | +| `runtime-kernel` | [SCN-168](../scenarios/SCN-168-openai-runtime-provider-registration-and-readiness-projection.md)
[SCN-170](../scenarios/SCN-170-cross-provider-fail-fast-on-schema-or-prompt-error.md)
[SCN-175](../scenarios/SCN-175-explicit-model-policy-and-config-resolution-diagnostics-without-silent-fallback.md)
`spec/runtime/index.md`, `spec/runtime/agent-execution-kernel.md`, `spec/runtime/pipeline-registry-and-binding-contract.md`, `spec/runtime/decision-explanation-envelope.md`, `spec/runtime/execution-traces-and-token-accounting.md`, `spec/runtime/trace-artifact-governance.md` | `packages/core` (`@dd-bot-platform/core`, repo-local execution-kernel plus runtime-helper slices: `execution-result`, `provider-result`, `pipeline-registry`, `provider-stage`, and PRT-043 `command-framework`) plus earlier `api-contract`/`scenario-system` bridge packages | [SCN-168](../scenarios/SCN-168-openai-runtime-provider-registration-and-readiness-projection.md) + [SCN-170](../scenarios/SCN-170-cross-provider-fail-fast-on-schema-or-prompt-error.md) + [SCN-175](../scenarios/SCN-175-explicit-model-policy-and-config-resolution-diagnostics-without-silent-fallback.md) | contract docs landed; provider-registration/readiness and cross-provider fail-fast anchors are now repo-local; the broader generic runtime-helper pack is framework-owned in `packages/core`, `core` is now release-allowlisted, and PRT-043 adds the first typed command-framework surface pending product adoption | | `auth-framework` | [SCN-012](../scenarios/SCN-012-scenario-auth-bootstrap.md)
`spec/security/index.md`, `spec/security/auth-core.md`, `spec/security/auth-and-access.md` | none extracted | [SCN-012](../scenarios/SCN-012-scenario-auth-bootstrap.md) + `scenarios/contracts/index.md` | baseline contracts landed; flat auth-bootstrap scenario is now repo-local; product DB/membership overlays remain product-owned | | `shared-control-plane-substrate` | [SCN-176](../scenarios/SCN-176-shared-control-plane-channel-binding-and-readback-contract.md)
[SCN-178](../scenarios/SCN-178-shared-control-plane-execution-run-and-trace-artifact-readback-contract.md)
[SCN-221](../scenarios/SCN-221-shared-control-plane-observability-event-evidence-contract.md)
`plans/protocols/PRT-039-shared-control-plane-access-channel-and-management-substrate.md`, `spec/operations/control-plane-configuration-and-observability-surfaces.md`, `spec/security/auth-and-access.md`, `spec/project/feature-area-boundaries.md` | none extracted | [SCN-176](../scenarios/SCN-176-shared-control-plane-channel-binding-and-readback-contract.md) + [SCN-178](../scenarios/SCN-178-shared-control-plane-execution-run-and-trace-artifact-readback-contract.md) + [SCN-221](../scenarios/SCN-221-shared-control-plane-observability-event-evidence-contract.md) + [SCN-012](../scenarios/SCN-012-scenario-auth-bootstrap.md) + [Scenario matrix](../scenarios/scenario-matrix.md) | shared control-plane implementation slices and runnable local framework verifier anchors for channel-binding (`SCN-176`), bounded diagnostics/readback (`SCN-178`), and observability-event evidence (`SCN-221`) are landed in `bot-platform`; SellerAgent `PRT-008` links owner-side adoption/no-regression proof upstream, so the wave-1 handoff is closed and future control-plane expansion belongs to later protocols | | `persistence-interfaces` | `spec/runtime/persistence-interface-and-store-boundary.md` | none extracted | [Scenario matrix](../scenarios/scenario-matrix.md) | contract boundary landed; runnable scenarios are still gated by split/extraction work | | `workflow-framework` | [SCN-116](../scenarios/SCN-116-workflow-host-job-start-status-and-completion-over-internal-host.md)
[SCN-118](../scenarios/SCN-118-hosted-hobby-safe-long-transcript-replay-via-workflow-host.md)
`spec/runtime/workflow-framework-contract.md`, `spec/runtime/index.md`, `spec/architecture/containers/workflow-host.md` | none extracted | [SCN-116](../scenarios/SCN-116-workflow-host-job-start-status-and-completion-over-internal-host.md) + [SCN-118](../scenarios/SCN-118-hosted-hobby-safe-long-transcript-replay-via-workflow-host.md) + `scenarios/hosted/index.md` | workflow topology/status and hosted durability anchors are now repo-local, and the dedicated workflow contract spec is landed | -| `command-framework` | `spec/runtime/command-framework-contract.md`, `spec/runtime/index.md` | none extracted | [Scenario matrix](../scenarios/scenario-matrix.md) + `scenarios/contracts/index.md` | framework contract spec is now landed; concrete split command scenarios remain later-wave work | +| `command-framework` | `spec/runtime/command-framework-contract.md`, `spec/runtime/index.md` | `packages/core` (`@dd-bot-platform/core`, `packages/core/src/command-framework`) | [Scenario matrix](../scenarios/scenario-matrix.md) + `scenarios/contracts/index.md` | first typed command-framework implementation is landed with deterministic registry/availability/dispatch tests; concrete Docoved/SellerAgent command adoption and hosted scenarios remain product-side follow-up work | | `shared-governed-content-and-import-substrate` | [SCN-177](../scenarios/SCN-177-shared-governed-content-import-readback-contract.md)
`plans/protocols/PRT-040-governed-content-source-processing-and-workflow-backed-import-substrate.md`, `spec/runtime/persistence-interface-and-store-boundary.md`, `spec/runtime/workflow-framework-contract.md`, `spec/project/feature-area-boundaries.md` | none extracted | [SCN-177](../scenarios/SCN-177-shared-governed-content-import-readback-contract.md) + [Scenario matrix](../scenarios/scenario-matrix.md) | shared governed-content/import implementation slices and the first runnable local framework verifier anchor are landed in `bot-platform`; Docoved links the first owner-side adoption proof upstream through its Wave 05 local closure line, so the wave-1 first-consumer handoff is closed and future hosted/product-activation or non-Docoved reuse proof belongs to later protocols | | `support-packages` | [SCN-041](../scenarios/SCN-041-verdict-export-stability-and-provenance.md)
`spec/project/repo-structure.md`, `spec/project/feature-area-boundaries.md`, `spec/runtime/execution-traces-and-token-accounting.md`, `spec/runtime/trace-artifact-governance.md` | only proven slices: `api-contract`, `scenario-system` | [SCN-041](../scenarios/SCN-041-verdict-export-stability-and-provenance.md) + `scenarios/contracts/index.md` | verdict export/provenance now has a repo-local framework scenario anchor; broader support-package extraction still requires multi-consumer proof | diff --git a/.memory-bank/spec/project/feature-area-boundaries.md b/.memory-bank/spec/project/feature-area-boundaries.md index 8dfd34f..dd7d4fa 100644 --- a/.memory-bank/spec/project/feature-area-boundaries.md +++ b/.memory-bank/spec/project/feature-area-boundaries.md @@ -2,7 +2,7 @@ file: .memory-bank/spec/project/feature-area-boundaries.md description: 'Framework feature-area boundaries for bot-platform.' purpose: Define which framework areas bot-platform owns and where product repos must take over. -version: 0.3.0 +version: 0.4.0 date: 2026-04-25 status: ACTIVE tags: [feature-areas, boundaries, bot-platform, framework] @@ -12,6 +12,9 @@ related_files: - .memory-bank/spec/project/repo-structure.md - .memory-bank/spec/project/three-layer-product-line-architecture.md history: + - version: 0.4.0 + date: 2026-04-26 + changes: Updated command-framework and channel-runtime boundaries after PRT-043 landed typed command contracts plus provider-neutral threading/delivery summary contracts. - version: 0.3.0 date: 2026-04-25 changes: Added the channel-runtime feature area after PRT-042 implementation and recorded the thin-seam rule for canonical response documents and pure rendering helpers. @@ -63,8 +66,15 @@ Owns: - command envelope and parser; - command registry primitives; - command execution hooks; +- actor/channel availability policy shape; - projection hooks and diagnostics patterns. +Does not own: +- product command catalogs or command names; +- product permission ladders and role mapping; +- channel tokenization quirks such as Telegram slash mentions or email subject conventions; +- command side effects, product persistence writes, provider sends, or UI/menu copy. + ### `channel-runtime` Owns: @@ -73,10 +83,11 @@ Owns: - citations and source-reference shape for channel-neutral delivery; - minimal render-target vocabulary; - small pure markdown/plaintext helpers when they remove real duplication. +- provider-neutral threading intent and outbound delivery result-summary contracts when they remain side-effect free and reference-only. Does not own: - command dispatch or command access policy; -- transport senders, delivery orchestration, provider retries, or threading state; +- transport senders, delivery orchestration, provider retries, or persisted threading state; - provider payloads such as Telegram parse mode or email headers; - product answer semantics, product source selection, DB tables, migrations, or UI screens. diff --git a/.memory-bank/spec/runtime/channel-runtime-contract.md b/.memory-bank/spec/runtime/channel-runtime-contract.md index a0813d2..af9c9cf 100644 --- a/.memory-bank/spec/runtime/channel-runtime-contract.md +++ b/.memory-bank/spec/runtime/channel-runtime-contract.md @@ -2,13 +2,14 @@ file: .memory-bank/spec/runtime/channel-runtime-contract.md description: 'Framework runtime contract for canonical response documents and minimal channel rendering primitives.' purpose: Define the stable first-wave vocabulary for channel-neutral response documents so product channels can render the same answer semantics without copying Telegram/email-specific helpers into core logic. -version: 0.2.0 -date: 2026-04-25 +version: 0.4.0 +date: 2026-04-26 status: DRAFT tags: [runtime, channel-runtime, contracts, rendering, framework] parent: .memory-bank/spec/runtime/index.md related_files: - .memory-bank/plans/protocols/PRT-042-channel-runtime-canonical-document-command-and-rendering.md + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md - .memory-bank/spec/runtime/command-framework-contract.md - .memory-bank/spec/runtime/pipeline-registry-and-binding-contract.md - .memory-bank/spec/architecture/boundaries.md @@ -16,6 +17,12 @@ related_files: - .memory-bank/mbb/principles.md - .memory-bank/mbb/delivery-docs-guide.md history: + - version: 0.4.0 + date: 2026-04-26 + changes: Recorded the PRT-043 provider-neutral threading and outbound delivery result-summary slice in `packages/channel-runtime`, keeping delivery intent reference-only and side-effect free. + - version: 0.3.0 + date: 2026-04-26 + changes: Linked PRT-043 as the draft follow-up that opens actor-aware commands, universal channel rendering, threading intent, and outbound delivery intent after the first-wave document seam. - version: 0.2.0 date: 2026-04-25 changes: Added deferred-work semantics to clarify why commands, delivery orchestration, threading, HTML, DB, and UI are outside the first-wave contract but remain possible future extensions. @@ -37,19 +44,22 @@ It defines: - stable response/run/trace reference slots; - minimal render-target vocabulary; - pure helper boundaries for markdown/plaintext rendering. +- provider-neutral threading intent and delivery result-summary contracts after PRT-043, without provider send logic. It does not define: - product answer semantics; - product knowledge-source selection; - provider-specific Telegram, email, web, or SMS payloads; - command dispatch, command registry, or command access policy; -- delivery orchestration, retry queues, threading, or provider send logic; +- delivery orchestration, retry queues, provider send logic, or persisted delivery/threading state; - DB tables, migrations, persistent delivery records, read models, or UI screens. These exclusions are first-wave boundaries, not permanent bans. Future work may add command adoption, delivery orchestration, threading, HTML rendering, persistence, or UI only after a product proof demonstrates repeated provider-neutral behavior. Until then, product adapters keep side effects and provider-specific behavior local. +The active follow-up planning anchor for command adoption, channel rendering responsibility, configurable threading intent, and outbound delivery intent is [PRT-043 Channel Interaction Runtime](../../plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md). + ## Ownership `bot-platform` owns the shared contract and must keep it product-neutral. @@ -115,8 +125,8 @@ Out of scope: - universal `ChannelRenderer`; - `ChannelRenderPolicy`; - `RenderedChannelMessage`; -- `OutboundDeliveryPlan`; -- `OutboundDeliveryThreading`; +- `OutboundDeliveryPlan` as orchestration; +- provider-specific delivery/threading payloads; - framework-owned HTML renderer. Product adapters remain responsible for provider-specific output: @@ -125,6 +135,47 @@ Product adapters remain responsible for provider-specific output: - web component rendering; - transport send attempts, retries, and provider errors. +## Threading Intent + +`channel-runtime` owns only a provider-neutral threading request shape. + +Current package anchor: +- `OutboundThreadingMode`; +- `OutboundThreadingConfig`; +- `InboundThreadingContext`; +- `OutboundThreadingIntent`; +- `createDefaultThreadingIntent`. + +Supported modes: +- `reply_to_inbound` — ask the adapter to answer in relation to the inbound message when the inbound transport reference and channel capability allow it; +- `new_thread` — ask the adapter to start a new provider thread/conversation unit; +- `none` — send without thread linkage. + +Rules: +- products configure the mode per concrete channel instance; +- provider-specific mapping remains adapter-owned, for example email `In-Reply-To` / `References` or Telegram reply parameters; +- fallback from `reply_to_inbound` must be explicit and deterministic; +- missing or unsupported inbound reply targets must not silently pretend that a threaded reply happened. + +## Outbound Delivery Result Summary + +`channel-runtime` may describe provider-neutral delivery intent and terminal summary, but it must not send messages. + +Current package anchor: +- `OutboundDeliveryIntent`; +- `OutboundDeliveryTarget`; +- `OutboundDeliveryResultSummary`; +- `OutboundDeliveryDiagnosticsSummary`; +- `classifyOutboundDeliveryTerminalState`; +- `isOutboundDeliveryTerminalSuccess`. + +Rules: +- `OutboundDeliveryIntent` is reference-only for response/rendered content (`documentRef`, `renderedMessageRef`, format, threading, and correlation fields); +- full `CanonicalResponseDocument` values stay in runtime/product memory or product-owned artifacts and are not embedded into the delivery intent seam; +- terminal summary statuses are `delivered`, `suppressed`, and `failed`; +- diagnostics must be bounded and safe for logs; raw provider payloads, secrets, and full answer bodies stay out of routine framework diagnostics; +- retries, queues, idempotency stores, and provider SDK sends remain product/adapter-owned. + ## Markdown Subset The canonical public text format is markdown-compatible text. @@ -190,6 +241,12 @@ The first implementation must include: - import-boundary proof showing no product, DB, or provider SDK imports; - pack/publish dry-run if a new publishable package is created. +The PRT-043 implementation slice adds deterministic tests for: +- reply-to-inbound retention when inbound refs exist; +- `new_thread` / `none` fallback when inbound refs are missing or unsupported; +- delivered / suppressed / failed terminal delivery classification; +- public export smoke for threading and delivery contracts. + Product adoption must add product-local proofs: - Docoved maps `DocovedAnswerArtifact` to `CanonicalResponseDocument`; - the same Docoved canonical document renders to email and Telegram without changing answer/source semantics; diff --git a/.memory-bank/spec/runtime/command-framework-contract.md b/.memory-bank/spec/runtime/command-framework-contract.md index 4578004..35e3e85 100644 --- a/.memory-bank/spec/runtime/command-framework-contract.md +++ b/.memory-bank/spec/runtime/command-framework-contract.md @@ -2,8 +2,8 @@ file: .memory-bank/spec/runtime/command-framework-contract.md description: 'Framework runtime contract for the command framework: command envelope, parser and registry primitives, dispatch hooks, and shared diagnostics.' purpose: Read when defining reusable command surfaces in `bot-platform` so framework command mechanics stay product-agnostic and do not absorb channel or product command truth. -version: 1.0.0 -date: 2026-04-22 +version: 1.2.0 +date: 2026-04-26 status: ACTIVE c4_level: L2 tags: [runtime, commands, framework-contract, diagnostics, dispatch, bot-platform] @@ -11,9 +11,16 @@ parent: .memory-bank/spec/runtime/index.md related_files: - .memory-bank/spec/project/feature-area-boundaries.md - .memory-bank/spec/runtime/agent-execution-kernel.md + - .memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md - .memory-bank/plans/epics/framework-feature-registry.md - .memory-bank/plans/protocols/PRT-036-platform-framework-and-product-repo-split.md history: + - version: 1.2.0 + date: 2026-04-26 + changes: Recorded the first PRT-043 code slice: `packages/core/src/command-framework` now exports product-neutral typed command contracts, registry helpers, availability evaluation, dispatch result envelopes, and deterministic tests. + - version: 1.1.0 + date: 2026-04-26 + changes: Linked PRT-043 as the draft implementation follow-up for actor-aware command availability across product actors, channel kinds, and concrete channel instances. - version: 1.0.0 date: 2026-04-22 changes: Landed the repo-local framework command contract for command envelope, parser/registry/dispatch primitives, and shared diagnostics under PRT-036 Wave 158. @@ -31,6 +38,11 @@ Define the narrow command-framework slice that `bot-platform` owns: This contract is intentionally narrow. It does not make `bot-platform` the owner of SellerAgent, Docoved, Telegram, or any other product command catalog. +The current draft implementation follow-up is [PRT-043 Channel Interaction Runtime](../../plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md). It extends this contract direction toward actor-aware command availability across system admins, workspace admins, employees/members, known external users, unknown external users, anonymous actors, channel kinds, and concrete channel instances without moving product command catalogs into the framework. + +The first implementation slice lives in `packages/core/src/command-framework`. +It is intentionally a typed contract/helper surface, not a product command catalog. + ## Framework ownership boundary `bot-platform` owns command mechanics: @@ -61,6 +73,10 @@ Rule: - framework code may define the envelope shape and lifecycle semantics; - product repos remain free to decide which concrete command keys exist and what business meanings they carry. +Current package anchor: +- `CommandEnvelope` lives in `packages/core/src/command-framework/contracts.ts`; +- it carries `actor`, `channel`, optional `ownership`, and optional `correlation` context using existing core refs instead of minting parallel identifiers. + ## Parser and normalization primitives Framework primitive: `CommandParser`. @@ -77,6 +93,11 @@ Framework rule: Framework non-rule: - the framework must not freeze Telegram-only command tokenization, channel mention behavior, or product message conventions as shared truth. +Current package anchor: +- `CommandParseResult` distinguishes `parsed`, `not_a_command`, and `failed`; +- `not_a_command` is a skip outcome so ordinary messages can continue through product answer flow; +- parse failure remains separate from `unknown_command`, validation, access, and handler failures. + ## Registry primitives Framework primitive: `CommandRegistry`. @@ -96,6 +117,10 @@ Registry boundary: - registry metadata may describe technical dispatch requirements; - registry metadata must not become a hidden home for product permission policy or product UX copy. +Current package anchor: +- `createCommandRegistry`, `listCommandDefinitions`, `getCommandDefinition`, and `requireCommandDefinition` live in `packages/core/src/command-framework/contracts.ts`; +- duplicate command keys are rejected deterministically. + ## Dispatch primitives Framework primitive: `CommandDispatcher`. @@ -110,6 +135,10 @@ Dispatch rule: - dispatch stays server-authoritative and traceable; - products own the handler implementation and the resulting side effects. +Current package anchor: +- `dispatchCommand` checks parse result, registry, validation, and availability before invoking the product-owned handler; +- handler payloads are generic so product repos can return their own result shape or later map to channel-runtime canonical responses. + ## Diagnostics and error-shape expectations Framework-owned command execution must distinguish at least these failure classes: @@ -130,12 +159,22 @@ Recommended diagnostic fields: - bounded human-readable summary; - optional structured field-level validation details. +Current package anchor: +- `CommandDispatchFailureClass` includes `parse_error`, `unknown_command`, `validation_error`, `access_denied`, and `dispatch_error`; +- thrown handler errors produce a safe public summary and bounded diagnostic details. + ## Access and permission boundary Framework owns only the access hook shape: - a command dispatch path may request an allow/deny decision from the canonical auth/access layer; - access failures must surface through the shared command error shape. +Current package anchor: +- `CommandActorType` includes `system_admin`, `workspace_admin`, `employee`, `known_external`, `unknown_external`, and `anonymous`, with string extension support; +- `CommandAvailabilityPolicy` supports allow/deny by actor type, channel kind, and concrete `channelRef`; +- explicit deny wins over allow; +- missing command availability policy denies by default. + Products own: - permission mapping; - role and capability semantics; diff --git a/.memory-bank/spec/runtime/index.md b/.memory-bank/spec/runtime/index.md index fe55d16..17d048e 100644 --- a/.memory-bank/spec/runtime/index.md +++ b/.memory-bank/spec/runtime/index.md @@ -2,8 +2,8 @@ file: .memory-bank/spec/runtime/index.md description: 'Runtime hub for bot-platform.' purpose: Hold framework runtime contracts for kernels, providers, pipelines, prompts, workflow, auth, command, and shared scenario-system layers. -version: 0.9.0 -date: 2026-04-25 +version: 0.11.0 +date: 2026-04-26 status: DRAFT tags: [runtime, bot-platform, contracts] parent: .memory-bank/spec/index.md @@ -21,6 +21,12 @@ children: target_audience: [developers, ai-agents] automation_ready: true history: + - version: 0.11.0 + date: 2026-04-26 + changes: Recorded PRT-043 platform implementation slice for command-framework contracts in `@dd-bot-platform/core` and threading/delivery summary contracts in `@dd-bot-platform/channel-runtime`. + - version: 0.10.0 + date: 2026-04-26 + changes: Noted that PRT-043 is the draft follow-up connecting channel-runtime and command-framework contracts for actor-aware commands, rendering, threading, and delivery intent. - version: 0.9.0 date: 2026-04-25 changes: Linked the first-wave channel-runtime contract for canonical response documents and minimal rendering primitives under PRT-042. @@ -69,8 +75,8 @@ Product runtime overlays stay out of this repo. ## Current runtime docs - [Agent execution kernel](agent-execution-kernel.md): defines the shared kernel contracts, workflow-family boundary, capability model, execution split, and trace requirements. -- [Channel runtime contract](channel-runtime-contract.md): defines canonical response documents, visibility, citations/source refs, minimal render-target vocabulary, and first-wave exclusions for commands, delivery orchestration, DB, and UI. -- [Command framework contract](command-framework-contract.md): defines the framework-owned command envelope, parser/registry/dispatch primitives, machine-readable diagnostics, and explicit product-owned exclusions. +- [Channel runtime contract](channel-runtime-contract.md): defines canonical response documents, visibility, citations/source refs, minimal render-target vocabulary, threading intent, outbound delivery result-summary contracts, and exclusions for delivery orchestration, provider senders, DB, and UI. +- [Command framework contract](command-framework-contract.md): defines the framework-owned command envelope, parser/registry/dispatch primitives, actor/channel availability, machine-readable diagnostics, product-owned exclusions, and the first PRT-043 implementation slice in `@dd-bot-platform/core`. - [Decision explanation envelope](decision-explanation-envelope.md): defines the framework-shared final-outcome explainability contract (`subject`, `final_outcome`, `summaries`, `decisive_factors`, `missing_requirements`, `provenance`) and projection boundaries. - [Execution traces and token accounting](execution-traces-and-token-accounting.md): defines framework-owned run/step/attempt trace layers, artifact linkage, usage accounting fields, and the billing boundary. - [Pipeline registry and binding contract](pipeline-registry-and-binding-contract.md): defines canonical pipeline definitions, channel binding validation, ownership boundaries, and pipeline defaults. diff --git a/.tasks/prt-043-channel-interaction-runtime/000-index.md b/.tasks/prt-043-channel-interaction-runtime/000-index.md new file mode 100644 index 0000000..8f95313 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/000-index.md @@ -0,0 +1,14 @@ +# PRT-043 Channel Interaction Runtime — Task Workspace + +Temporary workspace for implementation task packets, subagent reports, verifier reports, lessons learned, insights, and execution evidence. + +Canonical protocol docs: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` + +Rules: +- create one task file per subagent task; +- each subagent writes one report file here; +- verifier subagents must read original task, implementation report, and actual changed files; +- promote durable lessons/insights into Memory Bank before closure. diff --git a/.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md b/.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md new file mode 100644 index 0000000..f80e4f5 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md @@ -0,0 +1,72 @@ +# Task Packet Template + +## Task id +`T-043-XX` + +## Owner / model guidance +- Suggested agent type/model: +- Parallelism: +- Write scope: + +## Goal +Explain the delivered outcome and why this task exists in PRT-043. + +## Context to collect before work +Required docs: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` +- relevant runtime/product/ops docs for the task + +Required code searches: +- list exact `rg` queries or files to inspect before editing + +## Context readiness checklist +Before making any code or canonical documentation changes, the subagent must: +- state which repository/repositories are in scope; +- inspect current branch/status for each in-scope repo; +- read all required docs listed above and any nested/nearby `AGENTS.md` if editing under a new subtree; +- run the required code/doc searches from this packet; +- identify existing implementation seams, tests, helpers, fixtures, and product-owned boundaries that must be reused; +- list assumptions and unknowns that may affect design or scope; +- stop and report if a pre-code gate or ownership ambiguity is unresolved. + +The subagent report must include a `Context readiness` section summarizing: +- docs read; +- searches run; +- key files inspected; +- existing seams/helpers/tests found; +- assumptions/unknowns; +- decision that the task is ready for implementation or blocked. + +## What to do +- Step 1 +- Step 2 +- Step 3 + +## What not to do +- Do not change unrelated files. +- Do not move product command catalogs into `bot-platform`. +- Do not introduce framework DB/UI/provider sender scope. +- Do not bypass package-boundary decisions or product ownership rules. + +## Risks and thin points +- access/security: +- idempotency/retries: +- product compatibility: +- observability/redaction: + +## Completion criteria +- code/docs changed: +- tests/checks run: +- evidence produced: +- Memory Bank updates: + +## Report format +Write `.tasks/prt-043-channel-interaction-runtime/T-043-XX-report.md` with: +- summary; +- files changed; +- decisions/deviations; +- checks run and results; +- risks/follow-ups; +- lessons/insights candidates. diff --git a/.tasks/prt-043-channel-interaction-runtime/002-git-flow-start.md b/.tasks/prt-043-channel-interaction-runtime/002-git-flow-start.md new file mode 100644 index 0000000..40bc1a2 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/002-git-flow-start.md @@ -0,0 +1,9 @@ +# Git Flow Start Note + +Date: 2026-04-26 + +- Starting branch before implementation: `main` tracking `origin/main`. +- Repo git-flow says normal work should use `feature/*`, with `develop` preferred when materially active. +- Local `develop` branch was not active in this workspace at protocol start. +- Created implementation branch: `feature/EP-022-prt-043-channel-interaction-runtime` from current stable baseline. +- This branch is for PRT-043 protocol implementation only; no direct main push should happen from implementation work. diff --git a/.tasks/prt-043-channel-interaction-runtime/003-pre-code-gate-decision.md b/.tasks/prt-043-channel-interaction-runtime/003-pre-code-gate-decision.md new file mode 100644 index 0000000..3bc75e1 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/003-pre-code-gate-decision.md @@ -0,0 +1,79 @@ +# PRT-043 Pre-code Gate Decision + +Date: 2026-04-26 + +Inputs: +- `T-043-01-report.md` +- `T-043-05-report.md` +- `T-043-06-report.md` + +## Accepted decisions + +### G-043-01 command-framework implementation/export location + +Accepted: materialize command-framework typed contracts in `@dd-bot-platform/core` under `packages/core/src/command-framework/`, exported from `packages/core/src/index.ts`. + +Rationale: +- `@dd-bot-platform/core` already owns framework refs, channel/control-plane vocabulary, and has no package dependencies. +- Avoids a new package before dependency direction requires it. +- Avoids command-framework leakage into `@dd-bot-platform/channel-runtime`. + +### G-043-02 threading/delivery intent scope + +Accepted: add provider-neutral summary-only threading and outbound-delivery intent/result types to `@dd-bot-platform/channel-runtime`. + +Constraints: +- no provider SDK sender; +- no framework retry loop; +- no queues/schedulers; +- no DB/read models; +- no provider payload/header/reply SDK objects as first-class framework fields. + +### G-043-03 Docoved first parity command set + +Provisional: `/help`, `/sources`, `/status`, `/report`. + +Status: not ready for implementation. Product adoption remains blocked until Docoved decides canonical writable command-policy authority and builds/approves a live email command dispatch path. + +### G-043-04 SellerAgent first subset + +Accepted for planning: read-only diagnostics/readback subset only. + +Candidate subset: +- `/start`, `/help`, `/whoami`, `/status`, `/context`, `/pipeline`, `/why`, `/inspect`, `/versions`, `/releases`, `/current`. + +Status: broad adoption/mutation work blocked. Release-control mutation is out of first proof slice. + +### G-043-05 delivery fields + +Platform shared first slice: +- `deliveryId`, `attemptId`, `responseId`, `runId`, `traceId`, `channelRef`, `transportMessageRef`, `idempotencyKey`, `status`, `reasonCode`, timing summary, safe extensions. + +Product-local: +- provider payloads, retry history, stored delivery records, delivery plan steps, product workflow states, SellerAgent-specific job/conversation records. + +### G-043-06 threading config shape + +Platform first slice: +- default mode; +- fallback allowed flag; +- reply-to-origin required flag; +- namespaced adapter config summary/extensions. + +Product-local: +- provider ref lookup; +- email headers; +- Telegram reply params; +- config snapshots/storage. + +## Implementation authorization + +Authorized now: +- `T-043-02`: command-framework typed contracts in `@dd-bot-platform/core`. +- `T-043-03`: threading/delivery intent/result types in `@dd-bot-platform/channel-runtime`. + +Still blocked: +- `T-043-07`: Docoved adoption implementation. +- `T-043-08`: SellerAgent adoption implementation. +- any DB/UI/provider sender/mutation-command expansion. + diff --git a/.tasks/prt-043-channel-interaction-runtime/004-platform-implementation-progress.md b/.tasks/prt-043-channel-interaction-runtime/004-platform-implementation-progress.md new file mode 100644 index 0000000..c17e9c8 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/004-platform-implementation-progress.md @@ -0,0 +1,25 @@ +# PRT-043 Platform Implementation Progress + +## Status + +Platform slice `T-043-02` and `T-043-03` is complete. + +## Completed + +- `T-043-02`: implemented command-framework typed contracts in `packages/core/src/command-framework`. +- `T-043-03`: implemented provider-neutral threading and delivery result-summary contracts in `packages/channel-runtime/src/threading.ts` and `packages/channel-runtime/src/delivery.ts`. +- Verification subagents reviewed both code slices. +- Orchestrator hardened command availability so missing policy denies by default, matching the main PRT-043 safety rule. +- Orchestrator fixed the delivery intent seam after verifier feedback so `OutboundDeliveryIntent` remains reference-only. + +## Checks + +- `pnpm --filter @dd-bot-platform/core typecheck` — passed. +- `pnpm --filter @dd-bot-platform/channel-runtime typecheck` — passed. +- `node --test packages/core/dist/command-framework.spec.js packages/channel-runtime/dist/channel-runtime.spec.js` — 18 passed, 0 failed after final rerun. + +## Remaining gates + +- Product adoption in Docoved and SellerAgent is not part of this platform code slice. +- Hosted beta verification is not run until product scenarios are ready. +- Package release/publish requires the normal Changesets/release workflow after merge readiness. diff --git a/.tasks/prt-043-channel-interaction-runtime/005-lessons-learned.md b/.tasks/prt-043-channel-interaction-runtime/005-lessons-learned.md new file mode 100644 index 0000000..0a57853 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/005-lessons-learned.md @@ -0,0 +1,31 @@ +# PRT-043 Lessons Learned + +## 001 — Delivery intent must stay reference-only + +When channel-runtime describes outbound delivery, the intent should carry stable references to the canonical response or rendered message, not the full `CanonicalResponseDocument`. + +Why: +- keeps the package seam thin; +- avoids accidental duplication of product/runtime answer artifacts; +- prevents delivery contracts from becoming a hidden persistence or payload transport layer; +- leaves provider-specific payload generation and full document lifecycle in product/adapters. + +Memory Bank promotion: +- promoted into `.memory-bank/spec/runtime/channel-runtime-contract.md` under `Outbound Delivery Result Summary`. + +## 002 — Verifier tasks are useful even for small type-only slices + +The verifier subagent caught a scope-widening field that passed typecheck and tests. +For protocol work that changes package contracts, verification should inspect actual exported shape, not only green checks. + +Memory Bank promotion: +- promoted into `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` through the accepted verifier/fix status for `T-043-03`. + +## 003 — Task packets must not weaken protocol safety defaults + +The implementation task packet originally allowed a permissive missing-policy default for commands, while the main PRT-043 protocol requires framework default deny. +The code was hardened to `default_deny`; product external policy remains optional, but a command definition must provide an internal allow policy before dispatch reaches the handler. + +Memory Bank promotion: +- promoted into `.memory-bank/spec/runtime/command-framework-contract.md` through the current package anchor for availability policy; +- promoted into `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` as an accepted post-verification hardening. diff --git a/.tasks/prt-043-channel-interaction-runtime/006-platform-slice-closeout.md b/.tasks/prt-043-channel-interaction-runtime/006-platform-slice-closeout.md new file mode 100644 index 0000000..8b809a5 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/006-platform-slice-closeout.md @@ -0,0 +1,34 @@ +# PRT-043 Platform Slice Closeout + +## Scope closed + +Closed for the platform-only implementation slice: +- `T-043-02` command-framework typed contracts in `@dd-bot-platform/core`; +- `T-043-03` channel-runtime threading and outbound delivery result-summary contracts in `@dd-bot-platform/channel-runtime`; +- reports, verification, docs, and Changeset evidence. + +## Scope intentionally not closed + +Not closed by this slice: +- Docoved product adoption is blocked until `@dd-bot-platform/*@0.3.0` is published or an approved immutable bridge is used; +- SellerAgent product adoption is blocked until `@dd-bot-platform/*@0.3.0` is published or an approved immutable bridge is used; +- hosted beta scenarios wait for product adoption after package release; +- package publication is prepared through Changesets `0.3.0` versioned state but still requires merge to `main` and the release workflow; +- provider senders, DB/read models, UI/admin, queues/retry orchestration. + +## Closure evidence + +- Implementation reports: + - `.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md` + - `.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md` +- Verification reports: + - `.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.md` + - `.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.md` +- Progress: + - `.tasks/prt-043-channel-interaction-runtime/004-platform-implementation-progress.md` +- Lessons: + - `.tasks/prt-043-channel-interaction-runtime/005-lessons-learned.md` + +## Final local checks + +Final check commands are recorded in the task progress file and must be refreshed before commit if code/docs change again. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-01-package-boundary-decision.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-01-package-boundary-decision.task.md new file mode 100644 index 0000000..59b26f7 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-01-package-boundary-decision.task.md @@ -0,0 +1,80 @@ +# T-043-01 Package Boundary Decision + +## Owner / model guidance +- Suggested model: `gpt-5.5` +- Parallelism: can run in parallel with Docoved/SellerAgent inventory tasks. +- Write scope: report only. Do not edit repo code/docs. + +## Goal +Resolve the first pre-code gate for PRT-043: where command-framework typed contracts should live, whether threading/delivery intent belongs in `@dd-bot-platform/channel-runtime` now, and which existing refs/vocabularies must be reused. + +This task exists because implementation code must not start until package boundaries are clear. + +## Context to collect before work +Required docs: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `.memory-bank/spec/runtime/index.md` +- `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` +- `.memory-bank/mbb/delivery-docs-guide.md` + +Required code searches: +- `find packages -maxdepth 3 -type f -name package.json -print` +- `find packages -maxdepth 4 -type f -name '*.ts' | sort` +- `rg -n "CommandEnvelope|CommandRegistry|CommandDispatcher|CommandAvailability|CommandActor|ChannelRef|ExecutionRunRef|ReplyThreadLinkingFidelity|OutboundDelivery|ThreadingIntent|CanonicalResponseDocument" packages` +- inspect `packages/core/src/index.ts` +- inspect `packages/core/src/control-plane/**` +- inspect `packages/api-contract/src/control-plane/**` +- inspect `packages/channel-runtime/src/**` +- inspect root `package.json`, `pnpm-workspace.yaml` + +## Context readiness checklist +Before making recommendations, the subagent must: +- inspect current branch/status; +- read all required docs; +- run all required searches; +- identify existing package exports and dependency directions; +- identify whether command-framework is code-backed or documentation-only today; +- identify existing control-plane refs/capability/observability vocabularies to reuse; +- list assumptions and unknowns; +- decide whether implementation is ready or blocked. + +## What to do +- Recommend the package/module home for command-framework typed contracts. +- Recommend whether threading/delivery intent/result types should enter `channel-runtime` in first implementation or remain product-local for now. +- Define a lean first platform contract slice. +- Identify exact files likely to change in platform implementation. +- Identify tests/checks needed for the chosen boundary. +- Note any semver/release implications. + +## What not to do +- Do not create or edit code. +- Do not propose moving product command catalogs into `bot-platform`. +- Do not propose framework DB/UI/provider senders. +- Do not introduce a new package unless dependency direction justifies it. + +## Risks and thin points +- Avoid duplicate command framework inside `channel-runtime`. +- Avoid parallel vocabulary for refs/capabilities already in `core` / `api-contract`. +- Avoid overengineering delivery/threading beyond provider-neutral intent/result. + +## Completion criteria +- Report answers all pre-code boundary questions. +- Report names recommended package/module and rejected alternatives. +- Report identifies blocking unknowns if any. + +## Report format +Write `.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md` with: +- summary recommendation; +- context readiness; +- package inventory; +- decision matrix; +- recommended implementation slice; +- files likely to change; +- tests/checks; +- semver/release notes; +- risks/follow-ups. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md new file mode 100644 index 0000000..31f85c4 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md @@ -0,0 +1,332 @@ +# T-043-01 Package Boundary Decision Report + +## Summary recommendation + +Recommended boundary: + +- Materialize command-framework typed contracts in `@dd-bot-platform/core`, under a new command-framework-owned module such as `packages/core/src/command-framework/`, exported from `packages/core/src/index.ts`. +- Keep `@dd-bot-platform/channel-runtime` as the home for channel-adjacent canonical response, render, threading intent/resolution, and outbound delivery intent/result summary types. +- Do not put command parser/registry/dispatcher/availability contracts in `@dd-bot-platform/channel-runtime`. +- Do not create a new `@dd-bot-platform/command-framework` package for the first implementation slice; current dependency direction does not require it. +- Tie command success to canonical responses through generics or a channel-runtime bridge type, not by making `@dd-bot-platform/core` depend on `@dd-bot-platform/channel-runtime`. + +Implementation readiness verdict: + +- Ready for platform contract implementation after this decision is accepted: `T-043-02` command contracts in `core` and `T-043-03` channel intent/result contracts in `channel-runtime`. +- Still blocked for product adoption until product-specific gates are resolved: Docoved first parity command set, SellerAgent first read-only/diagnostic subset, and product-local effective config/write authority details. + +## Context readiness + +Repository status: + +- Current branch: `feature/EP-022-prt-043-channel-interaction-runtime`. +- `git status --short --branch` was clean before report writing. +- Write scope honored: no code or canonical docs were edited; only this report is written. + +Required docs read: + +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `.memory-bank/spec/runtime/index.md` +- `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` +- `.memory-bank/mbb/delivery-docs-guide.md` + +Required searches run: + +- `find packages -maxdepth 3 -type f -name package.json -print` +- `find packages -maxdepth 4 -type f -name '*.ts' | sort` +- `rg -n "CommandEnvelope|CommandRegistry|CommandDispatcher|CommandAvailability|CommandActor|ChannelRef|ExecutionRunRef|ReplyThreadLinkingFidelity|OutboundDelivery|ThreadingIntent|CanonicalResponseDocument" packages` + +Required files inspected: + +- `package.json` +- `pnpm-workspace.yaml` +- `packages/core/package.json` +- `packages/api-contract/package.json` +- `packages/channel-runtime/package.json` +- `packages/scenario-system/package.json` +- `packages/core/src/index.ts` +- `packages/core/src/control-plane/**` +- `packages/api-contract/src/control-plane/**` +- `packages/channel-runtime/src/**` + +Existing package exports and dependency directions: + +- `@dd-bot-platform/core` has no package dependencies and exports `./runtime`, `./control-plane`, and `./governed-content`. +- `@dd-bot-platform/api-contract` depends only on `zod` and exports schema/read-model surfaces, including control-plane schemas. +- `@dd-bot-platform/channel-runtime` depends on `@dd-bot-platform/api-contract` and `@dd-bot-platform/core`; it re-exports `RuntimeUsage`, `ChannelRef`, `ExecutionRunRef`, and `IsoTimestamp`. +- `@dd-bot-platform/scenario-system` depends on `@dd-bot-platform/api-contract` and is not a suitable home for runtime command contracts. +- `tsconfig.build.json` references `api-contract`, `channel-runtime`, `core`, and `scenario-system`; existing project references already allow `channel-runtime -> core/api-contract`. + +Command-framework code-backed status: + +- `CommandEnvelope`, `CommandRegistry`, `CommandDispatcher`, `CommandAvailability`, and `CommandActor` do not exist in package source today. +- Command-framework is documentation-backed today by `.memory-bank/spec/runtime/command-framework-contract.md` and PRT-043 planning docs. +- Package source contains only adjacent command mentions: `supportsOperatorCommands`, `commandId` metadata in `CanonicalResponseMetadata`, and scenario semantic-eval event text. + +Existing refs/capability/observability vocabulary to reuse: + +- Refs in `@dd-bot-platform/core`: `WorkspaceRef`, `ProductInstanceRef`, `ChannelRef`, `PipelineBindingRef`, `ExecutionRunRef`, `TraceArtifactRef`, `PrincipalRef`, `PolicyAssignmentRef`, `PipelineId`, `IsoTimestamp`. +- Channel vocabulary in `@dd-bot-platform/core`: `ChannelKind`, `KnownChannelKind`, `ChannelCapabilityMatrix`, `ReplyThreadLinkingFidelity`, `PipelineBindingStatus`. +- Capability vocabulary in `@dd-bot-platform/core` and `api-contract`: `ControlPlaneCapabilityFamily` and `CONTROL_PLANE_CAPABILITY_FAMILIES`. +- Observability vocabulary in `@dd-bot-platform/core` and `api-contract`: `ControlPlaneObservabilityEvent`, `compat_fallback_used`, correlation fields, operation ids, safe details object. +- Channel-runtime response vocabulary: `CanonicalResponseDocument`, `CanonicalResponseMetadata`, visibility sections, citations/source refs, artifacts, render targets/formats, markdown/plaintext helpers. + +Assumptions: + +- Public exported type additions require Changesets version bumps for every touched publishable package. +- Source files are canonical; `dist/` artifacts are present locally but not tracked by git. +- The first platform slice should be type/pure-helper only, not a provider sender, DB store, queue, UI, or product command catalog. +- Product repos will adapt their own actor lookup, command catalogs, persistence lookups, and provider send/retry behavior. + +Unknowns: + +- Exact Docoved first parity command set is not defined in this repo. +- Exact SellerAgent first read-only/diagnostic subset is not defined in this repo. +- Product-local canonical writable command-policy authority is not defined here. +- Exact product idempotency-key derivation and stored transport-reference lookup remain product-local. +- Whether API/Zod schemas for command contracts are required in `@dd-bot-platform/api-contract` is not proven for the first implementation slice. + +Ready/blocked decision: + +- Ready: package/module boundary for command-framework typed contracts. +- Ready: first platform threading/delivery intent/result scope, if kept provider-neutral and summary-only. +- Blocked: product adoption implementation until product inventories/config authorities are completed. +- Blocked: any DB/read-model/UI/provider-sender work; no evidence justifies those scopes. + +## Package inventory + +| Package | Current role | Dependencies | Relevant existing exports | Boundary implication | +| --- | --- | --- | --- | --- | +| `@dd-bot-platform/core` | Framework-safe execution/control-plane/governed-content contracts and helpers | none | `runtime`, `control-plane`, `governed-content`; refs, channel kinds, capability families, observability helper | Best first home for command-framework typed contracts because it can reuse refs without creating cycles. | +| `@dd-bot-platform/api-contract` | Zod-backed API/control-plane/governed-content/read-model schemas | `zod` | control-plane schemas, runtime usage schema, read envelopes | Not first home for dispatch/registry/error classes; add schemas later only if a serialized API surface is proven. | +| `@dd-bot-platform/channel-runtime` | Canonical response document and pure channel render helpers | `core`, `api-contract` | `CanonicalResponseDocument`, visibility filtering, render helpers, channel runtime error | Best home for threading/delivery intent/result summary types; wrong home for command parser/dispatch/availability. | +| `@dd-bot-platform/scenario-system` | Scenario and semantic-eval primitives | `api-contract`, `@openai/codex-sdk` | scenario artifacts, fixtures, semantic-eval runtime | Not part of this runtime boundary. | + +Notable source facts: + +- `packages/channel-runtime/src/document.ts` already imports `ChannelRef`, `ExecutionRunRef`, and `IsoTimestamp` from `core` and `RuntimeUsage` from `api-contract`. +- `packages/channel-runtime/src/document.ts` already has response correlation slots: `responseId`, `runId`, `traceId`, `channelRef`, `commandId`, `attemptId`, `deliveryId`, `transportMessageRef`. +- `packages/core/src/control-plane/models.ts` already has channel capability fields for `supportsOperatorCommands` and `replyThreadLinkingFidelity`. +- `packages/core/src/control-plane/observability.ts` already provides a safe event envelope pattern but not PRT-043 command/thread/delivery event names. + +## Decision matrix + +### Command-framework typed contracts + +| Option | Recommendation | Rationale | Rejected/accepted trade-off | +| --- | --- | --- | --- | +| Add `packages/core/src/command-framework/` and export from `@dd-bot-platform/core` | Accept | Aligns with `command-framework` ownership, keeps zero-dependency package, reuses control-plane refs/capabilities, avoids new package. | Success payload must be generic or bridged so `core` does not import `channel-runtime`. | +| Put command contracts in `@dd-bot-platform/channel-runtime` | Reject | Violates channel-runtime boundary; risks duplicate `ChannelCommand*` abstractions and command dispatch/access policy leakage. | Channel-runtime may reference command ids or bridge result-to-document types only. | +| Put command contracts in `@dd-bot-platform/api-contract` | Reject for first slice | API schemas are useful only when a serialized API surface is proven; registry/dispatcher/errors are runtime contracts, not schema-first API contracts. | Add Zod schemas later if product/API consumers need validation across process boundaries. | +| Create `@dd-bot-platform/command-framework` now | Reject for first slice | No current dependency cycle requires it, and the task forbids new packages unless dependency direction justifies one. | Revisit if command contracts must version independently or cannot stay generic without cycles. | +| Keep command contracts product-local | Reject | PRT-043 requires cross-product command mechanics; product-local copies would duplicate policy/result/failure vocabulary. | Product command catalogs and handlers stay product-local. | + +### Threading/delivery intent and result types + +| Option | Recommendation | Rationale | Rejected/accepted trade-off | +| --- | --- | --- | --- | +| Add provider-neutral summary types to `@dd-bot-platform/channel-runtime` now | Accept | Threading and delivery are channel-adjacent, already share response/correlation slots, and can serve Docoved/SellerAgent without provider senders. | Must be limited to intent/resolution/result summaries; no queues, retries, storage, or provider payloads. | +| Keep all threading/delivery types product-local until a second proof | Reject for intent/result vocabulary only | PRT-043 already identifies cross-channel Docoved and SellerAgent needs; keeping even summary vocabulary local would prolong drift. | Product-local remains correct for provider mapping, persistence lookup, retry, and delivery records. | +| Put threading/delivery runtime types in `core` control-plane | Reject | `core` owns capability/readback vocabulary like `ReplyThreadLinkingFidelity`; runtime outbound intent/result belongs next to canonical response/rendering. | Reuse `ReplyThreadLinkingFidelity` as capability input, not as a replacement for `ThreadingIntent`. | + +## Recommended implementation slice + +### `@dd-bot-platform/core` command-framework slice + +Add a new command-framework module with only product-agnostic contracts and deterministic pure helpers: + +- `CommandInvocationSource` + - Reuse `WorkspaceRef`, `ProductInstanceRef`, `ChannelRef`, `ChannelKind`, `PipelineBindingRef`, `ExecutionRunRef`, `TraceArtifactRef`, `PrincipalRef`, and `IsoTimestamp`. + - Include request/correlation ids and transport refs as nullable strings. +- `CommandActorClass` + - Minimum vocabulary: `system_admin`, `workspace_admin`, `workspace_member`, `verified_employee`, `external_known_user`, `external_unknown_user`, `anonymous`, plus namespaced extensions. +- `CommandActorContext` + - Actor class, optional safe `PrincipalRef`, workspace/product refs, product capability tags as strings or existing `ControlPlaneCapabilityFamily` where appropriate. +- `CommandEnvelope>` + - `commandKey`, normalized args, invocation source, actor context, scope/correlation refs. +- `CommandParseResult` + - `not_a_command`, `parse_error`, `unknown_command`, `valid_command`. +- `CommandDefinition` + - Stable key, optional argument validator hook, safe metadata, handler binding. +- `CommandRegistry` + - Register/resolve/list definitions without product catalog ownership. +- `CommandAvailabilityPolicy` and `CommandAvailabilityDecision` + - Actor class, channel kind, channel instance, product default, explicit allow/deny, reason codes. + - Include policy precedence/deny-over-allow helper if small and deterministic. +- `CommandExecutionResult` + - `success`, `not_a_command`, `parse_error`, `unknown_command`, `validation_error`, `access_denied`, `dispatch_error`, `unsupported_channel`, `rate_limited`. + - Carry bounded diagnostics and correlation refs. +- Command error classes or factory helpers + - Machine-readable and safe for framework-level tests; no raw args/provider payloads in defaults. +- Command observability constants/helpers + - If implemented, use safe event names from PRT-043 review details and the same shape principles as control-plane observability. + +Key constraint: + +- `core` must not import `@dd-bot-platform/channel-runtime`. If a command handler returns a canonical response, consumers can use `CommandExecutionResult`. + +### `@dd-bot-platform/channel-runtime` interaction slice + +Add provider-neutral channel-adjacent types: + +- `ThreadingMode` + - `reply_to_origin`, `continue_thread`, `new_message`, `none`. +- `ThreadingIntent` + - Requested mode, response/correlation refs, optional fallback policy summary, optional namespaced extensions. +- `ThreadingResolution` + - `resolved`, `fallback_used`, `ignored`, `failed`; requested/effective mode, bounded reason code, transport target ref summary, no provider headers or SDK objects. +- `ChannelInstanceThreadingPolicy` + - Default mode, fallback allowed, reply-to-origin required flag, optional namespaced adapter config ref/summary. +- `OutboundDeliveryStatus` + - `delivered`, `suppressed`, `failed`, `partial_failure`, `skipped`, `simulated`. +- `OutboundDeliveryIntent` + - `deliveryId`, `attemptId`, `responseId`, `runId`, `traceId`, `channelRef`, `transportMessageRef`, `idempotencyKey`, visibility/render format summary, optional `ThreadingIntent`. +- `OutboundDeliveryResult` + - Same correlation refs plus status, bounded reason code, safe provider/transport message ref summary, timing summary, extensions. + +Key constraints: + +- No provider SDK sender. +- No framework retry loop. +- No framework queue/scheduler. +- No framework delivery table/read model. +- No email headers, Telegram reply parameter objects, or provider payloads as first-class framework fields. + +### Shared-vs-product-local delivery field classification + +Shared first slice: + +- `deliveryId` +- `attemptId` +- `responseId` +- `runId` +- `traceId` +- `channelRef` +- `transportMessageRef` +- `idempotencyKey` +- `status` +- `reasonCode` +- `occurredAt` / timing summary +- safe `extensions` + +Product-local: + +- Provider SDK request/response payloads. +- Provider retry policy and retry history beyond summary counts/reason. +- Stored provider delivery records. +- Delivery plan steps. +- Product workflow states. +- SellerAgent-specific delivery outcome subtypes that are not proven for Docoved. +- Email `Message-ID`/`References` and Telegram reply parameter objects. + +## Files likely to change + +Command-framework implementation: + +- `packages/core/src/command-framework/index.ts` +- `packages/core/src/command-framework/actor.ts` +- `packages/core/src/command-framework/envelope.ts` +- `packages/core/src/command-framework/parser.ts` +- `packages/core/src/command-framework/registry.ts` +- `packages/core/src/command-framework/availability.ts` +- `packages/core/src/command-framework/dispatcher.ts` +- `packages/core/src/command-framework/results.ts` +- `packages/core/src/command-framework/observability.ts` +- `packages/core/src/command-framework/command-framework.spec.ts` +- `packages/core/src/index.ts` +- `packages/core/package.json` +- `packages/core/CHANGELOG.md` + +Channel-runtime interaction contracts: + +- `packages/channel-runtime/src/threading.ts` +- `packages/channel-runtime/src/delivery.ts` +- `packages/channel-runtime/src/index.ts` +- `packages/channel-runtime/src/channel-runtime.spec.ts` or new focused specs +- `packages/channel-runtime/package.json` +- `packages/channel-runtime/CHANGELOG.md` + +Optional later API schema surface, only if required by a consumer: + +- `packages/api-contract/src/command-framework/*` +- `packages/api-contract/src/channel-runtime/*` +- `packages/api-contract/src/index.ts` +- `packages/api-contract/package.json` +- `packages/api-contract/CHANGELOG.md` + +Canonical docs likely to change during implementation closure, not in this task: + +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `.memory-bank/spec/runtime/index.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +## Tests/checks + +Required framework checks: + +- `pnpm --filter @dd-bot-platform/core typecheck` +- `pnpm --filter @dd-bot-platform/channel-runtime typecheck` +- `pnpm build` +- `pnpm --filter @dd-bot-platform/core prepack` +- `pnpm --filter @dd-bot-platform/channel-runtime prepack` +- `pnpm changeset:status` + +Command-framework tests: + +- Public export/import smoke for `@dd-bot-platform/core`. +- Parse result union covers `not_a_command`, `parse_error`, `unknown_command`, `valid_command`. +- Availability policy covers actor classes, channel kinds, channel instance overrides, explicit deny over allow, and default deny. +- Decisions include bounded reason codes and required correlation refs. +- Execution result union covers `success`, `validation_error`, `access_denied`, `dispatch_error`, `unsupported_channel`, and `rate_limited`. +- Safe failure shaping does not include raw args, full provider messages, tokens, or full response bodies. +- Import-boundary proof: no product imports and no `@dd-bot-platform/channel-runtime` import inside `core`. + +Channel-runtime tests: + +- Public export/import smoke for `@dd-bot-platform/channel-runtime`. +- Threading intent serialization for all modes. +- Threading fallback/result shape for resolved, fallback, ignored, and failed cases. +- Delivery intent/result serialization for all first-slice statuses. +- Correlation fields round trip with existing `ChannelRef` and `ExecutionRunRef`. +- Type-level or runtime proof that provider payload/header/retry/storage fields are not required. +- Existing visibility/render helper tests remain green. + +Review checks: + +- Verify no product command catalogs moved into `bot-platform`. +- Verify no framework UI/admin/provider sender/DB/read-model scope was introduced. +- Verify `ReplyThreadLinkingFidelity` remains a channel capability/readback vocabulary and is not confused with `ThreadingIntent`. +- Verify `CommandExecutionResult` works from a consumer package without a `core -> channel-runtime` dependency. + +## Semver/release notes + +- Adding exported command-framework public types to `@dd-bot-platform/core` is a minor release. +- Adding exported threading/delivery public types to `@dd-bot-platform/channel-runtime` is a minor release. +- If `@dd-bot-platform/api-contract` schemas are added later, that package also needs a minor release. +- Changesets should be created before package release and changelogs updated via the existing Changesets flow. +- Product repos should consume pinned released package versions, not sibling-path source bridges, unless a temporary proof bridge is explicitly documented. +- No package publish should happen until typecheck/build/prepack and import-boundary proof pass. + +## Risks/follow-ups + +Risks: + +- A `core` command success type that imports `CanonicalResponseDocument` would create the wrong dependency direction; keep success payload generic. +- A `channel-runtime` command module would duplicate command-framework ownership; keep dispatch/access/registry out of channel-runtime. +- Threading/delivery types can grow into orchestration; keep first slice summary-only and provider-neutral. +- Actor classes can be mistaken for product permissions; products still own membership/capability mapping and final deny decisions. +- Observability helpers can accidentally log raw command args or provider payloads; defaults must be redaction-safe. + +Follow-ups: + +- Define Docoved first parity command set before Docoved adoption implementation. +- Define SellerAgent first read-only/diagnostic command subset before SellerAgent adoption implementation. +- Confirm product-local canonical writable command-policy authority and legacy compatibility adapter per product. +- Decide whether any command/thread/delivery API schemas are needed in `@dd-bot-platform/api-contract` after first source-level consumers exist. +- Promote accepted boundary decisions into canonical Memory Bank docs during implementation closure. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-02-command-framework-contracts.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-02-command-framework-contracts.task.md new file mode 100644 index 0000000..945b26d --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-02-command-framework-contracts.task.md @@ -0,0 +1,98 @@ +--- +task_id: T-043-02 +title: Command framework typed contracts in core +suggested_agent: worker / gpt-5.3-codex +status: READY +write_scope: + - packages/core/src/command-framework/** + - packages/core/src/index.ts + - packages/core/src/command-framework.spec.ts +report_path: .tasks/prt-043-channel-interaction-runtime/T-043-02-report.md +--- + +# T-043-02 Command framework typed contracts in core + +## Goal + +Add the first lean, product-neutral command-framework implementation surface to `@dd-bot-platform/core`. +This task must implement typed contracts and pure helpers only: command actor context, invocation envelope, parser result, registry metadata, actor/channel availability policy, dispatcher result envelopes, and deterministic tests. + +## Context readiness checklist + +Before editing, explicitly gather and record context in the report: +- confirm branch and git status; +- read `.memory-bank/index.md`; +- read `.memory-bank/spec/runtime/command-framework-contract.md`; +- read `.memory-bank/spec/project/feature-area-boundaries.md`; +- read `.memory-bank/spec/operations/observability-and-incident-diagnostics.md`; +- read `.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md`; +- inspect `packages/core/src/index.ts`; +- inspect existing `packages/core/src/runtime/**` and `packages/core/src/control-plane/**` patterns for type-only contracts, errors, and tests; +- run searches for `Command`, `access_denied`, `Capability`, `Actor`, `ChannelRef`, `ResultIntent`; +- list assumptions and any blockers before coding. + +Do not code until the context is complete. If the docs or existing code contradict this task, stop and report the blocker. + +## Implementation scope + +Create `packages/core/src/command-framework/` with a narrow surface: +- actor/context vocabulary for command availability: + - user types must cover at least `system_admin`, `workspace_admin`, `employee`, `known_external`, `unknown_external`, and `anonymous`; + - actor context must be generic and product-neutral; +- command envelope: + - stable `commandKey`; + - raw input and normalized args; + - actor, channel, ownership/scope, correlation metadata; +- parser contracts: + - parsed / not-a-command / failed result variants; + - parse diagnostics separate from validation/access/dispatch; +- registry contracts/helpers: + - command definition metadata; + - `createCommandRegistry`, `listCommandDefinitions`, `getCommandDefinition`, `requireCommandDefinition`; + - duplicate-key detection; +- availability policy: + - actor-type allow/deny; + - channel-kind allow/deny; + - concrete channelRef allow/deny; + - deny must win over allow; + - missing policy should be permissive by default for registered commands, while products can deny externally; +- dispatch contracts/helpers: + - normalized success/failure result envelope; + - failure classes: `parse_error`, `unknown_command`, `validation_error`, `access_denied`, `dispatch_error`; + - dispatcher invokes product-owned handler only after registry and availability checks; + - handler may return payload, canonical response document later, or custom product payload via generic type. + +Export the new surface from `packages/core/src/index.ts`. + +## Non-goals + +- no product command catalog; +- no Telegram/email parser quirks; +- no channel-runtime import from core; +- no DB/read-model persistence; +- no UI/admin; +- no provider SDK sender, queue, retry orchestration, or hosted deploy work; +- no broad refactor outside the write scope. + +## Tests + +Add deterministic Node test coverage in the package style: +- duplicate command keys are rejected; +- unknown command dispatch returns `unknown_command`; +- actor/channel/channelRef deny overrides allow; +- actor-type allow enables a command for the matching actor type; +- handler dispatch success returns normalized success envelope; +- thrown handler error returns `dispatch_error` without exposing raw secrets or stack as public summary. + +If the repo currently only builds spec files via `tsc`, follow that existing style. + +## Report + +Write `.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md` with: +- summary; +- context readiness evidence: docs read, searches run, files inspected, assumptions/blockers; +- files changed; +- implementation notes and deviations; +- checks run and results; +- risks/follow-ups; +- lessons learned / insights candidates, if any. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md new file mode 100644 index 0000000..e5b1471 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md @@ -0,0 +1,105 @@ +# T-043-02 Report — Command framework typed contracts in core + +## Summary +Implemented a new product-neutral command framework surface in `@dd-bot-platform/core` under `packages/core/src/command-framework/` and exported it from `packages/core/src/index.ts`. +The slice includes typed contracts and pure helpers for actor/context, envelope, parser results, registry, availability policy, and dispatch envelopes with deterministic tests. + +## Context readiness + +### Repository and status evidence (before edits) +- Repository in scope: `/Users/deksden/Documents/_Projects/bot-platform`. +- Branch: `feature/EP-022-prt-043-channel-interaction-runtime`. +- Observed status before coding included parallel/unrelated changes outside this task scope; they were not reverted or modified. + +### Docs read +- `.memory-bank/index.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` +- `.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` +- `.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md` (dependency decision confirmation) + +### Required searches run +- `rg -n "Command|access_denied|Capability|Actor|ChannelRef|ResultIntent" packages/core/src .memory-bank/spec/runtime .memory-bank/spec/project` + +### Files/patterns inspected +- `packages/core/src/index.ts` +- `packages/core/src/runtime/index.ts` +- `packages/core/src/runtime/kernel.ts` +- `packages/core/src/runtime/pipeline-registry.ts` +- `packages/core/src/control-plane/index.ts` +- `packages/core/src/control-plane/refs.ts` +- `packages/core/src/control-plane/capabilities.ts` +- `packages/core/src/control-plane/models.ts` +- `packages/core/src/control-plane/mutation-envelopes.ts` +- `packages/core/src/control-plane/channel-binding/verifier.spec.ts` +- `packages/core/src/control-plane/observability.spec.ts` +- `packages/core/src/governed-content/governed-content.verifier.spec.ts` +- `packages/core/package.json`, root `package.json`, `packages/core/tsconfig.json` + +### Assumptions and blockers (pre-code) +Assumptions: +- First slice must remain contract/helper only (no product catalog, no DB/UI/provider sender scope). +- Existing package style is TypeScript compile plus deterministic Node tests in `*.spec.ts`. +- External product policy denials should be pluggable via dispatcher input without moving policy ownership into core. + +Blockers: +- None found. Specs and prior boundary decision were consistent with task scope, so implementation proceeded. + +## Files changed +- `packages/core/src/command-framework/contracts.ts` +- `packages/core/src/command-framework/index.ts` +- `packages/core/src/command-framework.spec.ts` +- `packages/core/src/index.ts` + +## Implementation notes +- Added actor vocabulary with required types: `system_admin`, `workspace_admin`, `employee`, `known_external`, `unknown_external`, `anonymous` (+ extension string support). +- Added command envelope contracts with stable `commandKey`, `rawInput`, `normalizedArgs`, actor/channel context, ownership scope, and correlation metadata. +- Added parser result contracts and helpers for `parsed`, `not_a_command`, and `failed`, with parse diagnostics separated from later dispatch failures. +- Added registry contracts/helpers: + - `createCommandRegistry` + - `listCommandDefinitions` + - `getCommandDefinition` + - `requireCommandDefinition` + - duplicate-key rejection via `CommandRegistryError`. +- Added availability policy model and evaluator: + - actor-type allow/deny + - channel-kind allow/deny + - concrete channelRef allow/deny + - deny precedence over allow + - post-orchestrator hardening: missing command policy denies by default (`default_deny`) to match the main PRT-043 safety rule. +- Added normalized dispatch contracts/helpers: + - failure classes: `parse_error`, `unknown_command`, `validation_error`, `access_denied`, `dispatch_error` + - dispatch path enforces parse/registry/availability checks before invoking handler + - generic payload result support for product-defined payloads + - thrown handler errors mapped to safe `dispatch_error` public summary (`Command handler failed.`) with no raw secret/stack leakage. +- Exported new command framework surface from `packages/core/src/index.ts`. + +## Deterministic tests added +`packages/core/src/command-framework.spec.ts` covers: +- duplicate command key rejection; +- unknown command dispatch -> `unknown_command`; +- deny-over-allow precedence for actor/channel kind/channelRef; +- actor-type allow policy success; +- handler success normalized envelope; +- thrown handler error -> safe `dispatch_error` public summary (no leaked secret/stack terms); +- `not_a_command` dispatch skip envelope. + +## Checks run and results +- `pnpm --filter @dd-bot-platform/core typecheck` ✅ +- `pnpm --filter @dd-bot-platform/core build` ✅ +- `node --test packages/core/dist/command-framework.spec.js` ✅ (7 passed, 0 failed) + +## Deviations +- Added explicit `not_a_command` skipped dispatch variant in addition to required failure classes; this preserves parser/dispatch separation and avoids forcing non-command input into failure semantics. + +## Risks and follow-ups +- Future product adapters should supply `resolveAvailabilityPolicy` for product-owned deny overlays, while keeping command catalogs/permissions product-local. +- If API-level serialization becomes required, Zod/API-contract schemas for these command envelopes may be added later in a dedicated task. + +## Lessons learned / insights candidates +- Reusing existing control-plane refs and channel vocab in core avoided introducing parallel runtime identifiers. +- A thin generic dispatcher contract is enough to enforce policy/registry order without coupling core to channel-runtime or product handlers. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.md b/.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.md new file mode 100644 index 0000000..e5503a1 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.md @@ -0,0 +1,62 @@ +# T-043-02 Verification — Command framework typed contracts in core + +## Verdict +- accepted after orchestrator hardening + +## Scope compliance +- The implementation stays in `packages/core` and exports through `packages/core/src/index.ts`. +- I found no product catalog, DB, UI, provider SDK, transport sender, or `channel-runtime` code added to this slice. +- The new surface is product-neutral and matches the core/framework boundary described in the task packet and memory-bank specs. + +## Findings +- none + +## Context readiness evidence +- Repo/status checked in `/Users/deksden/Documents/_Projects/bot-platform`; unrelated worktree changes remain outside this task scope. +- Read: + - `.tasks/prt-043-channel-interaction-runtime/T-043-02-command-framework-contracts.task.md` + - `.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md` + - `.memory-bank/index.md` + - `.memory-bank/spec/runtime/command-framework-contract.md` + - `.memory-bank/spec/project/feature-area-boundaries.md` + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` + - `.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md` +- Inspected: + - `packages/core/src/index.ts` + - `packages/core/src/runtime/index.ts` + - `packages/core/src/control-plane/index.ts` + - `packages/core/src/control-plane/refs.ts` + - `packages/core/src/control-plane/capabilities.ts` + - `packages/core/src/control-plane/models.ts` + - `packages/core/src/control-plane/mutation-envelopes.ts` + - `packages/core/src/command-framework/contracts.ts` + - `packages/core/src/command-framework/index.ts` + - `packages/core/src/command-framework.spec.ts` +- Searches run: + - `rg -n "Command|access_denied|Capability|Actor|ChannelRef|ResultIntent" packages/core/src .memory-bank/spec/runtime .memory-bank/spec/project` + - focused `rg` checks across `packages/core/src`, `packages/channel-runtime/src`, and the runtime/project specs for product/channel/provider leaks. +- Diff reviewed: + - `git diff -- packages/core/src` + - `git status --short packages/core packages/channel-runtime .tasks/prt-043-channel-interaction-runtime` + +## Checks and evidence reviewed +- Verified the command framework lives under `packages/core/src/command-framework/`. +- Verified the actor vocabulary includes `system_admin`, `workspace_admin`, `employee`, `known_external`, `unknown_external`, and `anonymous`. +- Verified the envelope, parser result, registry, availability, and dispatch contracts are present and product-neutral. +- Verified dispatcher ordering: registry lookup and availability checks occur before handler invocation. +- Verified post-orchestrator hardening: missing availability policy denies by default, while product external policy is optional and evaluated only when supplied. +- Verified failure classes include `parse_error`, `unknown_command`, `validation_error`, `access_denied`, and `dispatch_error`. +- Verified handler error handling returns a safe public summary and does not surface raw secret text or stack text in the public summary. +- Verified deterministic tests cover the requested cases and `not_a_command` is handled as a skipped parse outcome. +- Ran: + - `pnpm --filter @dd-bot-platform/core typecheck` + - `pnpm --filter @dd-bot-platform/core build` + - `node --test packages/core/dist/command-framework.spec.js` +- Result: all checks passed; the Node test suite reported 7 passing tests and 0 failures. + +## Required fixes +- none + +## Optional follow-ups +- Keep any product-specific command catalogs and availability overlays outside `@dd-bot-platform/core`. +- If later tasks need API serialization, add schemas in a dedicated slice rather than expanding this contract surface opportunistically. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.task.md new file mode 100644 index 0000000..20a131f --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.task.md @@ -0,0 +1,51 @@ +--- +task_id: T-043-02-verification +title: Verify command framework implementation +suggested_agent: explorer / gpt-5.4-mini +status: READY +write_scope: + - .tasks/prt-043-channel-interaction-runtime/T-043-02-verification.md +--- + +# T-043-02 Verification + +## Goal + +Verify the implementation of `T-043-02` against the task packet, report, actual code, and protocol boundaries. + +## Required context readiness + +Before judging, read and record: +- `.tasks/prt-043-channel-interaction-runtime/T-043-02-command-framework-contracts.task.md`; +- `.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md`; +- `.memory-bank/spec/runtime/command-framework-contract.md`; +- `.memory-bank/spec/project/feature-area-boundaries.md`; +- `packages/core/src/command-framework/contracts.ts`; +- `packages/core/src/command-framework/index.ts`; +- `packages/core/src/command-framework.spec.ts`; +- `packages/core/src/index.ts`. + +Also inspect `git diff -- packages/core/src` and run focused searches for product/channel/provider leaks. + +## Review focus + +Check: +- command framework lives in core, not channel-runtime; +- no product catalog, DB, UI, provider SDK, or transport sender slipped in; +- actor types cover required categories; +- availability supports actor type, channel kind, channel ref, deny-over-allow; +- dispatcher does not call handler before registry/access/validation; +- failure classes match the protocol; +- thrown handler errors do not leak raw secret/stack as public summary; +- tests cover the requested cases; +- code is lean and does not create unused abstractions. + +## Output + +Write `.tasks/prt-043-channel-interaction-runtime/T-043-02-verification.md` with: +- verdict: accepted / needs fixes / blocked; +- scope compliance; +- findings with severity; +- checks/evidence reviewed; +- required fixes; +- optional follow-ups. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-03-channel-threading-delivery-types.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-03-channel-threading-delivery-types.task.md new file mode 100644 index 0000000..017e91a --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-03-channel-threading-delivery-types.task.md @@ -0,0 +1,84 @@ +--- +task_id: T-043-03 +title: Channel threading and delivery intent/result types +suggested_agent: worker / gpt-5.3-codex +status: READY +write_scope: + - packages/channel-runtime/src/threading.ts + - packages/channel-runtime/src/delivery.ts + - packages/channel-runtime/src/index.ts + - packages/channel-runtime/src/channel-runtime.spec.ts +report_path: .tasks/prt-043-channel-interaction-runtime/T-043-03-report.md +--- + +# T-043-03 Channel threading and delivery intent/result types + +## Goal + +Add provider-neutral threading intent and outbound delivery result-summary contracts to `@dd-bot-platform/channel-runtime`. +This task must keep side effects product-owned: only types and small pure helpers belong here. + +## Context readiness checklist + +Before editing, explicitly gather and record context in the report: +- confirm branch and git status; +- read `.memory-bank/index.md`; +- read `.memory-bank/spec/runtime/channel-runtime-contract.md`; +- read `.memory-bank/spec/runtime/command-framework-contract.md`; +- read `.memory-bank/spec/project/feature-area-boundaries.md`; +- read `.memory-bank/spec/operations/observability-and-incident-diagnostics.md`; +- read `.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md`; +- inspect `packages/channel-runtime/src/document.ts`, `render.ts`, `errors.ts`, `index.ts`, and `channel-runtime.spec.ts`; +- inspect `packages/core/src/control-plane/models.ts` and refs for existing `ChannelRef`/transport vocabulary; +- run searches for `replyThread`, `thread`, `delivery`, `attemptId`, `transportMessageRef`, `ChannelCapabilityMatrix`; +- list assumptions and any blockers before coding. + +Do not code until the context is complete. If the docs or existing code contradict this task, stop and report the blocker. + +## Implementation scope + +Create lean channel-runtime contracts: +- threading config/intent: + - product/channel instance can choose whether to reply in thread or not; + - modes should cover at least `reply_to_inbound`, `new_thread`, and `none`; + - include fallback behavior for unsupported/missing inbound target; + - include optional inbound transport message reference and thread reference slots; +- delivery intent/result summary: + - provider-neutral `OutboundDeliveryIntent` describing channelRef, target, document/format references, threading intent, and correlation ids; + - provider-neutral `OutboundDeliveryResultSummary` with status, attempt id, transport message ref, trace/correlation ids, and safe diagnostics; + - terminal statuses should distinguish delivered / suppressed / failed; +- pure helpers only if useful: + - create default threading intent from config + inbound context; + - classify delivery result terminal success/failure if needed by tests. + +Export the new surface from `packages/channel-runtime/src/index.ts`. + +## Non-goals + +- no provider SDK senders; +- no email header generation or Telegram payload generation; +- no retry queue/orchestration; +- no DB tables/read models; +- no UI/admin; +- no product-specific defaults; +- no command parser/registry/dispatcher in channel-runtime. + +## Tests + +Extend package tests with deterministic coverage: +- default threading config can produce `reply_to_inbound` when inbound ref exists; +- fallback behavior can produce `new_thread` or `none` when inbound ref is missing/unsupported; +- delivery summary classifies delivered as terminal success; +- delivery summary classifies suppressed/failed distinctly; +- public exports expose the new types/helpers without importing product/provider code. + +## Report + +Write `.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md` with: +- summary; +- context readiness evidence: docs read, searches run, files inspected, assumptions/blockers; +- files changed; +- implementation notes and deviations; +- checks run and results; +- risks/follow-ups; +- lessons learned / insights candidates, if any. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md new file mode 100644 index 0000000..ccc1158 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md @@ -0,0 +1,91 @@ +# T-043-03 Report — Channel threading and delivery intent/result types + +## Summary + +Implemented provider-neutral threading and delivery contracts in `@dd-bot-platform/channel-runtime` with pure helpers and deterministic tests: +- added threading config/intent vocabulary with fallback handling; +- added outbound delivery intent/result-summary vocabulary with terminal status classification; +- exported new surface from package public index; +- extended tests for threading fallback and delivery terminal classification behavior. + +## Context readiness + +### Repository and git state +- In-scope repository: `/Users/deksden/Documents/_Projects/bot-platform`. +- Branch: `feature/EP-022-prt-043-channel-interaction-runtime`. +- Pre-work status (before edits): untracked task files only in `.tasks/prt-043-channel-interaction-runtime/`. + +### Docs read +- `.memory-bank/index.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` +- `.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md` + +### Files inspected +- `packages/channel-runtime/src/document.ts` +- `packages/channel-runtime/src/render.ts` +- `packages/channel-runtime/src/errors.ts` +- `packages/channel-runtime/src/index.ts` +- `packages/channel-runtime/src/channel-runtime.spec.ts` +- `packages/core/src/control-plane/models.ts` +- `packages/core/src/control-plane/refs.ts` +- `packages/core/src/runtime/kernel.ts` + +### Searches run +- `rg -n "replyThread" packages/channel-runtime/src packages/core/src` +- `rg -n "thread" packages/channel-runtime/src packages/core/src` +- `rg -n "delivery" packages/channel-runtime/src packages/core/src` +- `rg -n "attemptId" packages/channel-runtime/src packages/core/src` +- `rg -n "transportMessageRef" packages/channel-runtime/src packages/core/src` +- `rg -n "ChannelCapabilityMatrix" packages/channel-runtime/src packages/core/src` + +### Existing seams/helpers/tests found +- Existing `channel-runtime` package already owns pure document and rendering helpers only. +- `CanonicalResponseMetadata` already contains `attemptId`/`transportMessageRef` slots. +- `core` has transport capability vocabulary (`ChannelCapabilityMatrix.replyThreadLinkingFidelity`) and shared `ChannelRef`. +- Existing tests are deterministic node tests in `channel-runtime.spec.ts`, suitable for extension. + +### Assumptions and blockers +- Assumption: `channel-runtime` should stay pure and type-focused; no provider send logic or runtime side effects. +- Assumption: terminal delivery statuses for this task are exactly `delivered | suppressed | failed`. +- Blockers: none found; no doc contradictions requiring stop. + +## Files changed +- `packages/channel-runtime/src/threading.ts` (new) +- `packages/channel-runtime/src/delivery.ts` (new) +- `packages/channel-runtime/src/index.ts` +- `packages/channel-runtime/src/channel-runtime.spec.ts` + +## Implementation notes and deviations +- Added `OutboundThreadingMode` with required modes: `reply_to_inbound`, `new_thread`, `none`. +- Added `OutboundThreadingConfig` + `InboundThreadingContext` + `OutboundThreadingIntent`. +- Added pure helper `createDefaultThreadingIntent(config, inboundContext)`: + - keeps `reply_to_inbound` when inbound message ref exists and reply is supported; + - falls back to configurable `new_thread` or `none` when inbound target missing/unsupported. +- Added `OutboundDeliveryIntent` and `OutboundDeliveryResultSummary` with: + - `channelRef`, target slots, document/format refs, threading intent, correlation refs; + - terminal `status`, `attemptId`, `transportMessageRef`, diagnostics summary. +- Added pure helpers: + - `classifyOutboundDeliveryTerminalState` (`success | suppressed | failure`); + - `isOutboundDeliveryTerminalSuccess`. +- Exported new contracts/helpers from package public index. +- Post-verification fix: removed optional inline `document` from `OutboundDeliveryIntent` after verifier feedback, keeping the delivery seam reference-only as requested by the task packet. + +## Checks run and results +- `pnpm -C packages/channel-runtime build` ✅ +- `node --test packages/channel-runtime/dist/channel-runtime.spec.js` ✅ + - 10 passed, 0 failed. +- Post-verification rerun by orchestrator: + - `pnpm --filter @dd-bot-platform/core typecheck` ✅ + - `pnpm --filter @dd-bot-platform/channel-runtime typecheck` ✅ + - `node --test packages/core/dist/command-framework.spec.js packages/channel-runtime/dist/channel-runtime.spec.js` ✅ + - 18 passed, 0 failed after final command default-deny hardening. + +## Risks and follow-ups +- `OutboundDeliveryTarget` is intentionally generic; product adapters may later require stricter target subtypes. +- `supportsReplyToInbound` is optional in inbound context; adapters should set it explicitly when capability is known to avoid ambiguity. + +## Lessons learned / insights candidates +- `channel-runtime` can extend safely with provider-neutral interaction contracts while preserving thin-seam package boundaries and deterministic pure-helper tests. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.md b/.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.md new file mode 100644 index 0000000..80a47a0 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.md @@ -0,0 +1,26 @@ +# T-043-03 Verification — Channel threading and delivery intent/result types + +## Verdict +accepted after orchestrator fix + +## Scope compliance +- `packages/channel-runtime/src/threading.ts`, `packages/channel-runtime/src/delivery.ts`, `packages/channel-runtime/src/index.ts`, and `packages/channel-runtime/src/channel-runtime.spec.ts` are present and stay pure/provider-neutral. +- No product code, DB code, UI code, provider SDK sender, retry orchestration, or command parser/registry/dispatcher entered `channel-runtime`. +- Public exports are wired through the package index and the package still builds/tests cleanly. + +## Findings +- P2 — resolved by orchestrator: `packages/channel-runtime/src/delivery.ts` no longer imports `CanonicalResponseDocument` and `OutboundDeliveryIntent` is reference-only (`documentRef` / `renderedMessageRef` / format + correlation fields). + +## Checks and evidence reviewed +- Read required context: `.memory-bank/index.md`, `.memory-bank/spec/runtime/channel-runtime-contract.md`, `.memory-bank/spec/runtime/command-framework-contract.md`, `.memory-bank/spec/project/feature-area-boundaries.md`, `.memory-bank/spec/operations/observability-and-incident-diagnostics.md`, and `.tasks/prt-043-channel-interaction-runtime/001-task-packet-template.md`. +- Inspected actual files: `packages/channel-runtime/src/document.ts`, `packages/channel-runtime/src/render.ts`, `packages/channel-runtime/src/errors.ts`, `packages/channel-runtime/src/index.ts`, `packages/channel-runtime/src/channel-runtime.spec.ts`, `packages/core/src/control-plane/models.ts`, `packages/core/src/control-plane/refs.ts`, and `packages/core/src/runtime/kernel.ts`. +- Ran focused searches for `replyThread`, `thread`, `delivery`, `attemptId`, `transportMessageRef`, and `ChannelCapabilityMatrix`. +- Reviewed `git diff -- packages/channel-runtime/src packages/core/src/index.ts` and checked the untracked/new files in the working tree. +- Verified package build and tests locally: `pnpm -C packages/channel-runtime build` and `node --test packages/channel-runtime/dist/channel-runtime.spec.js` both passed. + +## Required fixes +- none after orchestrator fix. + +## Optional follow-ups +- Track the unrelated `packages/core/src/index.ts` / `packages/core/src/command-framework` changes separately if they belong to a different task, so this verification stays scoped to T-043-03. +- If the delivery seam is meant to stay ultra-thin, consider narrowing `OutboundDeliveryTarget` and `OutboundDeliveryDiagnosticsSummary` to the smallest fields needed by downstream adapters. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.task.md new file mode 100644 index 0000000..338ff21 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.task.md @@ -0,0 +1,51 @@ +--- +task_id: T-043-03-verification +title: Verify channel threading and delivery contracts +suggested_agent: explorer / gpt-5.4-mini +status: READY +write_scope: + - .tasks/prt-043-channel-interaction-runtime/T-043-03-verification.md +--- + +# T-043-03 Verification + +## Goal + +Verify the implementation of `T-043-03` against the task packet, report, actual code, and protocol boundaries. + +## Required context readiness + +Before judging, read and record: +- `.tasks/prt-043-channel-interaction-runtime/T-043-03-channel-threading-delivery-types.task.md`; +- `.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md`; +- `.memory-bank/spec/runtime/channel-runtime-contract.md`; +- `.memory-bank/spec/project/feature-area-boundaries.md`; +- `packages/channel-runtime/src/threading.ts`; +- `packages/channel-runtime/src/delivery.ts`; +- `packages/channel-runtime/src/index.ts`; +- `packages/channel-runtime/src/channel-runtime.spec.ts`. + +Also inspect `git diff -- packages/channel-runtime/src` and run focused searches for product/channel/provider leaks. + +## Review focus + +Check: +- channel-runtime stays pure and provider-neutral; +- no command parser/registry/dispatcher entered channel-runtime; +- no DB, UI, provider SDK sender, retry orchestration, or product defaults slipped in; +- threading covers `reply_to_inbound`, `new_thread`, `none`; +- fallback behavior for missing/unsupported inbound target is deterministic; +- delivery summary distinguishes delivered/suppressed/failed; +- result summary uses safe diagnostics only; +- tests cover the requested cases; +- code is lean and not over-abstracted. + +## Output + +Write `.tasks/prt-043-channel-interaction-runtime/T-043-03-verification.md` with: +- verdict: accepted / needs fixes / blocked; +- scope compliance; +- findings with severity; +- checks/evidence reviewed; +- required fixes; +- optional follow-ups. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-05-docoved-inventory.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-05-docoved-inventory.task.md new file mode 100644 index 0000000..564a157 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-05-docoved-inventory.task.md @@ -0,0 +1,73 @@ +# T-043-05 Docoved Command / Email / Threading Inventory + +## Owner / model guidance +- Suggested model: `gpt-5.4-mini` +- Parallelism: can run in parallel with platform package-boundary and SellerAgent inventory tasks. +- Write scope: report only. Do not edit repo code/docs. + +## Goal +Inventory Docoved command, email, Telegram, rendering, and threading seams needed for PRT-043 adoption. Define the minimum Docoved first parity command set and identify implementation risks. + +## Context to collect before work +Required docs in `bot-platform`: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` + +Required docs in `/Users/deksden/Documents/_Projects/docoved-agent`: +- `.memory-bank/index.md` +- `.memory-bank/spec/operations/docoved-channel-adapter-contract.md` +- `.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md` +- relevant scenario index/docs around `SCN-201`, `SCN-202`, `SCN-204`, `SCN-211` if present. + +Required code searches in `/Users/deksden/Documents/_Projects/docoved-agent`: +- `rg -n "commandAccessPolicy|TelegramCommand|resolveTelegramCommand|direct command|/sources|/help|sources|Message-ID|In-Reply-To|References|reply_to_message|ask@beta-mail|CanonicalResponseDocument|channel-runtime" scripts src apps packages .memory-bank` +- inspect `scripts/_support/docoved-telegram-command-runtime.ts` if present; +- inspect `scripts/docoved-direct-command-proof.ts` if present; +- inspect `scripts/docoved-beta-telegram-commands.ts` if present; +- inspect email runtime/proof scripts found by search. + +## Context readiness checklist +Before recommendations, the subagent must: +- inspect branch/status for `docoved-agent` and `bot-platform`; +- read required docs; +- run required searches; +- identify existing Telegram command path, email command/thread path, and canonical rendering path; +- identify existing tests/proofs/scripts that can be reused; +- list assumptions and unknowns; +- decide whether Docoved adoption is ready or blocked. + +## What to do +- Identify current Docoved command surfaces and policy fields. +- Recommend the first parity command set for email/Telegram. +- Identify ordinary-email-not-command safeguards needed. +- Identify unauthorized sender/user denial paths. +- Identify threading requirements for `ask@beta-mail.docoved.pro` and Telegram replies. +- Identify exact files likely to change in Docoved adoption. +- Identify local and beta checks/proofs required. + +## What not to do +- Do not edit files. +- Do not move Docoved business logic into platform. +- Do not suggest mutation commands for the first proof unless already unavoidable. +- Do not assume scenario ids exist without checking. + +## Risks and thin points +- Email command parsing must not steal ordinary legal/document questions. +- `commandAccessPolicy` must not become a second writable authority unless Docoved declares it canonical. +- Threading fallback must not silently break `Re:` behavior. + +## Completion criteria +- Report identifies minimum command set, files, checks, risks, and blockers. + +## Report format +Write `.tasks/prt-043-channel-interaction-runtime/T-043-05-report.md` with: +- summary; +- context readiness; +- current Docoved seams; +- first parity command recommendation; +- threading/rendering/email risks; +- likely files to change; +- tests/local proofs; +- hosted beta proof plan; +- blockers/follow-ups. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-05-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-05-report.md new file mode 100644 index 0000000..1d7720f --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-05-report.md @@ -0,0 +1,96 @@ +# T-043-05 Docoved Command / Email / Threading Inventory + +## Summary +- Context readiness is complete: I inspected both repo statuses, read the required protocol/spec docs, ran the required Docoved searches, and inspected the live command/email/threading seams. +- Verdict: **blocked for implementation**, but **ready for handoff planning**; the inventory is sufficient to define the first parity slice, yet the live Docoved code still lacks the shared command-dispatch seam for email and the Telegram inbound reply-link normalization needed for full parity. + +## Context Readiness +- Repo status: `bot-platform` is on `feature/EP-022-prt-043-channel-interaction-runtime`; `docoved-agent` is on `main...origin/main`. +- Repo-local instructions: no nested `AGENTS.md` files were found in either repo tree. +- Required docs read: + - `bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + - `bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` + - `bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` + - `bot-platform/.memory-bank/spec/runtime/command-framework-contract.md` + - `bot-platform/.memory-bank/spec/runtime/channel-runtime-contract.md` + - `docoved-agent/.memory-bank/index.md` + - `docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` + - `docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md` + - `docoved-agent/.memory-bank/spec/runtime/docoved-acceptance-scenarios-and-host-contract.md` + - `docoved-agent/.memory-bank/scenarios/index.md` + - `docoved-agent/.memory-bank/scenarios/scenario-matrix.md` + - `docoved-agent/.memory-bank/guides/reference/docoved-hosted-live-channel-acceptance-playbook.md` + - `docoved-agent/.memory-bank/spec/operations/docoved-email-channel-binding-and-hosted-acceptance.md` +- Required searches completed in `docoved-agent` for command policy, Telegram commands, reply/thread metadata, `ask@beta-mail.docoved.pro`, `CanonicalResponseDocument`, and `channel-runtime`. + +## Current Docoved Seams +- Command-policy seam exists, but it is still product-local and legacy-shaped: `docoved-agent/apps/server/src/channels/docoved-command-policy.ts:10-68` maps `commandAccessPolicy` into a docoved Telegram surface and hardcodes `allowDebugCommands: true`. +- Telegram command catalog/projection seam exists: `docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts:17-260` defines the Docoved surface, actor classes, capabilities, and command lists; `docoved-agent/apps/server/src/telegram/command-projections.ts` consumes that same catalog for menu sync. +- Live Telegram answer webhook still does not parse commands; it treats inbound text as an answer question and only uses reply parameters on outbound send: `docoved-agent/apps/api/src/docoved-telegram-webhook-routes.ts:417-520`. +- Live email webhook already carries the threading seam the protocol wants: it preserves `Message-ID` / `In-Reply-To` / `References`, resolves reply targets, and sends `Re:` from `ask@beta-mail.docoved.pro`: `docoved-agent/apps/api/src/docoved-email-webhook-routes.ts:547-685`. +- Email-channel binding docs already require the same mailbox for inbound, `From`, and `Reply-To`, and call out `SCN-202` as the hosted beta readiness gate: `docoved-agent/.memory-bank/spec/operations/docoved-email-channel-binding-and-hosted-acceptance.md:73-102`. +- Channel-runtime adoption is already documented locally in Docoved: the mapping guide says Docoved owns the `DocovedAnswerArtifact -> CanonicalResponseDocument` mapping and that the current email/Telegram renderers stay thin over the same artifact. +- Scenario coverage is partially landed: `SCN-201` and `SCN-204` exist as flat docs, while `SCN-202` and `SCN-211` are only anchored in the hub/matrix and are not yet flat scenario docs. + +## First Parity Command Set +- Recommended minimum parity set: `/help`, `/sources`, `/status`, `/report`. +- Adjacent read-only diagnostics to phase in next: `/whoami`, then `/inspect` and `/context` if the first proof needs them. +- Rationale: + - `help` is the safest discovery/deny path. + - `sources` matches the existing compact explainability surface. + - `status` gives lightweight runtime/readback parity. + - `report` is already exercised by the current proof scripts and is the best bridge to canonical diagnostics. +- Do **not** start with mutation or release-control commands; the protocol itself says the first parity slice should stay diagnostics/source/help-style. + +## Threading / Rendering / Email Risks +- Email command recognition is still absent in the live webhook; today every verified inbound email is routed straight into `docoved_answer`, so ordinary email questions are not yet protected by a command parser/dispatcher boundary. +- Telegram reply-link ingestion is still incomplete: the live webhook sends outbound replies with `reply_parameters`, but the inbound message path does not normalize `reply_to_message` into canonical message lineage yet. +- `commandAccessPolicy` remains a legacy migration input unless the product memory bank explicitly declares it canonical writable authority; the current `allowDebugCommands: true` default makes it easy for policy drift to become a second authority. +- The `channel-runtime` contract explicitly excludes commands in first-wave scope, so any implementation must keep command dispatch in the command-framework seam and avoid creating parallel `ChannelCommand*` ownership. +- `SCN-202` email proof depends on `ask@beta-mail.docoved.pro` being the inbound, `From`, and `Reply-To` address with `Re:` threading preserved; that is already documented, but it remains an acceptance gate rather than a generalized command solution. + +## Likely Files To Change +- `docoved-agent/apps/api/src/docoved-email-webhook-routes.ts` +- `docoved-agent/apps/api/src/docoved-telegram-webhook-routes.ts` +- `docoved-agent/apps/server/src/channels/docoved-command-policy.ts` +- `docoved-agent/apps/server/src/telegram/command-projections.ts` +- `docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts` +- `docoved-agent/scripts/docoved-beta-telegram-commands.ts` +- `docoved-agent/scripts/docoved-beta-telegram-command-proof.ts` +- `docoved-agent/scripts/docoved-direct-command-proof.ts` +- `docoved-agent/scripts/docoved-beta-email-runtime-proof.ts` +- `docoved-agent/scripts/docoved-scn202-live-email.ts` +- likely doc updates in `docoved-agent/.memory-bank/scenarios/index.md` and `docoved-agent/.memory-bank/scenarios/scenario-matrix.md` if the SCN-202/SCN-211 anchors need promotion. + +## Checks / Proofs +- Local/package proofs to keep around for the next phase: + - `pnpm docoved:verify:local` + - command proof scripts in `docoved-agent/scripts/docoved-direct-command-proof.ts` and `docoved-agent/scripts/docoved-beta-telegram-command-proof.ts` + - email runtime proof scripts in `docoved-agent/scripts/docoved-beta-email-runtime-proof.ts` and `docoved-agent/scripts/docoved-scn202-live-email.ts` +- Hosted beta proofs required by the current Docoved docs: + - `pnpm docoved:preflight:beta --json` + - `pnpm docoved:verify:beta:corpus` + - `pnpm docoved:bundle:beta` + - `pnpm docoved:packet:beta:scn201` + - `pnpm docoved:packet:beta:scn202` + - `pnpm docoved:sync:beta:telegram --inspect` + - `pnpm docoved:sync:beta:telegram-commands --status` + - `pnpm docoved:inspect:beta:email` + - `pnpm docoved:probe:beta:telegram --chat-id --text "..."` when a real tester chat id is available + +## Hosted Beta Plan +- Telegram lane: prove the final live command/runtime behavior only after the command dispatcher exists in the live path; keep menu sync derived from policy, not authoritative. +- Email lane: keep the `ask@beta-mail.docoved.pro` reply/thread contract as the acceptance proof and add command handling only when the same normalized command path exists for email. +- Archive the final beta evidence only after the local proofs, the hosted corpus preflight, and the live lane reruns all agree. + +## Assumptions / Unknowns +- I assumed the first parity set should stay read-only and start with `/help`, `/sources`, `/status`, and `/report`; `/whoami`, `/inspect`, and `/context` look like the next diagnostics slice. +- It is still unknown whether `commandAccessPolicy` is meant to remain only migration input or become canonical writable authority for Docoved. +- It is still unknown whether SCN-202 and SCN-211 should stay hub-only anchors or be promoted into flat scenario docs before implementation closes. +- It is still unknown whether email command parsing should enter through the same dispatcher immediately or be bridged product-locally until the framework seam lands. + +## Blockers / Follow-ups +- Blocker 1: no live email command parser/dispatcher path exists yet in `apps/api/src/docoved-email-webhook-routes.ts`. +- Blocker 2: Telegram inbound reply-link normalization is missing from `apps/api/src/docoved-telegram-webhook-routes.ts`. +- Blocker 3: the exact first parity command set still needs a decision packet before implementation starts. +- Blocker 4: the command-framework implementation/export location and threading/delivery intent ownership gates from PRT-043 are still open. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-06-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-06-report.md new file mode 100644 index 0000000..3ad143e --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-06-report.md @@ -0,0 +1,129 @@ +# T-043-06 SellerAgent Command / Delivery Inventory Report + +## Summary +- SellerAgent already has the core seams needed for PRT-043-style command adoption: actor-aware Telegram command gating, derived menu projection, verified Telegram binding resolution, release readback/control, and reply-delivery summary models. +- The narrow first adoption subset should stay read-only: actor diagnostics, runtime/context readback, and release readback. Release-control mutations and model-policy mutation should wait for a later wave. +- Context readiness is **blocked for broad adoption / mutation work**, but **ready for a scoped read-only inventory/proof plan**. + +## Context Readiness +- Repo status checked on both branches: `bot-platform` and `seller-agent` are clean on their current feature branches. +- Required docs read: + - `bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:1` + - `bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md:1` + - `bot-platform/.memory-bank/spec/runtime/command-framework-contract.md:26` + - `bot-platform/.memory-bank/spec/runtime/channel-runtime-contract.md:31` + - `bot-platform/.memory-bank/spec/project/feature-area-boundaries.md:26` + - `bot-platform/.memory-bank/spec/operations/observability-and-incident-diagnostics.md:35` + - `bot-platform/.memory-bank/spec/operations/deployment-architecture.md:26` + - `bot-platform/.memory-bank/spec/operations/hosted-beta-acceptance-contract.md:22` + - `seller-agent/.memory-bank/index.md:28` + - `seller-agent/.memory-bank/plans/protocols/PRT-007-telegram-privileged-command-surface-bot-level-release-control-and-runtime-diagnostics.md:1` + - `seller-agent/.memory-bank/scenarios/SCN-053-telegram-observed-user-capture-and-employee-verification-flow.md:1` + - `seller-agent/.memory-bank/scenarios/SCN-168-channel-topology-and-release-assignment-resolution.md:1` + - `seller-agent/.memory-bank/guides/reference/telegram-direct-bot-command-catalog.md:20` + - `seller-agent/.memory-bank/guides/explanation/telegram-bot-integration-model.md:20` + - `seller-agent/.memory-bank/spec/operations/production-rollout-runbook.md:31` +- Required searches run in `seller-agent` for command, actor, release, and delivery seams. +- No targeted tests were found for the Telegram command/projection seam; inventory is source- and docs-driven. + +### Assumptions / Unknowns +- `seller-agent/.memory-bank/spec/scenarios/hosted-beta-execution-model.md` is not present; hosted-beta proof planning must currently rely on the production rollout runbook plus scenario matrices. +- Current SellerAgent actor modeling is still coarse (`external_customer`, `employee`, `system_admin`) and must be mapped to richer PRT-043 actor classes rather than assumed equivalent. +- `/use_model_policy` exists in SellerAgent, but it is adjacent to this task and should not be treated as part of the first release-control proof unless separately justified. + +## Current SellerAgent Seams +- `packages/core/src/telegram-commands.ts:325` owns the command catalog and descriptions, including release readback/control and deep-debug commands. +- `packages/core/src/telegram-commands.ts:625` resolves Telegram command access from verified bindings, workspace role, and system-admin status. +- `packages/core/src/telegram-commands.ts:470` and `:524` derive allowed commands from actor/access policy; menu/help is projection, not authority. +- `packages/core/src/telegram-commands.ts:1248` / `:1266` load business-profile versions/releases and current release resolution. +- `packages/core/src/telegram-commands.ts:2243` / `:2285` render `/versions`, `/releases`, and `/current`. +- `packages/core/src/telegram-commands.ts:2487` / `:2598` / `:2705` implement `/use_release` preview and `/confirm use_release` mutation. +- `apps/server/src/telegram/command-projections.ts:77` derives command projection state and sync status from `resolveTelegramCommandAccess`. +- `apps/server/src/telegram/index.ts:1323` routes direct slash commands and passes in the Docoved surface and access context. +- `apps/server/src/channels/docoved-command-policy.ts:42` keeps Docoved command policy separate, with `allowDirectCommands` and `allowDebugCommands`. +- `packages/api-contract/src/operations.ts:1101` defines the Telegram actor-class schema and the Telegram integration / binding / release-assignment schemas. +- `packages/api-contract/src/conversations.ts:406` and `:469` define delivery outcome and delivery summary shapes. + +## Command Classification + +### Read-only diagnostics / readback +- `/start`, `/help`, `/whoami`, `/status`, `/context`, `/pipeline`, `/why`, `/inspect` +- `/versions`, `/releases`, `/current` +- Optional adjacent read-only diagnostics: `/policy_current`, `/policy_role`, `/policy_failure`, `/policy_fallbacks` + +### Product workflow mutation +- `/new` is an operational session reset / fresh test session, not a release-control action. + +### Release-control mutation +- `/use_release` +- `/confirm use_release` +- `/use_model_policy` +- `/confirm use_model_policy` + +### Debug-only +- `/last`, `/trace`, `/analysis`, `/decision`, `/artifacts`, `/integration` + +### Minimum first SellerAgent adoption subset +- First proof should use only the read-only surface: `/start`, `/help`, `/whoami`, `/status`, `/context`, `/pipeline`, `/why`, `/inspect`, `/versions`, `/releases`, `/current`. +- Keep `/use_release`, `/confirm`, `/use_model_policy`, and `/new` out of the first proof unless a later gate explicitly needs them. +- If a broader diagnostic proof is desired, add `/policy_*` next; keep deep-debug commands out until the read-only subset is stable. + +## Actor / Capability Mapping +- Current SellerAgent `external_customer` is the closest match to PRT-043 `external_unknown_user` for unverified Telegram direct chat. +- Verified Telegram bindings plus workspace roles map to `verified_employee` / `workspace_admin` / `system_admin` rather than remaining in a single `employee` bucket. +- Existing SellerAgent capability strata already separate: + - diagnostics readback + - release readback + - release assignment + - model-policy readback / assignment + - deep debug +- `allowDebugCommands` is still a transport-level switch, not a substitute for capability-aware actor classes. +- Telegram menu projection remains derived from server policy; it should not grant authority. + +## Delivery Field Classification + +### Shared-candidate fields +- `ConversationReplyDeliveryExecutionOutcome` and `ConversationReplyDeliverySummary` are good cross-channel candidates because they summarize delivery verdict, counts, timing, and bounded reasons. +- Candidate shared fields include: `kind` / `verdict`, `planId`, `totalSteps`, `sentSteps`, `suppressedSteps`, `failedSteps`, `pendingSteps`, `lastDispatchAt`, `reason`, `reasonCode`, `sentStepCount`, `simulated`, and `supersededByMessageId`. +- `OutboundDispatch` fields such as `channelKind`, `deliveryStatus`, `planId`, `stepId`, `sequence`, `stepType`, `transportMessageRef`, and `reason` also look provider-neutral enough to remain shared. + +### SellerAgent-only / product-owned fields +- Job and conversation records such as `businessProfileSlug`, `integrationKey`, `channelAccountId`, `channelThreadRef`, `traceId`, `generatedMessageId`, `attemptCount`, `lastError`, and the job timestamps should stay product-owned. +- `replyToMessageId`, `transportReplyToMessageRef`, and `transportReferenceMessageRefs` remain product conversation/threading details for now, even though they are strong candidates for later threading-intent abstraction. +- The current `conversationReplyJobSummary` / `conversationReplyBurstSummary` shapes are product records, not framework-shared contracts. + +## Likely Files To Change +- `packages/core/src/telegram-commands.ts` +- `apps/server/src/telegram/command-projections.ts` +- `apps/server/src/telegram/index.ts` +- `apps/server/src/channels/docoved-command-policy.ts` +- `packages/api-contract/src/operations.ts` +- `packages/api-contract/src/conversations.ts` +- Possible support follow-ups: + - `packages/core/src/system/handlers.ts` + - `apps/server/src/business/operation-handlers.ts` + +## Tests / Local Proofs +- No targeted unit tests were found for the Telegram command/projection seam. +- If implementation starts, the first local checks should be: + - `pnpm typecheck` or `pnpm check` in `seller-agent` + - focused command-projection proof for `/help`, `/whoami`, `/status`, `/current` + - release readback proof against a local Telegram integration + - observed-user/binding proof for verified versus unverified actor behavior + - `pnpm verify:security` and `pnpm verify:security:live` when release/security boundaries are touched +- `SCN-053` is the best local operator/auth anchor; `SCN-168` is the best local release-assignment anchor. + +## Hosted Beta Proof Plan +- Use the stable beta pair only; do not count preview aliases as acceptance evidence. +- Prove that: + - unverified users stay on the public-safe surface; + - verified employees get the read-only diagnostics/readback subset; + - `/current` reflects explicit integration assignment over profile default; + - menu projection stays derived and never widens authority. +- Add `/use_release` / `/confirm` only in a second proof after the read-only subset is stable and the release-control gate is explicitly approved. +- Keep delivery/thread evidence tied to real Telegram reply behavior and traceable delivery summaries. + +## Blockers / Follow-ups +- Broad SellerAgent adoption is blocked until the shared PRT-043 contracts stop being just draft guidance and the implementation gates are resolved. +- The missing SellerAgent hosted-beta execution doc should be added or intentionally retired before claiming a final beta-proof path. +- After the read-only wave is accepted, decide whether `/policy_*`, `/new`, and release-control mutation commands belong in the next SellerAgent slice or stay separate. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-06-selleragent-inventory.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-06-selleragent-inventory.task.md new file mode 100644 index 0000000..959adcb --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-06-selleragent-inventory.task.md @@ -0,0 +1,74 @@ +# T-043-06 SellerAgent Command / Delivery Inventory + +## Owner / model guidance +- Suggested model: `gpt-5.4-mini` +- Parallelism: can run in parallel with platform package-boundary and Docoved inventory tasks. +- Write scope: report only. Do not edit repo code/docs. + +## Goal +Inventory SellerAgent command, actor/access, Telegram menu, release-control, and delivery outcome seams needed for PRT-043 adoption. Define the minimum first SellerAgent adoption subset. + +## Context to collect before work +Required docs in `bot-platform`: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` + +Required docs in `/Users/deksden/Documents/_Projects/seller-agent`: +- `.memory-bank/index.md` +- `.memory-bank/plans/protocols/PRT-007-telegram-privileged-command-surface-bot-level-release-control-and-runtime-diagnostics.md` +- `.memory-bank/scenarios/SCN-053-telegram-observed-user-capture-and-employee-verification-flow.md` +- relevant deployment/ops docs if adoption affects beta proof. + +Required code searches in `/Users/deksden/Documents/_Projects/seller-agent`: +- `rg -n "TelegramCommand|commandAccessPolicy|allowDirectCommands|allowDebugCommands|syncTelegramCommands|actorClass|system_admin|employee|external_customer|/use_release|release-control|ConversationReplyDelivery|deliveryOutcome|reply_to|thread" packages apps .memory-bank` +- inspect `packages/core/src/telegram-commands.ts` if present; +- inspect `apps/server/src/telegram/index.ts`; +- inspect `apps/server/src/channels/docoved-command-policy.ts` if present; +- inspect `packages/api-contract/src/operations.ts`; +- inspect `packages/api-contract/src/conversations.ts`. + +## Context readiness checklist +Before recommendations, the subagent must: +- inspect branch/status for `seller-agent` and `bot-platform`; +- read required docs; +- run required searches; +- identify existing command catalog, actor resolver, menu projection, release-control commands, and delivery summary models; +- identify existing tests/proofs/scenarios that can be reused; +- list assumptions and unknowns; +- decide whether SellerAgent adoption is ready or blocked. + +## What to do +- Classify SellerAgent commands into read-only diagnostics/readback, release-control mutation, product workflow mutation, and debug-only. +- Recommend the minimum first adoption subset. +- Map existing actor/access concepts to PRT-043 actor classes/capability tags. +- Identify delivery outcome fields that are shared candidates versus SellerAgent-only. +- Identify likely files to change in SellerAgent adoption. +- Identify local and hosted beta checks required. + +## What not to do +- Do not edit files. +- Do not move SellerAgent command catalog or release-control semantics into platform. +- Do not include mutation/release-control commands in first proof unless justified. +- Do not assume UI/admin migration is part of PRT-043. + +## Risks and thin points +- Telegram menu projection must remain derived, not authoritative. +- Release-control commands must preserve product permission gates and confirmation flow. +- Existing delivery workflows must not be replaced by generic platform orchestration. + +## Completion criteria +- Report identifies command subset, actor mapping, delivery field classification, files, checks, and blockers. + +## Report format +Write `.tasks/prt-043-channel-interaction-runtime/T-043-06-report.md` with: +- summary; +- context readiness; +- current SellerAgent seams; +- command classification and first subset; +- actor/capability mapping; +- delivery field classification; +- likely files to change; +- tests/local proofs; +- hosted beta proof plan; +- blockers/follow-ups. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-07-docoved-adoption.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-07-docoved-adoption.task.md new file mode 100644 index 0000000..14fe155 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-07-docoved-adoption.task.md @@ -0,0 +1,39 @@ +# T-043-07 Docoved Adoption + +## Goal + +Adopt the PRT-043 platform contracts in `/Users/deksden/Documents/_Projects/docoved-agent` for the first safe Docoved slice: +- consume released or approved bridge version of `@dd-bot-platform/core` / `@dd-bot-platform/channel-runtime`; +- align Docoved command handling with platform command-framework types where it removes drift without moving product command catalog out of Docoved; +- align email/Telegram reply threading with channel-runtime threading intent/result summary contracts; +- document and verify locally; prepare hosted beta proof path. + +## Context readiness checklist + +Before edits, record context in the report: +- Docoved branch/status and git-flow docs; +- `.memory-bank/index.md` and relevant runtime/ops/scenario docs in Docoved; +- platform PRT-043 specs and reports; +- current package dependencies and lockfile state; +- existing Telegram command files, email route files, channel-runtime mapping files, and proof scripts; +- searches for `commandAccessPolicy`, `allowDirectCommands`, `Message-ID`, `In-Reply-To`, `reply_to_message`, `CanonicalResponseDocument`, `@dd-bot-platform`. + +Do not guess. If product adoption is blocked by missing published package version, report the exact blocker and viable bridge/release path. + +## Scope + +Allowed: +- add platform package dependency/version updates required for PRT-043; +- add small adapter/mapping helpers using `@dd-bot-platform/core` command types and `@dd-bot-platform/channel-runtime` threading/delivery types; +- update tests/proofs/scripts if needed; +- update Docoved Memory Bank. + +Non-goals: +- no product command catalog extraction into bot-platform; +- no DB migrations unless already required and documented; +- no provider sender refactor beyond typed intent/result mapping; +- no unrelated Docoved behavior changes. + +## Output + +Write report to `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-07-report.md` with context readiness, changed files, checks, blockers, and beta proof plan. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-07-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-07-report.md new file mode 100644 index 0000000..872accc --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-07-report.md @@ -0,0 +1,118 @@ +# T-043-07 Report — Docoved adoption (PRT-043) + +## Summary +- `PRT-043` full Docoved adoption is **blocked by package release state**: npm exposes only `@dd-bot-platform/core@0.2.0` and `@dd-bot-platform/channel-runtime@0.2.0`, while required command-framework and threading/delivery exports are in `0.3.0` code line. +- Safe product-local work was completed: added explicit Docoved package-surface blocker proof, pinned direct `@dd-bot-platform/core` dependency, and updated Docoved adoption docs/proof metadata without changing live runtime behavior. + +## Context readiness (recorded before edits) + +### 1) Docoved branch/status and git-flow docs +- Repo: `/Users/deksden/Documents/_Projects/docoved-agent` +- Branch/status before edits: `main...origin/main`, clean short status output. +- Git-flow source read: `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/git-flow.md` (feature work should run from `feature/*` branched from `develop`; direct protected-branch push disallowed). +- PRT workspace flow note read: `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/002-git-flow-start.md`. + +### 2) Docoved memory-bank and relevant runtime/ops/scenario docs +- Read: + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/index.md` + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md` + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-email-channel-binding-and-hosted-acceptance.md` + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-acceptance-scenarios-and-host-contract.md` + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/scenarios/index.md` + +### 3) Platform PRT-043 specs and reports +- Read: + - `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/runtime/command-framework-contract.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/runtime/channel-runtime-contract.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/003-pre-code-gate-decision.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-02-report.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-03-report.md` + - `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-05-report.md` + +### 4) Current dependencies and lockfile state (before edits) +- Root `docoved-agent/package.json` initially had direct dependency only: + - `@dd-bot-platform/channel-runtime: 0.2.0` +- `pnpm-lock.yaml` already contained transitive entries: + - `@dd-bot-platform/core@0.2.0` + - `@dd-bot-platform/channel-runtime@0.2.0` +- Installed package surface inspection showed: + - `core@0.2.0` exports runtime-only symbols; no command-framework exports. + - `channel-runtime@0.2.0` exports canonical document/render helpers only; no threading/delivery exports. + +### 5) Existing command/email/channel-runtime/proof files inspected +- Telegram command/runtime: + - `/Users/deksden/Documents/_Projects/docoved-agent/apps/server/src/channels/docoved-command-policy.ts` + - `/Users/deksden/Documents/_Projects/docoved-agent/apps/server/src/telegram/command-projections.ts` + - `/Users/deksden/Documents/_Projects/docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts` +- Email and Telegram routes: + - `/Users/deksden/Documents/_Projects/docoved-agent/apps/api/src/docoved-email-webhook-routes.ts` + - `/Users/deksden/Documents/_Projects/docoved-agent/apps/api/src/docoved-telegram-webhook-routes.ts` +- Channel-runtime mapping proof: + - `/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-channel-runtime-adoption-proof.ts` + +### 6) Required searches run in docoved-agent +- `rg -n "commandAccessPolicy|allowDirectCommands|Message-ID|In-Reply-To|reply_to_message|CanonicalResponseDocument|@dd-bot-platform"` +- Results confirmed: + - command policy + projection seams exist; + - email route preserves `Message-ID`/`In-Reply-To`/`References`; + - Telegram route sends reply params but has no shared PRT-043 threading intent types; + - only `CanonicalResponseDocument` usage is in local proof script; + - no `@dd-bot-platform/core` imports existed pre-edit. + +## Blocker and bridge/release path + +### Exact blocker (confirmed) +- `npm view` on 2026-04-26 returned only `0.2.0` for both packages: + - `@dd-bot-platform/core`: latest `0.2.0` + - `@dd-bot-platform/channel-runtime`: latest `0.2.0` + - `@dd-bot-platform/channel-runtime@0.3.0` -> `E404` +- `bot-platform` source has required contracts at `0.3.0`: + - `/Users/deksden/Documents/_Projects/bot-platform/packages/core/package.json` + - `/Users/deksden/Documents/_Projects/bot-platform/packages/channel-runtime/package.json` + - commit with these contracts: `d744e06`. +- Therefore Docoved cannot yet adopt published command-framework + threading/delivery contracts directly by semver. + +### Viable bridge/release path +1. **Preferred release path**: publish `@dd-bot-platform/core@0.3.0` and `@dd-bot-platform/channel-runtime@0.3.0` from `bot-platform` commit `d744e06` (or later equivalent) via normal package release workflow. +2. **Temporary bridge path (only if explicitly approved)**: consume immutable tarball artifacts built from the same commit, pin exact checksums in `docoved-agent/pnpm-lock.yaml`, then replace with published semver once npm release is available. + +## Safe product-local changes completed +- Updated `/Users/deksden/Documents/_Projects/docoved-agent/package.json` + - added direct pin `@dd-bot-platform/core: 0.2.0` + - added script `docoved:proof:prt043-package-surface` +- Updated `/Users/deksden/Documents/_Projects/docoved-agent/pnpm-lock.yaml` + - lock sync after dependency pin. +- Added `/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-prt043-package-surface-proof.ts` + - deterministic proof of required PRT-043 export surface and explicit blocker/bridge output. +- Updated `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md` + - added explicit PRT-043 package-surface gate with blocker + release/bridge path. +- Updated `/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-channel-runtime-adoption-proof.ts` + - clarified that current proof scope is PRT-042 mapping and that PRT-043 exports require `0.3.0+`. + +## Checks run +- `pnpm install --lockfile-only` in `docoved-agent` ✅ +- `pnpm install` in `docoved-agent` ✅ +- `pnpm docoved:proof:prt043-package-surface` ❌ (expected blocker output; exits 1 until 0.3.0 contracts are available/pinned via approved bridge) +- `pnpm tsx scripts/docoved-channel-runtime-adoption-proof.ts` ✅ (PRT-042 canonical mapping proof remains green) + +## Scope compliance / non-goals +- No edits in `bot-platform/seller-agent`. +- No rollback/revert of unrelated changes. +- No commit performed. +- No DB/provider sender refactor or product command catalog extraction was done. + +## Hosted beta proof plan after unblock +- Keep first Docoved parity scope read-only (`/help`, `/sources`, `/status`, `/report`) per pre-code gate. +- After package unblock, wire command availability/dispatch types from `@dd-bot-platform/core` and threading/delivery intent/result types from `@dd-bot-platform/channel-runtime`. +- Re-run local proofs first, then hosted beta lane: + - `pnpm docoved:preflight:beta --json` + - `pnpm docoved:verify:beta:corpus` + - `pnpm docoved:packet:beta:scn201` + - `pnpm docoved:packet:beta:scn202` + - threaded email proof for `Re:` + `Message-ID`/`In-Reply-To`/`References` + - Telegram reply-link/runtime proof with real chat evidence. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-08-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-08-report.md new file mode 100644 index 0000000..9426b02 --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-08-report.md @@ -0,0 +1,93 @@ +# T-043-08 SellerAgent Adoption Report + +## Context readiness (recorded before edits) + +### Branch/status and git-flow docs +- SellerAgent repo: `/Users/deksden/Documents/_Projects/seller-agent` +- Branch/status snapshot: `feature/EP-022-wave-17-prt-008-beta-closure...origin/feature/EP-022-wave-17-prt-008-beta-closure` (clean) +- Git-flow doc read: `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/spec/operations/git-flow.md` + +### Memory-bank, protocol, command catalog, current status +- Read: `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/index.md` +- Read: `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/plans/protocols/PRT-007-telegram-privileged-command-surface-bot-level-release-control-and-runtime-diagnostics.md` +- Read: `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/guides/reference/telegram-direct-bot-command-catalog.md` +- Read: `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/plans/current-status-report.md` + +### Platform PRT-043 specs/reports +- Read: `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` +- Read: `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-01-report.md` +- Read: `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-06-report.md` +- Read: `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/006-platform-slice-closeout.md` +- Read task: `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-08-selleragent-adoption.task.md` + +### Current dependencies and lockfile state +- Root manifest inspected: `/Users/deksden/Documents/_Projects/seller-agent/package.json` +- Lockfile inspected: `/Users/deksden/Documents/_Projects/seller-agent/pnpm-lock.yaml` +- Existing platform deps in SellerAgent lock are only `@dd-bot-platform/api-contract@0.2.0` and `@dd-bot-platform/scenario-system@0.2.0` (via `packages/sa-judge`) +- No existing `@dd-bot-platform/core` or `@dd-bot-platform/channel-runtime` dependency in SellerAgent workspace packages + +### Existing implementation anchors inspected +- Telegram command runtime: `/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/telegram-commands.ts` +- Telegram command projection sync: `/Users/deksden/Documents/_Projects/seller-agent/apps/server/src/telegram/command-projections.ts` +- Telegram ingress/fallback delivery handling: `/Users/deksden/Documents/_Projects/seller-agent/apps/server/src/telegram/index.ts` +- Delivery outcome/runtime summary files: + - `/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/conversations/reply-execution.ts` + - `/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/conversations/delivery-summary.ts` + - `/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/conversations/telegram-delivery.ts` + - `/Users/deksden/Documents/_Projects/seller-agent/apps/workflow/workflows/reply-job.ts` +- Proof scripts inspected: `/Users/deksden/Documents/_Projects/seller-agent/scripts/verify-security.mjs`, `/Users/deksden/Documents/_Projects/seller-agent/scripts/verify-security-live.mjs` + +### Required searches run +- `TelegramCommandActorClass`, `commandAccessPolicy`, `actorClass`, `deliveryOutcome`, `/versions`, `/releases`, `/current`, `@dd-bot-platform` across SellerAgent source and lockfile +- Confirmed read-only command subset and delivery outcome seams from T-043-06 inventory remain present + +## Package release blocker and bridge path +- **Blocker (exact):** npm registry currently exposes only `0.2.0` for: + - `@dd-bot-platform/core` + - `@dd-bot-platform/channel-runtime` +- Verification command used: + - `npm view @dd-bot-platform/core version versions --json` + - `npm view @dd-bot-platform/channel-runtime version versions --json` +- PRT-043 command-framework and delivery/threading contracts were landed in bot-platform `0.3.0` code, but `0.3.0` is not yet published; direct package adoption in SellerAgent is blocked. + +### Viable bridge/release path +1. Preferred: publish `@dd-bot-platform/core@0.3.0` and `@dd-bot-platform/channel-runtime@0.3.0` via bot-platform Changesets release flow, then pin these versions in SellerAgent. +2. Temporary local bridge (only for local proof if explicitly approved): pin both packages to the same bot-platform prerelease artifact/commit tarball and document as non-production bridge. + +## Adoption execution decision +- Because package release blocker is active, full dependency adoption is blocked. +- Safe product-local prep that does not require unreleased package publication is still allowed and will be applied below. + +## Changes made +- `seller-agent/packages/core/src/telegram-commands.ts` + - Added `PlatformCommandActorType` plus `mapTelegramAccessToPlatformCommandActorType(...)` to bridge SellerAgent access profile into PRT-043 command-framework actor vocabulary. + - Extended read-only diagnostic command output (`/help`, `/whoami`) with `Framework actor` line derived from the mapping helper. +- `seller-agent/packages/core/src/conversations/delivery-platform-compat.ts` (new) + - Added safe product-local compatibility mapping for SellerAgent delivery outcomes/summaries to a channel-runtime-like terminal delivery summary shape: + - `mapDeliveryOutcomeToPlatformDeliveryCompatSummary(...)` + - `mapDeliverySummaryToPlatformDeliveryCompatSummary(...)` + - Mapping is summary-only; no workflow/job state replacement. +- `seller-agent/packages/core/src/index.ts` + - Exported the new command-actor and delivery-compat helpers. +- `seller-agent/apps/server/src/telegram/index.ts` + - Added `platformDeliverySummary` into partial-delivery failure details via the new compat mapper. + - Existing delivery behavior and terminal status logic are unchanged. + +### Dependency decision for this task +- Did **not** add `@dd-bot-platform/core` / `@dd-bot-platform/channel-runtime` to SellerAgent yet, because required `0.3.0` contracts are not published in npm. +- No lockfile dependency update was made for blocked package adoption. + +## Local checks +- `pnpm --filter @selleragent/core typecheck` ✅ +- `pnpm --filter @selleragent/core build && pnpm --filter @selleragent/server typecheck` ✅ +- Note: direct `@selleragent/server` typecheck before rebuilding `@selleragent/core` failed due stale `core/dist` export map; resolved by building `@selleragent/core` first. + +## Hosted beta proof path (first safe slice) +- Keep first proof on read-only command subset only: `/start`, `/help`, `/whoami`, `/status`, `/context`, `/pipeline`, `/why`, `/inspect`, `/versions`, `/releases`, `/current`. +- Verify unverified vs verified actor separation and policy-derived command visibility. +- Verify release readback (`/current`) remains read-only and reflects integration-level assignment precedence. +- Keep `/use_release`, `/confirm`, `/use_model_policy`, and deep-debug mutation/operational expansion out of first proof. + +## Notes +- `bot-platform/docoved-agent` was not touched. +- No commit will be created. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-08-selleragent-adoption.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-08-selleragent-adoption.task.md new file mode 100644 index 0000000..9b606cc --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-08-selleragent-adoption.task.md @@ -0,0 +1,38 @@ +# T-043-08 SellerAgent Adoption + +## Goal + +Adopt the PRT-043 platform contracts in `/Users/deksden/Documents/_Projects/seller-agent` for the first safe SellerAgent slice: +- consume released or approved bridge version of `@dd-bot-platform/core` / `@dd-bot-platform/channel-runtime`; +- align read-only/diagnostic Telegram command access with platform command-framework types where useful; +- map SellerAgent delivery outcome summaries to channel-runtime delivery result summary without replacing product workflow state; +- document and verify locally; prepare hosted beta proof path. + +## Context readiness checklist + +Before edits, record context in the report: +- SellerAgent branch/status and git-flow docs; +- `.memory-bank/index.md`, PRT-007, command catalog docs, current status report; +- platform PRT-043 specs and reports; +- current package dependencies and lockfile state; +- existing `packages/core/src/telegram-commands.ts`, workflow delivery outcome files, proof scripts; +- searches for `TelegramCommandActorClass`, `commandAccessPolicy`, `actorClass`, `deliveryOutcome`, `/versions`, `/releases`, `/current`, `@dd-bot-platform`. + +Do not guess. If adoption is blocked by missing package version, report exact blocker and viable bridge/release path. + +## Scope + +Allowed: +- add platform package dependency/version updates required for PRT-043; +- add small adapter/mapping helpers using `@dd-bot-platform/core` command types and `@dd-bot-platform/channel-runtime` delivery types; +- update tests/proofs/docs. + +Non-goals: +- no mutation/release-control behavior rewrite; +- no product command catalog extraction into bot-platform; +- no provider sender/queue refactor; +- no broad SellerAgent runtime replacement. + +## Output + +Write report to `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-08-report.md` with context readiness, changed files, checks, blockers, and beta proof plan. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-09-release-closure.task.md b/.tasks/prt-043-channel-interaction-runtime/T-043-09-release-closure.task.md new file mode 100644 index 0000000..8cc62ec --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-09-release-closure.task.md @@ -0,0 +1,35 @@ +# T-043-09 Release And Closure + +## Goal + +Complete PRT-043 release/closure evidence for `/Users/deksden/Documents/_Projects/bot-platform`: +- verify package release path; +- ensure `@dd-bot-platform/core` and `@dd-bot-platform/channel-runtime` versioning/publishing path is correct; +- update runbook/docs if stale; +- define/verify CI and hosted beta closure evidence for product adoption. + +## Context readiness checklist + +Before edits/reporting: +- read platform npm release runbook and workflow; +- inspect `scripts/publish-private-packages.mjs`; +- inspect current npm versions; +- inspect current branch/PR/main status; +- inspect PRT-043 implementation plan and closeout docs; +- identify whether workflow release or maintainer fallback is possible. + +## Scope + +Allowed: +- update stale release docs; +- run local release readiness checks; +- create reports/evidence; +- recommend exact merge/publish steps if credentials/workflows block automation. + +Non-goals: +- do not publish ad hoc from dirty worktree; +- do not merge/publish without green checks and documented evidence. + +## Output + +Write report to `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/T-043-09-report.md`. diff --git a/.tasks/prt-043-channel-interaction-runtime/T-043-09-report.md b/.tasks/prt-043-channel-interaction-runtime/T-043-09-report.md new file mode 100644 index 0000000..01ea4ba --- /dev/null +++ b/.tasks/prt-043-channel-interaction-runtime/T-043-09-report.md @@ -0,0 +1,61 @@ +# T-043-09 Release And Closure Report + +## Context Readiness +- Read the npm release runbook: `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/guides/reference/npm-package-release-runbook.md` +- Read the release workflow: `/Users/deksden/Documents/_Projects/bot-platform/.github/workflows/release-packages.yml` +- Read the publish script: `/Users/deksden/Documents/_Projects/bot-platform/scripts/publish-private-packages.mjs` +- Read the PRT-043 docs: `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md`, `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-implementation-plan.md`, `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-review-details.md`, `/Users/deksden/Documents/_Projects/bot-platform/.tasks/prt-043-channel-interaction-runtime/006-platform-slice-closeout.md` +- Checked current package versions in the workspace and on npm; all four publishable packages are still `0.2.0` locally and in the registry. +- Checked branch/PR/main status: current branch is `feature/EP-022-prt-043-channel-interaction-runtime`, it is 6 commits ahead of `origin/main`, 0 behind, and has no associated PR. +- Ran `pnpm changeset status`; it fails with `Some packages have been changed but no changesets were found.` + +## Release Facts +- Current local package versions: + - `@dd-bot-platform/api-contract` `0.2.0` + - `@dd-bot-platform/channel-runtime` `0.2.0` + - `@dd-bot-platform/core` `0.2.0` + - `@dd-bot-platform/scenario-system` `0.2.0` +- Current npm registry versions: + - `@dd-bot-platform/api-contract` `0.2.0` + - `@dd-bot-platform/channel-runtime` `0.2.0` + - `@dd-bot-platform/core` `0.2.0` + - `@dd-bot-platform/scenario-system` `0.2.0` +- Current release automation posture: + - `Release Packages` runs on pushes to `main` and on manual `workflow_dispatch`. + - The publish job uses `NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}`. + - The workflow validates versioned state with `pnpm changeset:publish --dry-run` before publish. +- Current allowed publish set is aligned across the source of truth files: + - `scripts/publish-private-packages.mjs` + - `.changeset/README.md` + - `.memory-bank/spec/operations/private-registry-package-bridge.md` + +## Stale-Docs Check +- The controlled script allowlist is **not stale**: `channel-runtime` is already present in `scripts/publish-private-packages.mjs` alongside `api-contract`, `core`, and `scenario-system`. +- The runbook explicit package checklist was stale because it did not list `@dd-bot-platform/channel-runtime`; the orchestrator updated it in `.memory-bank/guides/reference/npm-package-release-runbook.md`. +- Earlier PRT-042 evidence that said `channel-runtime` was absent from the publish allowlist is stale relative to the current repo state and should not be used as release authority. + +## Branch And Merge Gate +- This branch is not publish-ready as-is because it is not merged to `main`. +- The runbook says package release readiness and manual publication run from `main` until a `develop` branch is activated. +- The current release workflow only validates/publishes from `main`, so merge to `main` is part of the required path before publish. + +## Changeset Gate +- Initial `pnpm changeset status` failed before versioning. +- Orchestrator then ran `pnpm changeset:version`, materializing: + - `@dd-bot-platform/core@0.3.0` + - `@dd-bot-platform/channel-runtime@0.3.0` +- Release readiness after versioning: + - `pnpm install --frozen-lockfile` ✅ + - `pnpm build` ✅ + - `pnpm changeset:publish --dry-run` ✅ + - dry-run packed `core@0.3.0` and `channel-runtime@0.3.0`; skipped already-published `api-contract@0.2.0` and `scenario-system@0.2.0`. + +## Conclusion +- Release closure is **blocked for publish** until the versioned branch is merged to `main` and the publish workflow runs. +- The correct path is: + 1. commit the versioned state on the feature branch; + 2. open PR to `main`; + 3. wait for `Verification` and `Release Packages` readiness on the PR/main path; + 4. merge to `main`; + 5. publish through the workflow with `publish=true` and `NPM_TOKEN`; + 6. verify `npm view @dd-bot-platform/core version` and `npm view @dd-bot-platform/channel-runtime version` return `0.3.0`. diff --git a/.tasks/prt-043-protocol-review-phase-1/000-review-index.md b/.tasks/prt-043-protocol-review-phase-1/000-review-index.md new file mode 100644 index 0000000..93e4860 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/000-review-index.md @@ -0,0 +1,13 @@ +# PRT-043 Protocol Review Phase 1 + +Workspace for review tasks and reports for `PRT-043-channel-interaction-runtime-command-render-thread-delivery.md`. + +Protocol under review: +- `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required final outcome: +- each subagent reads its task file from this directory; +- each subagent writes a report file in this directory; +- orchestrator integrates accepted findings into `001-orchestrator-consolidated-review.md`; +- accepted documentation fixes are applied to Memory Bank docs; +- protocol records: `стадия проработки протокола: фаза 1 выполнена`. diff --git a/.tasks/prt-043-protocol-review-phase-1/001-orchestrator-consolidated-review.md b/.tasks/prt-043-protocol-review-phase-1/001-orchestrator-consolidated-review.md new file mode 100644 index 0000000..0163d1e --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/001-orchestrator-consolidated-review.md @@ -0,0 +1,134 @@ +# PRT-043 Protocol Review Phase 1 — Consolidated Orchestrator Report + +## Summary verdict + +PRT-043 is architecturally valid, but phase-1 review found that the protocol needs a documentation hardening patch before implementation tasks are opened. + +Accepted direction: +- keep command dispatch and command policy in the command-framework boundary; +- keep canonical response rendering and visibility in channel-runtime; +- treat threading/delivery intent as gated channel-runtime-adjacent candidates, not settled orchestration ownership; +- keep provider senders, retry orchestration, DB/read models, UI/admin, and product command catalogs out of bot-platform; +- require Docoved and SellerAgent adoption waves to prove the contract before closure. + +Main accepted fixes: +- add an explicit entity ownership matrix by feature area; +- add a boundary-step contract table for the inbound -> command -> response -> render -> thread -> delivery flow; +- resolve the phase-0/open-question contradiction by moving package and shape questions to pre-code gates; +- tighten lean scope by demoting delivery/threading nouns to minimal intent/result contracts and deferring orchestration; +- add MBB routing rules; +- add no-migrations/no-backups/no-hidden-storage language; +- add release/deploy/rollback sequence; +- add concrete test/scenario anchors and quality lanes; +- add product adoption side-effect details for Docoved and SellerAgent. + +## Subagent reports used + +- `201-architecture-boundaries-mbb.report.md` +- `202-lean-design-duplication-refactoring.report.md` +- `203-errors-reliability-observability.report.md` +- `204-testing-scenarios-quality.report.md` +- `205-ops-release-deployment-gitflow.report.md` +- `206-product-adoption-side-effects.report.md` +- `207-ui-db-scope-storage.report.md` + +## Accepted findings by area + +### Architecture and MBB + +Accepted: +- PRT-043 needs an ownership table mapping each entity to command-framework, channel-runtime, product, or adapter ownership. +- PRT-043 needs explicit MBB routing rules like PRT-042. +- Phase 0 wording must not claim all package-boundary ambiguity is resolved if pre-code gates remain. +- The protocol should trim or demote duplicated stable spec material by pointing to owning specs. + +Action: +- Patch protocol with `Entity ownership matrix`, `Boundary step contracts`, `Memory Bank documentation rules`, and `Pre-code gates`. + +### Lean design and duplication + +Accepted: +- Actor classes are useful, but should be framed as a minimum framework vocabulary plus product-owned mapping, not a replacement for product roles/capabilities. +- Delivery/threading should remain minimal intent/result/fallback contracts; no multi-step delivery plan or orchestration extraction in phase 1. +- Reuse existing `ChannelCapabilityMatrix`, `ReplyThreadLinkingFidelity`, and observability vocabularies where possible. +- Product-local Telegram compatibility and menu sync remain product/adapter responsibilities. + +Action: +- Patch package strategy and ownership matrix to mark threading/delivery as gated candidate extensions. +- Add reuse rule for existing core/api-contract/control-plane vocabularies. + +### Error handling, reliability, observability + +Accepted: +- Need explicit duplicate/replay and config snapshot/version guidance. +- Need clearer fallback handling for missing reply targets and policy fallback. +- Need product-local incident-monitoring hooks without platform coupling. +- Need no silent swallow rule for dispatch/render/thread/delivery failures. + +Action: +- Patch reliability sections with idempotency, effective config snapshot/readback, and incident-monitoring hooks. + +### Testing and quality + +Accepted: +- Current verification matrix is too generic. +- Need local/package/product/hosted lanes. +- Need concrete tests for policy precedence, command result envelopes, ordinary-email-not-command, unauthorized actors, threading fallback, duplicate delivery/idempotency, menu projection drift. +- Need cite existing scenario anchors, especially Docoved SCN-201/202/204/211 and SellerAgent SCN-053. +- Do not imply lint exists if repo does not expose it. + +Action: +- Patch verification matrix and phase exit criteria. + +### Ops and release + +Accepted: +- Need explicit package release / consumer pin / rollback sequence. +- Need stable alias/readback requirement for hosted beta/prod checks. +- Need no migrations/backups statement for current wave. +- Release/deploy/rollback lessons must be promoted to owning runbooks. + +Action: +- Patch Operations section and Non-goals / UI-DB sections. + +### Product adoption + +Accepted: +- Docoved needs ordinary email question non-command proof and unauthorized sender denial proof. +- SellerAgent should adopt read-only/diagnostic commands before mutation/release-control commands. +- Legacy `commandAccessPolicy` must be migration input only unless explicitly declared canonical by product docs. +- Product Memory Banks must state canonical writable command-policy authority. + +Action: +- Patch Docoved/SellerAgent adoption sections and config compatibility section. + +### UI/DB/storage + +Accepted: +- Current UI/Admin and DB/read-model exclusions are directionally correct. +- Need explicit no migrations/backups/restore workflows in this protocol. +- Hidden persistence for transport-ref lookup, idempotency state, and config snapshots is product-owned. +- Future UI/storage gates should name required docs/scenario/POM/migration responsibilities. + +Action: +- Patch UI/Admin, storage, non-goals, and future gates. + +## Findings not accepted as immediate patch + +- Moving detailed tables into a companion file was accepted during documentation hardening because the main protocol crossed the MBB decomposition threshold after phase-1 fixes. +- Adding a Mermaid diagram now: helpful but optional; table-based contracts provide enough precision for the next discussion. +- Creating new package names now: rejected until the pre-code package-boundary gate is resolved. + +## Documentation patch checklist + +- [x] PRT-043 version/history updated for phase 1. +- [x] Protocol state says phase 1 completed. +- [x] Entity ownership matrix added in companion details. +- [x] Boundary step contracts added in companion details. +- [x] Phase-0/open-question contradiction resolved via pre-code gates. +- [x] MBB routing rules added. +- [x] Verification matrix strengthened and linked to companion details. +- [x] Ops/release/rollback sequence added. +- [x] No migrations/backups/storage statement added. +- [x] Product adoption slices clarified. +- [x] Plans/protocol indexes updated. diff --git a/.tasks/prt-043-protocol-review-phase-1/101-architecture-boundaries-mbb.task.md b/.tasks/prt-043-protocol-review-phase-1/101-architecture-boundaries-mbb.task.md new file mode 100644 index 0000000..8cc2cf5 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/101-architecture-boundaries-mbb.task.md @@ -0,0 +1,48 @@ +# Task 101: Architecture, Entity Boundaries, MBB Documentation Review + +## Goal +Review PRT-043 from the top-level architecture perspective: whether entities, ownership boundaries, contracts, interaction processes, and Memory Bank routing match bot-platform conventions and MBB principles. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required context: +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `.memory-bank/spec/runtime/index.md` +- `.memory-bank/mbb/principles.md` +- `.memory-bank/mbb/delivery-docs-guide.md` +- `.memory-bank/mbb/indexing-guide.md` + +Optional context: +- `.memory-bank/plans/protocols/PRT-042-channel-runtime-canonical-document-command-and-rendering.md` +- `.memory-bank/plans/index.md` +- `.memory-bank/plans/protocols/index.md` + +## Questions to answer +1. Does the protocol describe architecture top-down clearly enough: platform -> product -> adapter -> transport? +2. Are the entities correctly placed? Pay special attention to `CommandInvocationSource`, `CommandActorContext`, `CommandAvailabilityPolicy`, `ThreadingIntent`, `OutboundDeliveryIntent`, and `CanonicalResponseDocument`. +3. Are boundaries consistent with `feature-area-boundaries.md`, especially the rule that command dispatch belongs to command-framework while channel-runtime owns response/render/thread/delivery-adjacent contracts? +4. Does the protocol duplicate existing command-framework/channel-runtime specs, or does it link to them correctly? +5. Are interaction processes described with enough contract precision for implementation? +6. Is MBB documentation routing correct: spec vs protocol vs product-local docs vs task artifacts? +7. Are MBB principles and guides linked and actually followed, not just listed? +8. What specific documentation changes are needed? + +## Constraints +- Do not edit files. +- Be critical but lean: recommend removing text if it duplicates stable specs. +- Prefer concrete line/section references. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/201-architecture-boundaries-mbb.report.md` + +Report format: +- Summary verdict +- Accepted strengths +- Findings requiring documentation change +- Findings that are optional/nice-to-have +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/102-lean-design-duplication-refactoring.task.md b/.tasks/prt-043-protocol-review-phase-1/102-lean-design-duplication-refactoring.task.md new file mode 100644 index 0000000..3ce63ba --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/102-lean-design-duplication-refactoring.task.md @@ -0,0 +1,49 @@ +# Task 102: Lean Design, Duplication, Refactoring Opportunities Review + +## Goal +Review PRT-043 for overengineering, unnecessary abstractions, duplication of existing project capabilities, and refactoring opportunities that are appropriate to plan alongside implementation. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required context: +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `packages/channel-runtime/src/document.ts` +- `packages/channel-runtime/src/render.ts` +- `packages/channel-runtime/src/index.ts` +- `packages/core/src/control-plane/channel-binding/status.ts` +- `packages/core/src/control-plane/models.ts` + +Optional product context: +- `/Users/deksden/Documents/_Projects/docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts` +- `/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-direct-command-proof.ts` +- `/Users/deksden/Documents/_Projects/seller-agent/apps/server/src/telegram/index.ts` +- `/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/conversations.ts` + +## Questions to answer +1. Does PRT-043 introduce too many entities for current needs? Which should be deferred or simplified? +2. Is the proposed package split too vague or too complicated? What is the leanest viable implementation path? +3. Are we duplicating existing `ChannelCapabilityMatrix`, `ReplyThreadLinkingFidelity`, `ControlPlaneObservabilityEvent`, or command-framework concepts? +4. Which product-local Telegram-shaped code smells should be refactored during adoption, and which should remain untouched? +5. Are there opportunities to reuse existing helpers/tests instead of building new layers? +6. Does the protocol prevent speculative universal renderers/provider senders/UI/DB enough? +7. What concrete changes should be made to the protocol to keep implementation minimal? + +## Constraints +- Do not edit files. +- Avoid vague advice; identify exact sections to tighten. +- Prefer a simple path that can ship and be beta-tested. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/202-lean-design-duplication-refactoring.report.md` + +Report format: +- Summary verdict +- Potential overengineering findings +- Duplication/reuse findings +- Refactoring opportunities worth planning +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/103-errors-reliability-observability.task.md b/.tasks/prt-043-protocol-review-phase-1/103-errors-reliability-observability.task.md new file mode 100644 index 0000000..143352a --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/103-errors-reliability-observability.task.md @@ -0,0 +1,48 @@ +# Task 103: Error Handling, Reliability, Race Conditions, Observability Review + +## Goal +Review PRT-043 for robust error handling, retries, idempotency, race conditions, external-provider failure behavior, logging, incident diagnostics, and redaction/safety. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required context: +- `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` +- `.memory-bank/spec/runtime/command-framework-contract.md` +- `.memory-bank/spec/runtime/channel-runtime-contract.md` +- `packages/core/src/control-plane/observability.ts` +- `packages/api-contract/src/control-plane/observability.ts` + +Optional product context: +- `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` +- `/Users/deksden/Documents/_Projects/seller-agent/apps/workflow/workflows/reply-job.ts` +- `/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/conversations.ts` + +## Questions to answer +1. Are error classes complete and aligned with project style? +2. Are parse/validation/access/dispatch/render/threading/delivery failures distinguished clearly? +3. Are retries and idempotency safe enough to avoid duplicate sends? +4. Are race conditions considered: command menu policy drift, config update during dispatch, repeated webhook delivery, email duplicate inbound events, parallel delivery retries? +5. Are fallback rules safe and visible, especially for threading fallback and legacy config fallback? +6. Does the plan avoid silently swallowing important errors? +7. Are observability events sufficient for incident investigation? +8. Do event names/fields align with existing logger and observability specs? +9. Does the protocol mention incident-monitoring/Sentry-style product-local hooks appropriately without forcing platform coupling? +10. What exact documentation changes are needed? + +## Constraints +- Do not edit files. +- Focus on investigation and concrete protocol improvements. +- Pay attention to privacy and redaction. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/203-errors-reliability-observability.report.md` + +Report format: +- Summary verdict +- Error/reliability gaps +- Observability gaps +- Race/concurrency risks +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/104-testing-scenarios-quality.task.md b/.tasks/prt-043-protocol-review-phase-1/104-testing-scenarios-quality.task.md new file mode 100644 index 0000000..26bf442 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/104-testing-scenarios-quality.task.md @@ -0,0 +1,48 @@ +# Task 104: Testing, Scenarios, Quality Gates Review + +## Goal +Review PRT-043 testing and verification plan: local tests, package checks, scenario anchors, hosted beta checks, CI/build/lint/typecheck expectations, and whether planned tests use existing infrastructure. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required context: +- `.memory-bank/plans/verification-matrix.md` +- `.memory-bank/spec/scenarios/hosted-beta-execution-model.md` if present +- `.memory-bank/spec/operations/hosted-beta-acceptance-contract.md` if present +- `.memory-bank/spec/engineering/coding-style.md` if present +- `.memory-bank/spec/engineering/delivery-standards.md` if present +- `packages/channel-runtime/src/channel-runtime.spec.ts` +- `package.json` +- `pnpm-workspace.yaml` + +Product scenario context: +- `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/scenarios/index.md` if present +- `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/scenarios/SCN-053-telegram-observed-user-capture-and-employee-verification-flow.md` +- `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/plans/protocols/PRT-007-telegram-privileged-command-surface-bot-level-release-control-and-runtime-diagnostics.md` + +## Questions to answer +1. Are tests specific enough for each changed subsystem? +2. Are there missing scenarios: unauthorized email sender, ordinary email not command, repeated webhook, duplicate delivery, policy fallback, menu projection drift? +3. Does protocol distinguish local checks vs hosted beta checks vs CI/package release checks? +4. Does it reference existing test helpers/fixtures where available? +5. Are lint/typecheck/build/package dry-run checks planned appropriately? +6. Are hosted beta checks planned only when needed, not wastefully? +7. Are acceptance criteria strong enough to catch the kind of issues that previously slipped through? +8. What exact documentation changes are needed? + +## Constraints +- Do not edit files. +- If a referenced file is absent, report that as a documentation risk rather than guessing. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/204-testing-scenarios-quality.report.md` + +Report format: +- Summary verdict +- Missing/weak tests +- Missing scenario anchors +- Quality gate improvements +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/105-ops-release-deployment-gitflow.task.md b/.tasks/prt-043-protocol-review-phase-1/105-ops-release-deployment-gitflow.task.md new file mode 100644 index 0000000..c4254d4 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/105-ops-release-deployment-gitflow.task.md @@ -0,0 +1,46 @@ +# Task 105: Ops, Release, Deployment, Git Flow Review + +## Goal +Review whether PRT-043 handles operational and DevOps concerns: git flow, commits/pushes, package release, CI, beta deploy timing, hosted verification, rollback, migrations/backups if any, and avoiding unnecessary hosted builds. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required context: +- `.memory-bank/spec/operations/git-flow.md` if present +- `.memory-bank/spec/operations/deployment-architecture.md` if present +- `.memory-bank/spec/operations/runbook.md` if present +- `.memory-bank/spec/operations/hosted-beta-acceptance-contract.md` if present +- `.memory-bank/spec/operations/private-registry-package-bridge.md` if present +- `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` + +Product ops context: +- `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-hosted-deployment-topology.md` if present +- `/Users/deksden/Documents/_Projects/docoved-agent/package.json` +- `/Users/deksden/Documents/_Projects/seller-agent/package.json` + +## Questions to answer +1. Does PRT-043 say when to commit, push, release packages, and deploy beta? +2. Does it prevent unnecessary CI/Vercel builds? +3. Does it specify package release sequence and product pinning clearly? +4. Are rollback/compatibility concerns planned for package version adoption? +5. Since DB/UI are non-goals, does it clearly say no migrations/backups are needed unless later scope changes? +6. Are hosted beta verification gates clear for Docoved and SellerAgent? +7. Does it require checking GitHub/Vercel statuses where relevant? +8. Are lessons learned/insights rules adequate? +9. What exact documentation changes are needed? + +## Constraints +- Do not edit files. +- Focus on protocol wording and missing operational gates. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/205-ops-release-deployment-gitflow.report.md` + +Report format: +- Summary verdict +- Ops/release gaps +- Deployment/rollback risks +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/106-product-adoption-side-effects.task.md b/.tasks/prt-043-protocol-review-phase-1/106-product-adoption-side-effects.task.md new file mode 100644 index 0000000..9c93d0d --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/106-product-adoption-side-effects.task.md @@ -0,0 +1,46 @@ +# Task 106: Docoved and SellerAgent Adoption / Side Effects Review + +## Goal +Review cross-repo adoption implications for Docoved and SellerAgent: command parity, channel config, threading behavior, product ownership, migration from legacy fields, beta proof scope, and side effects in product behavior. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Docoved context: +- `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` +- `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md` +- `/Users/deksden/Documents/_Projects/docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts` if present +- `/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-direct-command-proof.ts` if present +- `/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-beta-telegram-commands.ts` if present + +SellerAgent context: +- `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/plans/protocols/PRT-007-telegram-privileged-command-surface-bot-level-release-control-and-runtime-diagnostics.md` +- `/Users/deksden/Documents/_Projects/seller-agent/apps/server/src/telegram/index.ts` +- `/Users/deksden/Documents/_Projects/seller-agent/apps/server/src/channels/docoved-command-policy.ts` if present +- `/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/operations.ts` +- `/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/conversations.ts` + +## Questions to answer +1. Does Docoved adoption cover email commands, Telegram commands, normal answer flow, reply-threading, unauthorized actors, and ordinary email questions? +2. Does SellerAgent adoption avoid breaking existing privileged command behavior and release-control command safety? +3. Are existing legacy fields like `commandAccessPolicy` handled safely without introducing a second authority? +4. Are side effects covered: command menu sync, channel config drift, beta bot/address specifics, external users, product-specific capabilities? +5. Are product Memory Bank updates specified enough? +6. Does the protocol identify minimum adoption subsets to avoid taking on risky mutation commands too early? +7. What exact documentation changes are needed? + +## Constraints +- Do not edit files. +- Do not assume product implementation details not present in code/docs; mark uncertainty clearly. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/206-product-adoption-side-effects.report.md` + +Report format: +- Summary verdict +- Docoved adoption findings +- SellerAgent adoption findings +- Cross-product side effects +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/107-ui-db-scope-storage.task.md b/.tasks/prt-043-protocol-review-phase-1/107-ui-db-scope-storage.task.md new file mode 100644 index 0000000..6d57102 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/107-ui-db-scope-storage.task.md @@ -0,0 +1,42 @@ +# Task 107: UI/Admin, DB/Storage, Persistence Scope Review + +## Goal +Review whether PRT-043 correctly excludes UI/Admin and DB/read-model work for now, while still documenting future gates and avoiding hidden persistence requirements. + +## Files to inspect +Primary: +- `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` + +Required context: +- `.memory-bank/spec/runtime/persistence-interface-and-store-boundary.md` if present +- `.memory-bank/spec/project/feature-area-boundaries.md` +- `.memory-bank/mbb/delivery-docs-guide.md` +- `.memory-bank/mbb/scenario-docs-guide.md` if present + +Optional product context: +- `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` +- `/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/conversations.ts` + +## Questions to answer +1. Is UI/Admin correctly marked out of scope? +2. Does the protocol avoid requiring UI documentation/POM objects while correctly saying they are needed if UI is introduced later? +3. Is DB/read-model work correctly excluded? +4. Are hidden persistence requirements implied by delivery idempotency/threading lookup/config SSoT? If yes, are they product-owned and documented enough? +5. Does the protocol clearly state no migrations/backups are needed for current scope, and what would change if storage enters scope? +6. Are future gates for UI/DB specific enough? +7. What exact documentation changes are needed? + +## Constraints +- Do not edit files. +- Focus on preventing accidental scope creep. + +## Report +Write your report to: +- `.tasks/prt-043-protocol-review-phase-1/207-ui-db-scope-storage.report.md` + +Report format: +- Summary verdict +- UI/Admin scope findings +- DB/storage scope findings +- Hidden persistence risks +- Suggested exact patch direction diff --git a/.tasks/prt-043-protocol-review-phase-1/201-architecture-boundaries-mbb.report.md b/.tasks/prt-043-protocol-review-phase-1/201-architecture-boundaries-mbb.report.md new file mode 100644 index 0000000..558c6e5 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/201-architecture-boundaries-mbb.report.md @@ -0,0 +1,200 @@ +# PRT-043 Architecture, Boundaries, and MBB Review Report + +## Summary verdict + +PRT-043 is directionally sound and should proceed only after a documentation hardening pass. The protocol correctly frames the platform/product split and mostly keeps product behavior out of `bot-platform`, but it currently overstates a few candidate framework seams as settled ownership, duplicates stable spec material, and lacks a dedicated MBB routing section equivalent to PRT-042. + +Question-by-question verdict: + +1. **Top-down architecture:** Mostly clear. The flow in `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` section `Target architecture` lines 109-124 gives a readable adapter -> parser -> dispatcher -> handler -> render/thread/deliver sequence, but it should explicitly label the layers as platform -> product -> adapter -> transport. +2. **Entity placement:** Partially correct but needs a normative ownership table. Command entities belong to `command-framework`; canonical response, render, threading-intent, and delivery-intent vocabulary may be channel-runtime-adjacent only within the thin seam. The current `Interaction contract boundaries` section lines 126-152 says "framework-owned contracts" without identifying the owning feature area for each entity. +3. **Boundary consistency:** Good intent, but not fully safe. The protocol says command dispatch remains command-framework-owned at lines 77-79 and 587-593, matching `.memory-bank/spec/project/feature-area-boundaries.md` lines 60-85, but `ThreadingIntent` / `OutboundDeliveryIntent` are described as channel-runtime-owned before the boundary gate is fully resolved. +4. **Duplication vs links:** Needs trimming. It links to the owning specs in frontmatter and at lines 77-79, but repeats command-framework and channel-runtime contract content in several long sections instead of treating specs as SSoT. +5. **Process precision:** Close, not implementation-ready. Parse outcomes, policy precedence, failure types, threading fallback, delivery idempotency, and logging events are present, but the protocol needs one step contract table with inputs, outputs, owner, failure result, and event names for each boundary crossing. +6. **MBB routing:** Incomplete. Indexes already mention PRT-043, but the protocol itself lacks explicit routing rules for spec vs protocol vs product-local docs vs `.tasks` artifacts. +7. **MBB principles:** Referenced but not fully followed. The file is 819 lines, crosses the MBB >800-line decomposition threshold, and duplicates stable spec truth, conflicting with SSOT/atomicity guidance. +8. **Required documentation changes:** Add an ownership table, mark candidate seams as gated, trim duplicate spec material, add MBB routing rules, resolve Phase-0/open-question contradictions, and add precise implementation boundary contracts. + +## Accepted strengths + +- **Clear platform/product principle:** PRT-043 states that `bot-platform` owns shared interaction mechanics while product repos own product behavior in `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` lines 71-84. +- **Good high-level flow:** The target architecture sequence in lines 109-124 is a useful implementation backbone and already separates adapter, parser, dispatcher, handler, renderer, threading, delivery, and diagnostics. +- **Strong command boundary intent:** Lines 77-79 and 244-271 correctly say command parser/dispatch primitives must reuse the command framework and must not become Telegram-shaped platform truth. +- **Correct product-local exclusions:** Lines 139-152, 526-552, and 554-578 keep actor lookup, product command catalogs, provider credentials, business semantics, and provider send behavior in product/adapters. +- **No DB/UI scope creep:** Lines 84, 513-524, and 800-808 explicitly reject shared UI/admin, framework DB/read-model tables, provider SDK senders, and product command catalogs. +- **Operational safety is concrete:** Lines 386-397 define idempotency expectations, lines 456-497 list structured diagnostics and redaction rules, and lines 499-511 add anti-abuse/rate-limit hooks. + +## Findings requiring documentation change + +### 1. Add an explicit entity ownership table before implementation + +PRT-043 lists `CommandInvocationSource`, `CommandActorContext`, `CommandAvailabilityPolicy`, `CommandAvailabilityDecision`, `CommandExecutionResult`, `ThreadingIntent`, and `OutboundDeliveryIntent` together as "Framework-owned contracts" in `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` lines 130-137. That is too coarse for this repo's feature-area model. + +Required change: + +- Add a table near `Interaction contract boundaries` with columns: `Entity`, `Owning feature area`, `Owning stable spec`, `Implementation package/module candidate`, `Product-owned inputs`, `Adapter-owned inputs`. +- Place command entities under `.memory-bank/spec/runtime/command-framework-contract.md`, especially `CommandEnvelope`, parser/normalization, registry, dispatch, failures, and access hook shape per lines 40-49, 55-68, 70-84, 105-117, 119-149. +- Place `CanonicalResponseDocument` under `.memory-bank/spec/runtime/channel-runtime-contract.md` lines 72-97 and current code in `packages/channel-runtime/src/document.ts` lines 61-84. +- Mark `ThreadingIntent`, `ThreadingResolution`, `OutboundDeliveryIntent`, and `OutboundDeliveryResult` as a **candidate/gated channel-runtime extension**, not settled stable ownership, until Phase 1 proves the thin seam. +- State that refs such as workspace/product/channel/run/trace must reuse existing core/api-contract vocabulary, consistent with `.memory-bank/spec/project/feature-area-boundaries.md` lines 83-85 and PRT-042's reuse rule in `.memory-bank/plans/protocols/PRT-042-channel-runtime-canonical-document-command-and-rendering.md` lines 449-460. + +Why required: + +- `.memory-bank/spec/project/feature-area-boundaries.md` says `command-framework` owns command envelope/parser/registry/execution hooks at lines 60-66. +- The same file says `channel-runtime` owns canonical response/render vocabulary but does **not** own command dispatch/access policy, transport senders, retries, threading state, provider payloads, DB, or UI at lines 68-85. +- `.memory-bank/mbb/delivery-docs-guide.md` warns candidate seams must not be documented as owned truth at lines 230-246. + +### 2. Resolve the Phase-0 completion contradiction + +PRT-043 says Phase 0 is complete at lines 55-69 and lines 622-624. It also says Phase-0 exit criteria are satisfied at lines 616-620. But the `Open questions before implementation` section says the questions "must be resolved in Phase 0 before code changes begin" at lines 810-819, and those questions include unresolved ownership/package decisions. + +Required change: + +- Either mark Phase 0 as **not fully complete** until lines 812-817 are resolved, or move those questions into a new "Phase 1 gates before code" section. +- Change line 617's "no unresolved ownership ambiguity" claim to a narrower statement, for example: "design direction is agreed; package/module placement remains a pre-code gate." +- Align `Protocol elaboration state`, `Phase-0 status`, and `Open questions before implementation` so they do not disagree. + +Why required: + +- The package-boundary question is material. Current repo packages are `@dd-bot-platform/core`, `@dd-bot-platform/api-contract`, and `@dd-bot-platform/channel-runtime`; there is no command-framework package in `packages/*/package.json`. +- PRT-043 acknowledges this at lines 601-603, but still states Phase 0 has no ownership ambiguity at lines 616-620. + +### 3. Do not let channel-runtime absorb command policy or dispatch by implication + +The protocol is mostly careful, but some sections can be misread as channel-runtime owning the whole interaction runtime because the protocol title and package strategy emphasize `@dd-bot-platform/channel-runtime`. The hard rule at lines 587-593 is correct, but it needs to be elevated earlier and made normative. + +Required change: + +- In `Core decision`, add a short normative split: + - `command-framework` owns command envelope, normalization, registry, dispatcher, command availability policy, command failures, and command diagnostics. + - `channel-runtime` owns canonical response documents, visibility, render target vocabulary, and candidate response/thread/delivery intent/result contracts. + - adapters own provider syntax, provider payloads, reply/header mapping, and final send. +- In `Package strategy`, replace "channel-runtime owns ... threading intent, delivery intent/result" at lines 591-593 with "channel-runtime may own ... if the Phase 1 boundary gate confirms they are provider-neutral and do not include threading state, provider senders, retries, or delivery orchestration." + +Why required: + +- `.memory-bank/spec/runtime/channel-runtime-contract.md` excludes command dispatch, command registry, command access policy, delivery orchestration, retry queues, threading, provider send logic, DB, and UI from the first-wave contract at lines 45-55. +- `.memory-bank/spec/runtime/channel-runtime-contract.md` lines 149-155 explicitly require future command adoption to reuse the command framework rather than adding parallel `ChannelCommand*` primitives. + +### 4. Trim duplicated stable spec content and link to SSoT instead + +PRT-043 repeats a lot of stable command and channel-runtime vocabulary: + +- `Command input normalization` lines 216-243 overlaps `.memory-bank/spec/runtime/command-framework-contract.md` lines 70-84. +- `Command ownership boundaries` lines 244-271 overlaps `.memory-bank/spec/runtime/command-framework-contract.md` lines 40-53, 139-161, and 163-176. +- `Canonical response and universal rendering` lines 297-327 overlaps `.memory-bank/spec/runtime/channel-runtime-contract.md` lines 72-132. +- `Package strategy` lines 580-603 restates ownership already covered by `.memory-bank/spec/project/feature-area-boundaries.md` lines 60-85 and the two runtime specs. + +Required change: + +- Keep PRT-043 focused on the delta after PRT-042: actor-aware availability, command-result-to-canonical-document bridge, threading intent fallback semantics, delivery intent/result correlation, migration compatibility, and adoption waves. +- Replace repeated stable definitions with links such as "must conform to Command Framework Contract / Channel Runtime Contract." +- Promote any stable new contract shape from PRT-043 into the owning runtime spec once accepted; do not leave stable truth only in the protocol. + +Why required: + +- `.memory-bank/mbb/principles.md` requires Single Source of Truth at lines 23-42. +- `.memory-bank/mbb/delivery-docs-guide.md` says a protocol must not store duplicated normative design that belongs in a spec at lines 203-205. + +### 5. Add one implementation boundary contract table for the nine-step flow + +The target flow at `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` lines 113-121 is readable, but implementation teams still have to infer exact boundary contracts across parser, dispatcher, product handler, renderer, threading, and delivery. + +Required change: + +- Add a table after `Target architecture` with one row per step: + - input contract; + - output contract; + - owner (`command-framework`, `channel-runtime`, product, adapter, transport); + - required failure/result kind; + - required diagnostic event from lines 456-471; + - whether the step is side-effect free. +- Explicitly specify these boundary transitions: + - `not_a_command` returns to ordinary answer flow, not command dispatch. + - `parse_error` / `unknown_command` / `validation_error` / `access_denied` convert to safe `CanonicalResponseDocument` only when user-facing feedback is required. + - `ThreadingIntent` is resolved by the adapter into `ThreadingResolution` before final provider send. + - `OutboundDeliveryIntent` carries or derives an idempotency key before any transport call. + +Why required: + +- Current process details are split across parse outcomes at lines 229-233, command result/failure rules at lines 273-295, threading fallback at lines 354-366, delivery idempotency at lines 386-390, and logging events at lines 456-471. +- `.memory-bank/mbb/delivery-docs-guide.md` requires ambiguity-sensitive documents that touch contract shape, fallback semantics, ownership boundaries, or acceptance-critical runtime behavior to list open questions/research and avoid pretending the design is fully settled at lines 281-298. + +### 6. Add a dedicated MBB routing section + +PRT-043 frontmatter links MBB guides at lines 21-23, and product sections mention routing at lines 552 and 578, but the protocol lacks explicit rules for where stable truth and adoption truth live. + +Required change: + +- Add `## Memory Bank documentation rules` modeled on PRT-042 lines 751-779. +- State: + - stable command contract truth lives in `.memory-bank/spec/runtime/command-framework-contract.md`; + - stable channel response/render/thread/delivery-intent truth lives in `.memory-bank/spec/runtime/channel-runtime-contract.md` only after accepted/gated promotion; + - cross-wave sequencing and evidence live in PRT-043; + - Docoved adoption details live in Docoved Memory Bank; + - SellerAgent adoption details live in SellerAgent Memory Bank; + - `.tasks/prt-043-protocol-review-phase-1/` reports are transient review evidence, not canonical contract truth. +- Add a required docs update list for runtime specs and indexes when the protocol is hardened. + +Why required: + +- `.memory-bank/mbb/principles.md` requires explicit documentation operating model at lines 199-216. +- `.memory-bank/mbb/delivery-docs-guide.md` defines source-of-truth by document type at lines 189-215. +- `.memory-bank/mbb/indexing-guide.md` requires indexes to stay current when files/content change at lines 27-31 and 361-367. + +### 7. Reduce or split the protocol because it crosses the MBB >800-line threshold + +PRT-043 is 819 lines. `.memory-bank/mbb/principles.md` says Tier 3 documents over 800 lines require decomposition at lines 47-51. + +Required change: + +- Prefer trimming duplicated spec content below 800 lines. +- If it remains over 800 lines, split long detail into a small companion detail file and keep PRT-043 as the protocol summary with annotated links. +- Do not split into product-local details inside `bot-platform`; product adoption details should remain only high-level here and move to product repos. + +Why required: + +- This is not just cosmetic. The length comes largely from duplicated stable spec content and makes the protocol compete with runtime specs as SSoT. + +## Findings that are optional/nice-to-have + +- **Add a simple architecture diagram:** A small Mermaid diagram showing platform -> product -> adapter -> transport would make the top-down intent unambiguous. +- **Rename "Universal rendering":** The section title at line 297 could be "Canonical response rendering" because line 301 correctly says the framework does not own one universal provider renderer. +- **Add example entity rows:** One compact example each for Telegram, email, web/API, and CLI would help validate `CommandInvocationSource`, `CommandActorContext`, `ThreadingIntent`, and `OutboundDeliveryIntent` without adding product-specific truth. +- **Make actor vocabulary extensibility sharper:** Lines 158-166 define actor classes; add whether product extensions can affect framework policy directly or only through product capability tags. +- **Add "unknown vs anonymous" distinction:** Lines 164-165 list both; a short distinction would prevent inconsistent product mappings. +- **Use exact anchor links:** Where stable specs are cited, link to the specific section anchors instead of only listing files in frontmatter. + +## Suggested exact patch direction + +1. **Patch `Core decision` / `Interaction contract boundaries`:** + - Insert a normative ownership matrix immediately after `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` line 126. + - Replace "Framework-owned contracts" at line 130 with "bot-platform-owned contracts by feature area." + - Route `CommandInvocationSource`, `CommandActorContext`, `CommandAvailabilityPolicy`, `CommandAvailabilityDecision`, and `CommandExecutionResult` to `command-framework`, with reused auth/control-plane refs where applicable. + - Route `CanonicalResponseDocument` to `channel-runtime`. + - Route `ThreadingIntent` / `OutboundDeliveryIntent` to "candidate channel-runtime extension after Phase 1 boundary gate." + +2. **Patch `Package strategy`:** + - Keep lines 587-593 as the hard split but soften ownership of threading/delivery to candidate/gated language. + - Add an explicit rule that no command-framework public types are exported from `@dd-bot-platform/channel-runtime` unless they are re-exports from the command owner and the dependency direction is documented. + +3. **Patch `Phase-0 status` and `Open questions`:** + - Move lines 812-817 into a "Pre-code gates" subsection or mark Phase 0 as still open. + - Update lines 616-620 so they do not claim all ambiguity is resolved while package-boundary and field-shape questions remain. + +4. **Patch process precision:** + - Add a `Boundary step contracts` table after the target architecture flow. + - Consolidate parse/result/failure/threading/delivery diagnostics into the table instead of scattering all implementation-critical rules across separate prose sections. + +5. **Patch duplicated sections:** + - Shorten `Command input normalization`, `Command ownership boundaries`, and `Canonical response and universal rendering` to PRT-043-specific deltas. + - Replace stable vocabulary restatement with links to `.memory-bank/spec/runtime/command-framework-contract.md` and `.memory-bank/spec/runtime/channel-runtime-contract.md`. + +6. **Patch MBB routing:** + - Add a `Memory Bank documentation rules` section before `Lessons learned and insights`. + - Explicitly state spec/protocol/product/task ownership. + - Fix or clarify the task artifact path at line 789 so it does not conflict with the active review workspace `.tasks/prt-043-protocol-review-phase-1/`. + +7. **Patch indexes after protocol hardening:** + - `.memory-bank/spec/runtime/index.md` already mentions the command/channel contracts at lines 74-76; update only if new stable spec sections are promoted. + - `.memory-bank/plans/index.md` lines 90-108 and `.memory-bank/plans/protocols/index.md` lines 81-82 already route readers to PRT-043; update history/status if Phase 0 is reclassified or gates are renamed. diff --git a/.tasks/prt-043-protocol-review-phase-1/202-lean-design-duplication-refactoring.report.md b/.tasks/prt-043-protocol-review-phase-1/202-lean-design-duplication-refactoring.report.md new file mode 100644 index 0000000..45e84a7 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/202-lean-design-duplication-refactoring.report.md @@ -0,0 +1,31 @@ +# PRT-043 Lean Design / Duplication / Refactoring Review + +## Summary Verdict +PRT-043 is directionally correct, but phase 1 is still too broad. The leanest viable path is to keep `bot-platform` focused on the existing command-framework contract plus the current canonical response-document seam, and defer most new command/thread/delivery nouns until both Docoved and SellerAgent prove they need the same shape. + +## Potential Overengineering Findings +- The protocol introduces a larger actor vocabulary than the codebase currently needs. In `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:154` (`Actor-aware command model`), the framework wants `system_admin`, `workspace_admin`, `workspace_member`, `verified_employee`, `external_known_user`, `external_unknown_user`, and `anonymous`. The current product code only resolves three coarse outcomes: `system_admin`, `employee`, and `external_customer` in `seller-agent/packages/core/src/telegram-commands.ts:625` and `docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts:332`. The cross-product vocabulary should be narrowed to a product-owned mapping layer instead of becoming a new shared taxonomy. +- The framework-owned command policy/result surface is too close to a parallel command framework. `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:126` (`Interaction contract boundaries`) adds `CommandInvocationSource`, `CommandActorContext`, `CommandAvailabilityPolicy`, `CommandAvailabilityDecision`, and `CommandExecutionResult`, but `.memory-bank/spec/runtime/command-framework-contract.md:17` already owns `CommandEnvelope`, parser/registry/dispatcher primitives, and typed failure classes. Leaner implementation: reuse the existing command-framework nouns and only add the smallest threading/delivery bridge needed by both products. +- The delivery model is also more elaborate than the current seam justifies. `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:368` (`Outbound delivery intent and outcome`) adds `OutboundDeliveryIntent`, `OutboundDeliveryResult`, six delivery status values, and a configuration matrix. Product code already owns delivery orchestration, retry, and fallback behavior in `seller-agent/apps/server/src/telegram/index.ts:90` and `seller-agent/apps/server/src/telegram/index.ts:1344`. That makes a framework-owned delivery lifecycle premature unless a shared persistence/read-model requirement is proven first. +- The command input section is already drifting toward a universal parser contract. `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:216` (`Command input normalization`) includes Telegram, email, web/API, and CLI grammars. Only Telegram direct-command behavior is concretely implemented in the current product helpers, so the web/API/CLI cases should remain adapter-specific until a second consumer appears. + +## Duplication / Reuse Findings +- `ChannelCapabilityMatrix` and `ReplyThreadLinkingFidelity` already exist in `packages/core/src/control-plane/models.ts:41`, and `packages/core/src/control-plane/channel-binding/status.ts:57` already uses them to assess channel binding capabilities. PRT-043 should reuse those control-plane types instead of minting parallel thread/capability vocabulary. +- The same concepts are already duplicated again in the API contract schema: `packages/api-contract/src/control-plane/models.ts:115` defines `controlPlaneChannelCapabilityMatrixSchema`. The protocol should explicitly point at the existing core/api-contract vocabulary rather than treating threading/capability as a new channel-runtime model. +- `ControlPlaneObservabilityEvent` already exists in `packages/core/src/control-plane/observability.ts:11`, and the API contract schema exists in `packages/api-contract/src/control-plane/observability.ts:19`. PRT-043’s required event names should be framed as extensions of that existing observability contract, not as a new command-runtime event model. +- `channel-runtime` already has the exact first-wave seam the protocol should build on: `packages/channel-runtime/src/document.ts:78` defines `CanonicalResponseDocument` plus visibility filtering, and `packages/channel-runtime/src/render.ts:34` and `packages/channel-runtime/src/render.ts:95` provide the pure markdown/plain-text and message-splitting helpers. The package does not need a broader renderer abstraction to ship the phase-1 proof. +- The Telegram command code is duplicated across both products. `docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts:7` and `seller-agent/packages/core/src/telegram-commands.ts:39` both define catalog entries, direct-command policy/surface, access profiles, command allow-list projection, and access resolution. `docoved-agent/scripts/docoved-direct-command-proof.ts:30` also reimplements command parsing and reply sending locally. These are the right refactor targets, but they should stay product-local rather than moving into `bot-platform`. + +## Refactoring Opportunities Worth Planning +- Refactor the Telegram command parsing/access/catalog helpers inside each product repo into a small product-local compatibility layer. The repeated code around `parseDirectCommand`, `telegramCommandsForAccess`, `resolveTelegramCommandAccess*`, and command-menu projection should be shared within Docoved and within SellerAgent, but not extracted as a framework package. +- Keep Telegram send/reply mechanics product-owned. `seller-agent/packages/core/src/telegram-commands.ts:178` and `seller-agent/apps/server/src/telegram/index.ts:90` both show that HTML rendering, split logic, reply fallback, and transport send behavior are tightly coupled to Telegram/provider APIs. `channel-runtime` should only help with canonical document rendering and plain-text fallback, not own provider send policy. +- Treat `commandAccessPolicy` as a migration input, not a new shared source of truth. The protocol already says legacy fields can be read compatibly in `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:422`, but it should be stricter that the canonical edit surface remains product-local until the migration plan lands. +- Reuse `packages/channel-runtime/src/channel-runtime.spec.ts:53` as the acceptance anchor for visibility filtering and markdown splitting. If PRT-043 adds anything new, keep the test footprint small and focused on the new threading/correlation seam instead of adding a new renderer stack. + +## Suggested Exact Patch Direction +- In `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:126` (`Interaction contract boundaries`), replace the new framework noun list with a reuse-first rule: `bot-platform` should reuse the existing `CommandEnvelope` / parser / registry / dispatcher contract, and only add a minimal thread/delivery correlation bridge if both products require it. +- In `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:154` (`Actor-aware command model`), remove the hardcoded shared actor taxonomy beyond the existing coarse product resolution. Keep actor-to-role mapping product-owned, and make `verified_employee`, `external_known_user`, `external_unknown_user`, and `anonymous` product-local if they are needed at all. +- In `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:297` (`Canonical response and universal rendering`), keep the scope limited to canonical documents, visibility filtering, and pure markdown/plaintext helpers. Do not add a universal renderer, render-plan envelope, or provider-specific HTML policy. +- In `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:329` and `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:368` (`Threading intent` / `Outbound delivery intent and outcome`), defer the delivery result lattice and most delivery policy nouns. If anything is shared now, make it `ThreadingIntent` plus correlation IDs only; keep delivery retries, idempotency keys, and provider send state product-local. +- In `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:434` (`Logging-first diagnostics`), tie required events to the existing `ControlPlaneObservabilityEvent` vocabulary in `packages/core/src/control-plane/observability.ts:11` instead of introducing a separate command-runtime event model. +- Add one more non-goal in `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:513` (`UI/Admin stance`): no framework-owned universal renderer, no framework-owned provider sender, and no framework-owned delivery store/read model. diff --git a/.tasks/prt-043-protocol-review-phase-1/203-errors-reliability-observability.report.md b/.tasks/prt-043-protocol-review-phase-1/203-errors-reliability-observability.report.md new file mode 100644 index 0000000..26ee779 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/203-errors-reliability-observability.report.md @@ -0,0 +1,133 @@ +# Task 103 Report: Errors, Reliability, Observability + +## Summary verdict + +PRT-043 is directionally strong on typed command failures, logging-first diagnostics, redaction, and avoiding framework-owned queues/DB/UI. It already cites the right owners: command failures reuse `.memory-bank/spec/runtime/command-framework-contract.md` sections "Diagnostics and error-shape expectations" and "Access and permission boundary"; rendering/threading/delivery stay in `.memory-bank/spec/runtime/channel-runtime-contract.md` section "Reliability And Observability"; incident policy follows `.memory-bank/spec/operations/observability-and-incident-diagnostics.md`. + +The protocol is not implementation-ready for reliability without a hardening pass. The biggest gaps are: delivery idempotency is still too advisory; retry and duplicate-event behavior is under-specified; config/menu policy races lack snapshot/version semantics; render/thread/delivery failures are not elevated into a complete interaction failure taxonomy; and the required event names in PRT-043 do not align with the current control-plane observability vocabulary in `packages/core/src/control-plane/observability.ts` and `packages/api-contract/src/control-plane/vocabulary.ts`. + +Recommended verdict: approve the protocol direction, but require a patch before Phase 1 code tasks. The patch should add exact failure classes, idempotency/dedup rules, policy/config snapshot rules, product-local incident-monitoring hooks, and an event vocabulary alignment decision. + +## Error/reliability gaps + +1. **Failure taxonomy is incomplete beyond command dispatch.** + - `.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md` section "Command result and failure model" covers `not_a_command`, `parse_error`, `unknown_command`, `validation_error`, `access_denied`, `dispatch_error`, `unsupported_channel`, and `rate_limited`. + - `.memory-bank/spec/runtime/command-framework-contract.md` section "Diagnostics and error-shape expectations" requires command execution to distinguish at least `parse_error`, `unknown_command`, `validation_error`, `access_denied`, and `dispatch_error`. + - PRT-043 sections "Canonical response and universal rendering", "Threading intent", and "Outbound delivery intent and outcome" mention typed/logged failures, but they do not define stable failure classes for `render_error`, `render_degraded`, `threading_resolution_failed`, `threading_fallback_used`, `delivery_provider_transient`, `delivery_provider_permanent`, `delivery_idempotency_conflict`, `delivery_duplicate_suppressed`, or `config_resolution_failed`. + - Patch direction: add a separate `ChannelInteractionFailureClass` / `reason_code` table so command failures do not become overloaded with rendering/threading/delivery failures. + +2. **Dispatch errors are described as "incident-grade" too broadly.** + - PRT-043 section "Command result and failure model" says dispatch errors should log incident-grade diagnostics. + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` sections "Error classes" and "Crash policy" distinguish expected domain errors, external transient errors, recoverable runtime errors, slow-path anomalies, and unexpected/invariant errors. + - Patch direction: replace broad "incident-grade" wording with a severity matrix: validation/access/unknown are expected `info`/`warn`; provider transient failures are `error` with bounded retry; retry exhaustion, impossible state, serialization corruption, and post-send finalization failure are incident-monitor candidates. + +3. **Idempotency is necessary but not enforceable as written.** + - PRT-043 section "Outbound delivery intent and outcome" says every delivery intent should carry a stable idempotency key "or enough correlation fields for the adapter to derive one." + - That is weaker than `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` section "Retry policy", which allows retries only when the operation is idempotent, guarded by an idempotency key, or represented as a new attempt entity. + - SellerAgent already has product-local lifecycle guards and terminal delivery readback in `/Users/deksden/Documents/_Projects/seller-agent/apps/workflow/workflows/reply-job.ts` around workflow delivery handling and recovery, and delivery outcome schemas in `/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/conversations.ts` section defining `conversationReplyDeliveryExecutionOutcomeSchema`. + - Patch direction: require `OutboundDeliveryIntent.idempotencyKey` unless a product-specific provider idempotency primitive is documented. If derived, define the derivation inputs and scope explicitly: product instance, channel ref, response id, command id/run id, transport target, and delivery purpose. Log only a hash or bounded key fingerprint. + +4. **Retry ownership is named but not bounded enough.** + - PRT-043 section "Outbound delivery intent and outcome" correctly says retry ownership must be one layer deep. + - It does not define default max attempts, backoff, terminal exhaustion event, retryable vs non-retryable delivery classes, or provider-attempt vs platform-attempt counters. + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` section "Retry policy" sets default max attempts to `3`, exponential backoff with jitter, and terminal traceable state. + - Patch direction: add delivery retry rules by class: validation/config/access/render errors are not retryable; provider timeout/5xx/rate limit can retry with `attempt_id`, `retry_ordinal`, and idempotency key; provider 4xx/auth failures fail terminally unless product config explicitly marks them recoverable. + +5. **Inbound deduplication is missing.** + - PRT-043 mentions idempotency for outbound delivery, but not repeated inbound webhook deliveries or duplicate email inbound events. + - Docoved requires canonical conversation ingress and reply-link normalization in `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` sections "Internal operation", "Source-binding rule", and "Reply-link rule"; these depend on stable transport refs. + - Patch direction: add `InboundInteractionIdentity` guidance: provider update id/message id/email `Message-ID` plus channel ref and product instance ref. Repeated inbound events must be processed once or logged as `channel_event_skipped` / `duplicate_event_suppressed` with correlation to the original canonical message. + +6. **Config failures need exact safe/unsafe behavior.** + - PRT-043 section "Configuration source of truth and compatibility" says invalid delivery policy suppresses send only when safe; otherwise it fails loudly. + - "Safe" is not defined. This is risky because suppressing a customer-visible send can hide a generated answer, while sending under an invalid policy can leak content. + - Patch direction: define safe suppression as requiring no provider send attempted, a user/operator-visible terminal result where applicable, and a structured `policy_resolution_failed` or `outbound_delivery_failed` event. If any content may already have been sent, suppressing finalization is not safe; record partial failure. + +## Observability gaps + +1. **PRT-043 event names do not currently exist in the control-plane event schemas.** + - PRT-043 section "Logging-first diagnostics" requires `command_input_received`, `command_parse_completed`, `command_policy_evaluated`, `command_dispatch_started`, `command_dispatch_completed`, `command_dispatch_failed`, `channel_render_completed`, `channel_render_failed`, `threading_intent_resolved`, `threading_intent_failed`, `outbound_delivery_started`, `outbound_delivery_completed`, `outbound_delivery_failed`, `compat_fallback_used`, and `rate_limit_triggered`. + - `packages/core/src/control-plane/observability.ts` and `packages/api-contract/src/control-plane/vocabulary.ts` currently allow only membership/session/channel-binding/policy-assignment/diagnostics/trace/fallback events. + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` section "Event naming policy" includes baseline events such as `channel_event_received`, `channel_event_processed`, `channel_event_failed`, `channel_event_skipped`, `retry_scheduled`, `retry_exhausted`, `delivery_plan_completed`, `delivery_plan_failed`, `policy_resolution_failed`, and `compat_fallback_used`, but not most PRT-043-specific command/render/thread events. + - Patch direction: state whether PRT-043 events are product-local runtime log events outside the control-plane API schemas, or extend the shared vocabulary. Do not leave them in-between. + +2. **Required field names mix log shape and TypeScript API shape.** + - PRT-043 section "Logging-first diagnostics" lists snake_case fields such as `request_id`, `workspace_ref`, and `delivery_id`. + - Existing control-plane code uses camelCase fields such as `requestId`, `workspaceRef`, and `traceArtifactRef` in `packages/core/src/control-plane/observability.ts` and `packages/api-contract/src/control-plane/observability.ts`. + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` section "Logger baseline" uses snake_case for emitted JSON logs. + - Patch direction: add a casing rule: TypeScript contract fields may be camelCase, emitted structured logs use snake_case, and any serializer must map between them deterministically. + +3. **Incident-monitoring hooks are missing.** + - The task asks whether the protocol mentions incident-monitoring/Sentry-style product-local hooks without forcing platform coupling. + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` sections "Layers of observability", "Crash policy", and "Controlled error drill" require incident-monitor capture for unexpected exceptions/anomaly messages and optional event ids. + - PRT-043 section "Logging-first diagnostics" mentions logs, traces, and product-local artifacts, but not incident-monitor hooks or `incident_event_id`. + - Patch direction: add a paragraph: products may attach Sentry-style incident monitors at product boundaries; platform contracts may carry optional `incident_event_id`/`incident_ref`; bot-platform must not import or require a concrete monitoring SDK. + +4. **Fallback event requirements are too vague for schema validation.** + - `packages/api-contract/src/control-plane/observability.ts` requires `compat_fallback_used` events to include `details.fallbackKind`. + - PRT-043 sections "Actor-aware command model", "Threading intent", and "Configuration source of truth and compatibility" say fallback must be logged, but do not require `fallbackKind`, `from`, `to`, `reason_code`, `required`, `configured`, or `safety_verdict`. + - Patch direction: define required fallback details for command policy, legacy config, threading fallback, and delivery suppression. Use `fallbackKind` consistently to match the existing schema. + +5. **Missing operational fields for incident reconstruction.** + - PRT-043 lists core correlation fields, but incident investigation also needs: `effective_config_ref` or `config_version`, `policy_version`, `policy_decision`, `provider_kind`, `provider_error_category`, `retry_ordinal`, `max_attempts`, `idempotency_key_hash`, `requested_threading_mode`, `effective_threading_mode`, and duplicate-event identity. + - `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` section "Runtime and async visibility baseline" requires configuration truth and execution truth to stay distinguishable. + - Patch direction: add these as required where applicable, while keeping raw provider payloads, full command args, full email bodies, Telegram messages, tokens, headers, cookies, and full response bodies forbidden as PRT-043 already states. + +## Race/concurrency risks + +1. **Command menu policy drift.** + - PRT-043 section "Actor-aware command model" correctly says command menu projection is not authority and menus/help derive from server-side policy. + - Remaining race: a provider menu can stay stale after policy changes, causing users to see commands that the server will deny or miss commands that are now allowed. + - Patch direction: add menu projection version/readback guidance. Denial remains server-authoritative, but stale menu detection should log `command_menu_projection_stale` or a product-local equivalent with policy version and channel ref. + +2. **Config update during dispatch.** + - PRT-043 section "Configuration source of truth and compatibility" defines effective config inputs but not when the effective config snapshot is captured. + - Race: command policy, threading mode, or delivery policy can change between parse, policy evaluation, render, and send. + - Patch direction: require the adapter/dispatcher to capture an immutable effective-config snapshot or version/fingerprint at dispatch start. The same snapshot governs parse/policy/render/thread/delivery for that invocation unless a product explicitly aborts on stale config. Log configured truth and executed truth separately. + +3. **Repeated webhook delivery and email duplicate inbound events.** + - PRT-043 section "Command input normalization" is conservative about email parsing but does not define duplicate inbound handling. + - Docoved's adapter contract requires inbound email to become a canonical conversation turn and allows email thread recovery from stored transport refs in `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-channel-adapter-contract.md` section "Source-binding rule". + - Patch direction: require inbound idempotency before command dispatch or answer generation. Duplicate provider events should not re-run command side effects or cause duplicate outbound delivery. + +4. **Parallel delivery retries.** + - PRT-043 section "Outbound delivery intent and outcome" says retries must not duplicate sends, but does not require single-flight, locking, terminal readback, or conflict behavior. + - SellerAgent already models lifecycle guards and terminal recovery in `/Users/deksden/Documents/_Projects/seller-agent/apps/workflow/workflows/reply-job.ts` workflow error path, which is a useful product-local pattern. + - Patch direction: require adapters to perform terminal-result readback before send, acquire product-local single-flight/lock where available, and treat concurrent attempts with the same idempotency key as `delivery_duplicate_suppressed` or `delivery_idempotency_conflict`, not as independent sends. + +5. **Post-send finalization failure.** + - SellerAgent explicitly handles delivered-but-finalization-failed as failed delivery in `/Users/deksden/Documents/_Projects/seller-agent/apps/workflow/workflows/reply-job.ts` via the post-send finalization enrichment path. + - PRT-043 does not call out this class, but it is important for incident diagnostics: customer-visible delivery may have happened even if persistence/finalization failed. + - Patch direction: add `delivery_finalization_failed_after_send` as a terminal anomaly with incident-monitor eligibility, no automatic resend unless product-local proof says it is safe. + +## Suggested exact patch direction + +1. **Patch PRT-043 section "Command result and failure model".** + - Keep command result kinds as-is. + - Add a second interaction failure taxonomy: `render_error`, `render_degraded`, `threading_resolution_failed`, `threading_fallback_used`, `delivery_provider_transient`, `delivery_provider_permanent`, `delivery_retry_exhausted`, `delivery_duplicate_suppressed`, `delivery_idempotency_conflict`, `delivery_finalization_failed_after_send`, `config_resolution_failed`, and `policy_resolution_failed`. + - For each class, define default log level, retryability, user-facing behavior, and whether incident-monitor capture is expected. + +2. **Patch PRT-043 section "Outbound delivery intent and outcome".** + - Make `idempotencyKey` mandatory or require a documented provider/product derivation. + - Add `idempotencyKeyHash`, `retryOrdinal`, `maxAttempts`, `providerAttemptCount`, `terminalReadbackRef`, and `deliveryOutcomeKind` as diagnostic fields. + - Require terminal readback/single-flight behavior for parallel attempts and repeated retries. + - Add explicit handling for post-send finalization failure and partial failure. + +3. **Patch PRT-043 section "Configuration source of truth and compatibility".** + - Add `effectiveConfigVersion` / `effectivePolicyVersion` / `effectiveConfigHash` guidance. + - State that one invocation uses one effective snapshot across policy evaluation, render, threading, and delivery. + - Define safe vs unsafe delivery suppression. + +4. **Patch PRT-043 section "Threading intent".** + - Define `ThreadingResolution` fields: requested mode, effective mode, fallback used, fallback kind, fallback reason code, provider target ref state, required vs optional, and user-visible impact. + - Require `compat_fallback_used` or `threading_intent_failed` details to include `fallbackKind` where fallback occurs. + +5. **Patch PRT-043 section "Logging-first diagnostics".** + - Decide event ownership: either product-local runtime events or shared control-plane events. + - Align with `.memory-bank/spec/operations/observability-and-incident-diagnostics.md` baseline names by adding or mapping `channel_event_*`, `retry_scheduled`, `retry_exhausted`, `policy_resolution_failed`, `delivery_plan_completed`, and `delivery_plan_failed`. + - If shared, update the plan to include changes to `packages/core/src/control-plane/observability.ts`, `packages/api-contract/src/control-plane/vocabulary.ts`, and schema tests. If product-local, explicitly say these PRT events are not accepted by the control-plane API schemas. + - Add optional product-local `incident_event_id` / `incident_ref` without coupling bot-platform to Sentry or another SDK. + +6. **Patch PRT-043 verification matrix.** + - Add tests for duplicate inbound provider event suppression, duplicate email `Message-ID` handling, config update during dispatch, stale menu projection, parallel delivery retry with same idempotency key, retry exhaustion, post-send finalization failure, fallback event schema details, and redaction of raw command args/email bodies/Telegram messages/provider headers. + diff --git a/.tasks/prt-043-protocol-review-phase-1/204-testing-scenarios-quality.report.md b/.tasks/prt-043-protocol-review-phase-1/204-testing-scenarios-quality.report.md new file mode 100644 index 0000000..a0aa3b2 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/204-testing-scenarios-quality.report.md @@ -0,0 +1,76 @@ +# PRT-043 Testing, Scenarios, Quality Gates Review + +## Summary verdict + +PRT-043 is directionally strong, but it is not yet specific enough for phase-1 verification. The protocol names the right classes of checks, yet the current verification matrix still reads like a policy outline rather than an executable test plan, and it does not pin the new behavior to enough concrete scenario ids or existing helper surfaces. + +## Missing / weak tests + +- The only current `channel-runtime` tests are the four pure-helper cases in `/Users/deksden/Documents/_Projects/bot-platform/packages/channel-runtime/src/channel-runtime.spec.ts:53-115`: visibility filtering, markdown-to-plain-text rendering, message splitting, and invalid `maxLength`. +- That leaves the phase-1 promises in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:653-670` uncovered for: + - actor/channel allow-deny precedence; + - safe command failure envelopes; + - threading intent and fallback shapes; + - delivery idempotency/correlation fields; + - redaction-safe observability event construction. +- The protocol’s own quality gap list already admits the missing behavior: policy precedence, channel-neutral command parsing, reply-thread fallback, duplicate-send constraints, and anti-abuse hooks are all called out in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:90-100`, but there are no tests yet that exercise those cases. +- I did not find adjacent `*.spec.ts` or `*.test.ts` coverage around the existing product helpers that the protocol should be reusing: + - `/Users/deksden/Documents/_Projects/docoved-agent/scripts/_support/docoved-telegram-command-runtime.ts:12-39,41-68,147-306` + - `/Users/deksden/Documents/_Projects/docoved-agent/scripts/_support/docoved-in-process-acceptance-harness.ts:20-40` + - `/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/telegram-commands.ts:39-68,168-317` + - `/Users/deksden/Documents/_Projects/seller-agent/apps/server/src/telegram/control-plane-support.ts:19-115` + +## Missing scenario anchors + +- The verification matrix is still generic for `command-framework`: `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/verification-matrix.md:64-75` points that row at `scenarios/contracts/index.md` and the scenario matrix, but it does not name a concrete scenario doc the way `runtime-kernel` does. +- The protocol’s Docoved adoption section is still too vague at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:526-543`. It says to “update Docoved Memory Bank and hosted beta scenarios,” but it does not explicitly anchor the work to the repo-local scenarios that already exist in Docoved: + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/scenarios/index.md:83-95` includes `SCN-201`, `SCN-202`, `SCN-203`, `SCN-204`, and `SCN-211`. +- SellerAgent has a concrete capability anchor already, but the protocol does not cite it: + - `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/scenarios/SCN-053-telegram-observed-user-capture-and-employee-verification-flow.md:23-30,80-108` covers observed-user capture, verification, revocation, and stable rebind by Telegram `user_id`. +- The specific edge cases you asked about are still missing as explicit scenario coverage in the protocol: + - unauthorized email sender; + - ordinary email that is not a command; + - repeated webhook replay; + - duplicate delivery / send idempotency; + - policy fallback; + - menu projection drift. +- `SCN-211` is the closest existing Docoved anchor for command-policy/projection behavior, but the protocol does not currently tie its verification bullets to that id or to any new dedicated idempotency/fallback scenario. + +## Quality gate improvements + +- Split the checks into three clearly labeled lanes, because the protocol currently blends them: + - local framework/package checks; + - product-local checks; + - hosted beta checks. +- The repo only exposes build/typecheck gates today: + - root scripts in `/Users/deksden/Documents/_Projects/bot-platform/package.json:6-14`; + - package publish gate in `/Users/deksden/Documents/_Projects/bot-platform/packages/channel-runtime/package.json:38-42` via `prepack`. + There is no lint script or test runner wired at root, so the protocol should not imply those exist unless they are added. +- For release-package validation, `prepack` is the current concrete publish gate for `@dd-bot-platform/channel-runtime`, so the protocol should say “build/typecheck plus package prepack or pack dry-run” rather than just “CI/package checks.” +- Hosted beta checks should stay limited to cases that actually need live lane proof: + - `Re:` / thread-header behavior; + - webhook delivery / reply-target behavior; + - live command authorization and denial; + - delivery logs/correlation on the deployed beta lane. + Everything else should remain local and deterministic. +- The host-layer rules already exist in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/scenarios/hosted-beta-execution-model.md:1-54` and `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/operations/hosted-beta-acceptance-contract.md:1-54,75-107`; the protocol should explicitly name `beta_api` versus `beta_ui` rather than saying “hosted beta verification” generically. + +## Suggested exact patch direction + +- In `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:718-757`, replace the current high-level verification matrix with a mapping like: + - framework local: policy precedence, parse/result/failure envelopes, threading/delivery serialization, redaction-safe observability; + - Docoved local: Telegram/email parser behavior, ordinary-email-not-command, unauthorized sender denial, reply-thread fallback; + - Docoved hosted beta: `SCN-201`, `SCN-202`, `SCN-204`, and `SCN-211`; + - SellerAgent local: role/capability projection and menu drift against `/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/telegram-commands.ts:211-317`; + - SellerAgent hosted beta: `SCN-053` plus the command-policy/release-control regressions. +- In `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:526-543`, add explicit bullets for: + - ordinary email questions must not become commands; + - repeated webhook / duplicate delivery must be idempotent or visibly suppressed; + - policy fallback must be observable; + - menu projection must be treated as derived, not authoritative. +- In `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:653-670`, tighten phase-1 exit criteria so they require concrete tests for: + - allow/deny precedence across actor, channel kind, and channel instance; + - `not_a_command`, `access_denied`, `rate_limited`, and `unsupported_channel` result kinds; + - `ThreadingIntent` fallback/required-target behavior; + - `OutboundDeliveryIntent` / `OutboundDeliveryResult` correlation and idempotency fields. +- If the intent is to add linting, introduce the script first; otherwise keep the phase-1 gate to build/typecheck plus the package publish dry-run that already exists. diff --git a/.tasks/prt-043-protocol-review-phase-1/205-ops-release-deployment-gitflow.report.md b/.tasks/prt-043-protocol-review-phase-1/205-ops-release-deployment-gitflow.report.md new file mode 100644 index 0000000..080d7f6 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/205-ops-release-deployment-gitflow.report.md @@ -0,0 +1,46 @@ +# PRT-043 Ops / Release / Deployment Review + +## Summary Verdict + +PRT-043 is **close but not ops-complete**. It already covers commit/push discipline, hosted beta gating, rollback hygiene, and release-traceability basics, but it still needs one explicit end-to-end release/deploy/publish sequence and one explicit “no migrations/backups” guard before it can be treated as fully operational for beta/prod handoff. + +### Question Readout + +- **Q1**: partial — `PRT-043` says when to commit, push, and deploy beta in `.../PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:759-778`, but it does not say when to version or publish packages. +- **Q2**: mostly yes — it says not to trigger hosted builds “just to see what happens” and to push only when ready, but it does not explicitly tie that to versioned release commits or block unnecessary preview/publish loops. +- **Q3**: partial — package pinning is stated in `...:595-603`, but the release sequence and consumer-cutover order are not explicit. +- **Q4**: partial — compatibility is mentioned, but rollback-by-version-revert for consumers is missing. +- **Q5**: no — DB/UI are non-goals, but the protocol never clearly says migrations/backups are out of scope unless a later protocol adds them. +- **Q6**: mostly yes — Docoved and SellerAgent hosted beta checks are listed in `...:738-757`, but the stable alias / hosted-status readback gate should be stated more explicitly. +- **Q7**: yes, but only at closure — `...:774-776` requires GitHub/CI and Vercel/hosting verification after pushes/deployments. +- **Q8**: mostly yes — the lessons rules are fine at a generic level, but they should explicitly route release/deploy/rollback lessons back into the owning runbook or Memory Bank section. +- **Q9**: see the patch direction below. + +## Ops / Release Gaps + +- `PRT-043`’s `## Operations and git-flow` section (`/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:759-778`) covers commit, push, and beta deployment timing, but it never defines the package-release order. Compare that with the explicit release flow in `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/guides/reference/npm-package-release-runbook.md:54-103` and `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/guides/reference/npm-package-release-runbook.md:54-103`. +- `PRT-043`’s `## Package strategy` (`...:595-603`) says product repos must pin released versions, but it does not say rollback happens by reverting the pinned version first. That omission is inconsistent with `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/operations/private-registry-package-bridge.md:128-143`. +- `PRT-043` excludes framework UI/admin surfaces and framework-owned DB tables in `...:513-524` and `...:800-806`, but it still never states that migrations/backups are not part of this protocol. Because the same document uses “migration compatibility” language elsewhere (`...:68, 423-427, 597`), the scope boundary should be made explicit. +- `PRT-043`’s lessons section (`...:780-798`) is directionally fine, but it should name release/deploy/rollback lessons as required durable outputs, not only docs-missing/debugging learnings. + +## Deployment / Rollback Risks + +- The hosted beta checks for Docoved and SellerAgent are present (`...:738-757`), but the protocol does not require an explicit stable-alias or live-hosted truth readback before closure. That is weaker than the framework baseline in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/operations/deployment-architecture.md:69-104` and `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/operations/hosted-beta-acceptance-contract.md:49-102`. +- `do not trigger hosted builds just to “see what happens”` (`...:771`) is good, but the doc still leaves room for unnecessary preview/publish cycles that are not tied to a versioned release commit. +- Package-adoption rollback is under-specified. The safe rule is “revert the pinned package version first,” as documented in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/operations/private-registry-package-bridge.md:128-143`; `PRT-043` should say that directly so consumers do not improvise source-copy rollbacks. +- The Docoved product runbook already has the exact manual beta/prod rollout and rollback sequence in `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-hosted-bootstrap-runbook.md:205-233, 486-540, 573-590`. `PRT-043` should reference that sequence instead of stopping at generic “deploy beta only when ready” wording. + +## Suggested Exact Patch Direction + +- Add a new `## Release, deploy, and rollback sequence` subsection under `## Operations and git-flow` in `PRT-043`. + - Required order should be explicit: local checks → package versioning if applicable (`pnpm changeset version`) → commit the versioned state → push/PR merge → CI/package readiness → beta deploy → live alias/readback verification → hosted beta proof → `main` promotion → prod deploy/readback → rollback by alias/version revert if needed. +- Expand `## Package strategy` to say: + - released packages are consumed only through pinned versions; + - consumer rollback is a version revert, not source copying; + - compatibility-sensitive changes must cite the package bridge and consumer adoption docs. +- Add one explicit non-goal sentence near `## Non-goals`: + - “No DB schema migrations, backups, or restore workflows are introduced by this protocol; any later data-path change requires a separate protocol.” +- Tighten `## Lessons learned and insights` so release/deploy/rollback lessons are promoted into the owning Memory Bank section and referenced from the relevant runbook, not left only in `.tasks/`. +- If you want this protocol to stand alone operationally, mirror the same release-order wording into the Docoved and SellerAgent release docs already serving as the runbook SSoT: + - `/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/operations/docoved-hosted-bootstrap-runbook.md:205-233, 486-540` + - `/Users/deksden/Documents/_Projects/seller-agent/.memory-bank/spec/operations/deployment-architecture.md:167-188, 323-339` diff --git a/.tasks/prt-043-protocol-review-phase-1/206-product-adoption-side-effects.report.md b/.tasks/prt-043-protocol-review-phase-1/206-product-adoption-side-effects.report.md new file mode 100644 index 0000000..7016ad5 --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/206-product-adoption-side-effects.report.md @@ -0,0 +1,32 @@ +# PRT-043 Product Adoption / Side Effects Review + +## Summary Verdict +- Directionally correct, but not yet fully closed for implementation. +- The protocol covers the right adoption surfaces, but it still leaves a real migration hazard around command-policy authority and a couple of proof-slice boundaries that should be pinned before coding. + +## Docoved Adoption Findings +- Yes: the protocol explicitly covers Telegram + email command parity, canonical response documents, normal answer flow, reply-threading, unauthorized actors, and ordinary email-question safety in `PRT-043:526-543`. +- Threading is also handled at the right level: per-channel-instance `reply_to_origin` behavior, fallback, and missing/stale reply-target handling are spelled out in `PRT-043:329-366`. +- The gap is proof scope, not intent: the current Docoved runtime adoption note still says hosted beta verification is `N/A` because no command/threading behavior changed yet (`/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md:103-114`), so `PRT-043` needs explicit beta proof cases for ordinary email-question non-command classification and unauthorized sender denial. +- The Docoved beta tooling already treats command policy and command sync as an operational side effect: it previews `allowDirectCommands`, `allowDebugCommands`, and `commandAccessPolicy`, then resyncs observed users and Telegram commands (`/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-beta-telegram-commands.ts:412-651`). + +## SellerAgent Adoption Findings +- Yes: the protocol preserves current privileged-command safety by requiring existing gates to survive adoption and by keeping release-control regression-free (`PRT-043:554-569`, `PRT-043:746-757`). +- The current SellerAgent command surface is already capability-based: Telegram command availability is derived from actor class + workspace role + debug policy, and release-control commands stay behind preview/confirm flows (`/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/telegram-commands.ts:147-208`, `:2487-2533`, `:2598-2665`). +- The current schema still exposes multiple writable knobs that can drift: `channel.commandAccessPolicy` exists on the channel record while Telegram integration flags still include `allowDirectCommands` and `allowDebugCommands` (`/Users/deksden/Documents/_Projects/seller-agent/packages/api-contract/src/operations.ts:1588-1618`, `:1149-1174`). +- That makes the protocol’s compatibility rule essential, not optional: legacy `commandAccessPolicy` must be treated as migration input only, or SellerAgent will have two editable command-policy authorities in practice (`PRT-043:422-427`). + +## Cross-Product Side Effects +- Command menu sync is a real behavioral side effect, not just presentation. `PRT-043` correctly says menu/help projection is not authority (`PRT-043:260-271`), and the Docoved beta tool demonstrates why: policy changes can trigger command resync plus snapshot verification (`/Users/deksden/Documents/_Projects/docoved-agent/scripts/docoved-beta-telegram-commands.ts:443-651`). +- Channel config drift is covered conceptually by the compatibility rules, but the protocol should say more explicitly that one writable source is canonical and all others are compatibility reads (`PRT-043:406-427`). +- External/unknown-user handling is covered well: the protocol requires default denial, bounded error messages, and no menu projection for unknown users unless public commands are explicitly enabled (`PRT-043:499-511`). +- Beta-specific bindings are mentioned, but should be called out as proof targets, not assumed defaults: Docoved names `docoved-beta-main` and `ask@beta-mail.docoved.pro` in its adoption note (`/Users/deksden/Documents/_Projects/docoved-agent/.memory-bank/spec/runtime/docoved-channel-runtime-adoption.md:89-114`). +- SellerAgent’s command catalog remains product-owned, and the shared protocol should not try to absorb those menus into platform code (`/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/telegram-commands.ts:168-220`). + +## Suggested Exact Patch Direction +- In `PRT-043` under `Configuration source of truth and compatibility`, add one sentence that `commandAccessPolicy` is legacy migration input only, and name exactly one canonical writable authority per product. +- In `PRT-043` under `Product adoption: Docoved`, add explicit first-slice acceptance for ordinary email-question non-command classification and unauthorized sender denial. +- In `PRT-043` under `Product adoption: SellerAgent`, split the proof order into read-only diagnostics/readback first, then release-control mutation; do not take the mutation commands into the minimum proof slice. +- In `PRT-043:810-817`, resolve the open questions that still matter here: first Docoved parity commands, minimum SellerAgent beta subset, shared vs SellerAgent-only delivery fields, and the exact threading config shape. +- Update the product Memory Bank docs the protocol already names: `FT-015-10`, `FT-016-05`, `EP-015`, `EP-016`, `auth-and-access.md`, `telegram-channel-architecture.md`, `business-profile-publish-runbook.md`, and the relevant scenario/verification docs. +- Add one explicit SellerAgent adoption note somewhere in the SellerAgent Memory Bank that normalizes command naming, especially `/use_release` in code versus the `/use-release` spelling used in planning prose (`/Users/deksden/Documents/_Projects/seller-agent/packages/core/src/telegram-commands.ts:2487-2533`). diff --git a/.tasks/prt-043-protocol-review-phase-1/207-ui-db-scope-storage.report.md b/.tasks/prt-043-protocol-review-phase-1/207-ui-db-scope-storage.report.md new file mode 100644 index 0000000..4d94c4b --- /dev/null +++ b/.tasks/prt-043-protocol-review-phase-1/207-ui-db-scope-storage.report.md @@ -0,0 +1,31 @@ +# PRT-043 UI/DB/Storage Scope Review + +## Summary verdict + +PRT-043 is mostly correct on scope containment: it keeps framework UI/admin work out of the wave, keeps DB/read-model ownership out of `bot-platform`, and routes product persistence back to the product repos. The protocol is not yet fully sharp enough for a no-scope-creep gate, though: it should explicitly say that current scope does not require migrations, backups, or restore procedures, and it should make the future UI/storage gates more specific so readers do not infer hidden platform storage work from threading/idempotency/config language. + +## UI/Admin scope findings + +- **Yes, UI/Admin is correctly out of scope for the current wave.** `PRT-043` says “No new framework-owned UI or DB tables” in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:84`, repeats “No framework UI/admin surface” and bans shared admin screens, POM objects, framework read-model tables, channel command management UI, and delivery inspection UI in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:513-524`, and restates “No shared UI/admin implementation” in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:800-808`. +- **The future UI gate is directionally right but not specific enough yet.** The protocol says a later shared UI must open “a separate UI protocol with scenario anchors and MBB UI documentation” at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:524`, but it does not say that a later UI wave must also carry screen contracts, POM mapping, and stable `data-testid`. That requirement exists in the scenario guide for GUI/browser automation at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/mbb/scenario-docs-guide.md:211-217`. +- **Product-owned UI/admin is preserved.** The Docoved and SellerAgent adoption sections keep product UI/admin behavior local at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:569-576`, which helps avoid accidental framework UI takeover. + +## DB/storage scope findings + +- **Yes, DB/read-model work is correctly excluded from current scope.** The protocol says no new framework-owned DB tables at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:84`, says “This protocol does not create DB/read-model tables” at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:436`, limits later framework-owned tables/read models to a separate protocol and proven use case at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:444-449`, blocks a `DB/read-model task` in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:645-648`, and repeats “No framework-owned DB/read-model tables” in `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:802-803`. +- **What is still missing is an explicit no-migrations/no-backups statement.** The current wording excludes DB tables, but it never states plainly that this wave needs no schema migrations, backups, or restore procedures. That omission leaves room for accidental storage work to creep in through interpretation. +- **If storage later enters scope, the protocol should point to the persistence boundary spec.** The storage gate should reference `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/spec/runtime/persistence-interface-and-store-boundary.md:29-40` for ownership split, `:57-67` for projection/read-model constraints, and `:82-103` for idempotency and transaction expectations. + +## Hidden persistence risks + +- **Threading introduces an implied lookup requirement, but it is product-owned.** `PRT-043` says adapters own the “persistence lookup needed to find provider message references” at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:351-358`, and it requires per-channel-instance threading config at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:360-366`. That is a real persistence dependency, but it stays on the product side. +- **Delivery idempotency also implies storage, but again product-owned.** The protocol says adapters own “delivery persistence if the product already has it” at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:379-384`, and that every delivery intent should carry or derive an idempotency key at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:386-390`. This is enough to signal persistence concerns, but not enough to suggest a framework table or queue. +- **Config source of truth can hide a snapshot/version requirement.** The one-effective-config-path rule at `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:406-427` is good, but it does not yet spell out whether the effective config is captured as a snapshot/versioned record during dispatch. That should be explicit so later readers do not assume a shared platform config store. +- **Overall risk call:** the persistence implications are documented well enough to keep them out of framework ownership, but not yet explicit enough to prevent readers from inventing hidden framework storage. + +## Suggested exact patch direction + +- **Tighten the UI gate in `UI/Admin stance`.** Add one sentence after `/Users/deksden/Documents/_Projects/bot-platform/.memory-bank/plans/protocols/PRT-043-channel-interaction-runtime-command-render-thread-delivery.md:524` that says current scope adds no UI docs, POM objects, or screen contracts; if UI is later introduced, the owning repo must create a separate UI protocol plus scenario docs with screen contracts, POM mapping, and stable `data-testid`. +- **Add a hard no-storage-work sentence.** In `Logging-first diagnostics` or `Configuration source of truth and compatibility`, add a sentence that current scope requires no migrations, backups, restore procedures, or framework-owned storage artifacts. +- **Make the persistence ownership explicit.** In `Threading intent` and `Outbound delivery intent and outcome`, add a short note that transport-ref lookup, delivery idempotency state, and any config snapshot are product-local persistence concerns, not bot-platform truth. +- **Add a storage future gate.** If storage/read-model work ever enters scope, require a separate storage protocol that cites the persistence boundary spec and names schema/migration/index/transaction responsibilities before any shared storage surface is approved. diff --git a/packages/channel-runtime/CHANGELOG.md b/packages/channel-runtime/CHANGELOG.md index 8d8f574..7e1a956 100644 --- a/packages/channel-runtime/CHANGELOG.md +++ b/packages/channel-runtime/CHANGELOG.md @@ -1,5 +1,16 @@ # @dd-bot-platform/channel-runtime +## 0.3.0 + +### Minor Changes + +- d744e06: Add the first PRT-043 interaction-runtime contracts: product-neutral command-framework helpers in core plus provider-neutral threading and outbound delivery summary contracts in channel-runtime. + +### Patch Changes + +- Updated dependencies [d744e06] + - @dd-bot-platform/core@0.3.0 + ## 0.2.0 ### Minor Changes diff --git a/packages/channel-runtime/package.json b/packages/channel-runtime/package.json index 573d03d..865774f 100644 --- a/packages/channel-runtime/package.json +++ b/packages/channel-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@dd-bot-platform/channel-runtime", "description": "Framework-safe canonical channel response contract and pure render helpers for bot-platform.", - "version": "0.2.0", + "version": "0.3.0", "main": "dist/index.js", "types": "dist/index.d.ts", "exports": { diff --git a/packages/channel-runtime/src/channel-runtime.spec.ts b/packages/channel-runtime/src/channel-runtime.spec.ts index d8146d6..9a3dac5 100644 --- a/packages/channel-runtime/src/channel-runtime.spec.ts +++ b/packages/channel-runtime/src/channel-runtime.spec.ts @@ -1,8 +1,16 @@ import assert from 'node:assert/strict'; import { test } from 'node:test'; -import type { CanonicalResponseDocument } from './index'; +import type { + CanonicalResponseDocument, + OutboundDeliveryIntent, + OutboundDeliveryResultSummary, + OutboundThreadingIntent +} from './index'; import { + classifyOutboundDeliveryTerminalState, + createDefaultThreadingIntent, filterCanonicalResponseDocumentByVisibility, + isOutboundDeliveryTerminalSuccess, renderChannelMarkdownToPlainText, splitRenderedMessageParts } from './index'; @@ -114,3 +122,106 @@ test('channel-runtime split helper rejects invalid maxLength', () => { /positive integer/ ); }); + +test('channel-runtime default threading keeps reply_to_inbound when inbound ref exists', () => { + const intent = createDefaultThreadingIntent( + { mode: 'reply_to_inbound', fallbackMode: 'new_thread' }, + { + inboundTransportMessageRef: 'transport_message_01', + inboundThreadRef: 'thread_01', + supportsReplyToInbound: true + } + ); + + assert.equal(intent.mode, 'reply_to_inbound'); + assert.equal(intent.inboundTransportMessageRef, 'transport_message_01'); + assert.equal(intent.inboundThreadRef, 'thread_01'); +}); + +test('channel-runtime threading fallback can create new_thread when inbound ref missing', () => { + const intent = createDefaultThreadingIntent( + { mode: 'reply_to_inbound', fallbackMode: 'new_thread' }, + { + inboundTransportMessageRef: null + } + ); + + assert.equal(intent.mode, 'new_thread'); +}); + +test('channel-runtime threading fallback can disable threading when unsupported', () => { + const intent = createDefaultThreadingIntent( + { mode: 'reply_to_inbound', fallbackMode: 'none' }, + { + inboundTransportMessageRef: 'transport_message_01', + supportsReplyToInbound: false + } + ); + + assert.equal(intent.mode, 'none'); +}); + +test('channel-runtime delivery summary classifies delivered as terminal success', () => { + const deliveredSummary: OutboundDeliveryResultSummary = { + status: 'delivered', + channelRef: 'channel_01', + target: { + targetRef: 'user_01' + }, + attemptId: 'attempt_01', + transportMessageRef: 'transport_message_02', + traceId: 'trace_01' + }; + + assert.equal(isOutboundDeliveryTerminalSuccess(deliveredSummary), true); + assert.equal(classifyOutboundDeliveryTerminalState(deliveredSummary), 'success'); +}); + +test('channel-runtime delivery summary distinguishes suppressed and failed', () => { + const suppressedSummary: OutboundDeliveryResultSummary = { + status: 'suppressed', + channelRef: 'channel_01', + target: { + targetRef: 'user_01' + }, + attemptId: 'attempt_02' + }; + + const failedSummary: OutboundDeliveryResultSummary = { + status: 'failed', + channelRef: 'channel_01', + target: { + targetRef: 'user_01' + }, + attemptId: 'attempt_03', + diagnostics: { + reasonCode: 'transport_timeout', + summary: 'Send attempt exceeded timeout.' + } + }; + + assert.equal(classifyOutboundDeliveryTerminalState(suppressedSummary), 'suppressed'); + assert.equal(classifyOutboundDeliveryTerminalState(failedSummary), 'failure'); + assert.equal(isOutboundDeliveryTerminalSuccess(suppressedSummary), false); + assert.equal(isOutboundDeliveryTerminalSuccess(failedSummary), false); +}); + +test('channel-runtime public exports include delivery and threading contracts', () => { + const threadingIntent: OutboundThreadingIntent = { + mode: 'none' + }; + + const intent: OutboundDeliveryIntent = { + channelRef: 'channel_01', + target: { + targetAddress: 'operator@example.com' + }, + renderedFormat: 'plain_text', + threading: threadingIntent, + correlationId: 'correlation_01' + }; + + assert.equal(intent.threading.mode, 'none'); + assert.equal(typeof createDefaultThreadingIntent, 'function'); + assert.equal(typeof classifyOutboundDeliveryTerminalState, 'function'); +}); diff --git a/packages/channel-runtime/src/delivery.ts b/packages/channel-runtime/src/delivery.ts new file mode 100644 index 0000000..a672aaf --- /dev/null +++ b/packages/channel-runtime/src/delivery.ts @@ -0,0 +1,73 @@ +import type { ChannelRef, ExecutionRunRef } from '@dd-bot-platform/core'; +import type { ChannelRenderedFormat } from './render'; +import type { OutboundThreadingIntent } from './threading'; + +export type OutboundDeliveryStatus = 'delivered' | 'suppressed' | 'failed'; + +export type OutboundDeliveryTerminalClassification = 'success' | 'suppressed' | 'failure'; + +export interface OutboundDeliveryTarget { + targetRef?: string | null; + targetAddress?: string | null; + threadRef?: string | null; + metadata?: Record; +} + +export interface OutboundDeliveryIntent { + channelRef: ChannelRef; + target: OutboundDeliveryTarget; + documentRef?: string | null; + renderedMessageRef?: string | null; + renderedFormat: ChannelRenderedFormat; + threading: OutboundThreadingIntent; + correlationId?: string | null; + traceId?: string | null; + runId?: ExecutionRunRef | null; + deliveryId?: string | null; + attemptId?: string | null; + extensions?: Record; +} + +export interface OutboundDeliveryDiagnosticsSummary { + reasonCode?: string; + summary?: string; + providerCode?: string; + retryable?: boolean | null; + details?: Record; +} + +export interface OutboundDeliveryResultSummary { + status: OutboundDeliveryStatus; + channelRef: ChannelRef; + target: OutboundDeliveryTarget; + attemptId?: string | null; + deliveryId?: string | null; + transportMessageRef?: string | null; + correlationId?: string | null; + traceId?: string | null; + runId?: ExecutionRunRef | null; + diagnostics?: OutboundDeliveryDiagnosticsSummary; +} + +export function classifyOutboundDeliveryTerminalState( + resultSummary: Pick +): OutboundDeliveryTerminalClassification { + switch (resultSummary.status) { + case 'delivered': + return 'success'; + case 'suppressed': + return 'suppressed'; + case 'failed': + return 'failure'; + default: { + const exhaustiveStatus: never = resultSummary.status; + return exhaustiveStatus; + } + } +} + +export function isOutboundDeliveryTerminalSuccess( + resultSummary: Pick +): boolean { + return classifyOutboundDeliveryTerminalState(resultSummary) === 'success'; +} diff --git a/packages/channel-runtime/src/index.ts b/packages/channel-runtime/src/index.ts index 80cdf6a..4b2f33b 100644 --- a/packages/channel-runtime/src/index.ts +++ b/packages/channel-runtime/src/index.ts @@ -2,5 +2,7 @@ export type { RuntimeUsage } from '@dd-bot-platform/api-contract'; export type { ChannelRef, ExecutionRunRef, IsoTimestamp } from '@dd-bot-platform/core'; export * from './document'; +export * from './delivery'; export * from './errors'; export * from './render'; +export * from './threading'; diff --git a/packages/channel-runtime/src/threading.ts b/packages/channel-runtime/src/threading.ts new file mode 100644 index 0000000..1b9c8f5 --- /dev/null +++ b/packages/channel-runtime/src/threading.ts @@ -0,0 +1,63 @@ +export type OutboundThreadingMode = 'reply_to_inbound' | 'new_thread' | 'none'; + +export type OutboundThreadingFallbackMode = Exclude; + +export interface OutboundThreadingConfig { + mode: OutboundThreadingMode; + fallbackMode?: OutboundThreadingFallbackMode; +} + +export interface InboundThreadingContext { + inboundTransportMessageRef?: string | null; + inboundThreadRef?: string | null; + supportsReplyToInbound?: boolean | null; +} + +export interface OutboundThreadingIntent { + mode: OutboundThreadingMode; + fallbackMode?: OutboundThreadingFallbackMode; + inboundTransportMessageRef?: string | null; + inboundThreadRef?: string | null; +} + +function resolveThreadingFallbackMode( + config: OutboundThreadingConfig +): OutboundThreadingFallbackMode { + return config.fallbackMode ?? 'none'; +} + +export function createDefaultThreadingIntent( + config: OutboundThreadingConfig, + inboundContext?: InboundThreadingContext +): OutboundThreadingIntent { + const baseIntent = { + fallbackMode: resolveThreadingFallbackMode(config), + ...(inboundContext?.inboundTransportMessageRef !== undefined + ? { inboundTransportMessageRef: inboundContext.inboundTransportMessageRef } + : {}), + ...(inboundContext?.inboundThreadRef !== undefined + ? { inboundThreadRef: inboundContext.inboundThreadRef } + : {}) + }; + + if (config.mode !== 'reply_to_inbound') { + return { + mode: config.mode, + ...baseIntent + }; + } + + const inboundTargetMissing = !inboundContext?.inboundTransportMessageRef; + const inboundReplyUnsupported = inboundContext?.supportsReplyToInbound === false; + if (inboundTargetMissing || inboundReplyUnsupported) { + return { + mode: resolveThreadingFallbackMode(config), + ...baseIntent + }; + } + + return { + mode: 'reply_to_inbound', + ...baseIntent + }; +} diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 0a51d58..4c2488a 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,11 @@ # @dd-bot-platform/core +## 0.3.0 + +### Minor Changes + +- d744e06: Add the first PRT-043 interaction-runtime contracts: product-neutral command-framework helpers in core plus provider-neutral threading and outbound delivery summary contracts in channel-runtime. + ## 0.2.0 ### Minor Changes diff --git a/packages/core/package.json b/packages/core/package.json index c92b814..b5d555a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@dd-bot-platform/core", "description": "Framework-safe execution kernel contracts and helpers for bot-platform.", - "version": "0.2.0", + "version": "0.3.0", "main": "dist/index.js", "types": "dist/index.d.ts", "exports": { diff --git a/packages/core/src/command-framework.spec.ts b/packages/core/src/command-framework.spec.ts new file mode 100644 index 0000000..832c8ff --- /dev/null +++ b/packages/core/src/command-framework.spec.ts @@ -0,0 +1,240 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { + createCommandRegistry, + createNotACommandParseResult, + createParsedCommandResult, + dispatchCommand, + evaluateCommandAvailability, + type CommandDefinition, + type CommandEnvelope +} from './command-framework'; + +const BASE_ENVELOPE: CommandEnvelope, string> = { + commandKey: 'diagnostics.read', + rawInput: '/diagnostics', + normalizedArgs: {}, + actor: { + actorType: 'workspace_admin', + actorRef: 'actor-01' + }, + channel: { + channelKind: 'telegram', + channelRef: 'ch-telegram-01' + }, + ownership: { + workspaceRef: 'ws-01', + productInstanceRef: 'pi-01' + }, + correlation: { + correlationId: 'corr-01' + } +}; + +test('command registry rejects duplicate command keys', () => { + const definition: CommandDefinition = { + commandKey: 'diagnostics.read', + handler: () => ({ ok: true }) + }; + + assert.throws( + () => createCommandRegistry([definition, definition]), + /Duplicate command key: diagnostics\.read/ + ); +}); + +test('dispatcher returns unknown_command for unregistered command key', async () => { + const registry = createCommandRegistry([]); + + const result = await dispatchCommand({ + registry, + parseResult: createParsedCommandResult({ + envelope: BASE_ENVELOPE + }), + context: undefined + }); + + assert.equal(result.ok, false); + if (result.ok) { + assert.fail('Expected unknown command failure.'); + } + if ('skipped' in result) { + assert.fail('Expected command failure, received skipped result.'); + } + + assert.equal(result.failureClass, 'unknown_command'); + assert.equal(result.commandKey, 'diagnostics.read'); +}); + +test('availability policy deny overrides allow for actor, channel kind, and channel ref', () => { + const actorDecision = evaluateCommandAvailability({ + policy: { + actorTypes: { + allow: ['workspace_admin'], + deny: ['workspace_admin'] + } + }, + actorType: 'workspace_admin', + channelKind: 'telegram', + channelRef: 'ch-01' + }); + assert.equal(actorDecision.allowed, false); + if (actorDecision.allowed) { + assert.fail('Expected actor deny to override allow.'); + } + assert.equal(actorDecision.reasonCode, 'actor_type_denied'); + + const channelKindDecision = evaluateCommandAvailability({ + policy: { + channelKinds: { + allow: ['telegram'], + deny: ['telegram'] + } + }, + actorType: 'workspace_admin', + channelKind: 'telegram', + channelRef: 'ch-01' + }); + assert.equal(channelKindDecision.allowed, false); + if (channelKindDecision.allowed) { + assert.fail('Expected channel kind deny to override allow.'); + } + assert.equal(channelKindDecision.reasonCode, 'channel_kind_denied'); + + const channelRefDecision = evaluateCommandAvailability({ + policy: { + channelRefs: { + allow: ['ch-01'], + deny: ['ch-01'] + } + }, + actorType: 'workspace_admin', + channelKind: 'telegram', + channelRef: 'ch-01' + }); + assert.equal(channelRefDecision.allowed, false); + if (channelRefDecision.allowed) { + assert.fail('Expected channel ref deny to override allow.'); + } + assert.equal(channelRefDecision.reasonCode, 'channel_ref_denied'); +}); + +test('availability actor allow enables a matching actor type', () => { + const decision = evaluateCommandAvailability({ + policy: { + actorTypes: { + allow: ['employee'] + } + }, + actorType: 'employee', + channelKind: 'email', + channelRef: 'inbox-01' + }); + + assert.equal(decision.allowed, true); + if (!decision.allowed) { + assert.fail('Expected employee actor to be allowed.'); + } + + assert.equal(decision.reasonCode, 'policy_allows'); +}); + +test('availability defaults to deny when no policy is provided', () => { + const decision = evaluateCommandAvailability({ + policy: null, + actorType: 'workspace_admin', + channelKind: 'telegram', + channelRef: 'ch-01' + }); + + assert.equal(decision.allowed, false); + if (decision.allowed) { + assert.fail('Expected missing policy to deny by default.'); + } + assert.equal(decision.reasonCode, 'default_deny'); +}); + +test('dispatcher returns normalized success envelope on handler success', async () => { + const registry = createCommandRegistry([ + { + commandKey: 'diagnostics.read', + availabilityPolicy: { + actorTypes: { + allow: ['workspace_admin'] + } + }, + handler: () => ({ + status: 'ok' + }) + } + ]); + + const result = await dispatchCommand({ + registry, + parseResult: createParsedCommandResult({ + envelope: BASE_ENVELOPE + }), + context: undefined + }); + + assert.equal(result.ok, true); + if (!result.ok) { + assert.fail('Expected dispatch success.'); + } + + assert.equal(result.commandKey, 'diagnostics.read'); + assert.deepEqual(result.payload, { status: 'ok' }); + assert.equal(result.correlationId, 'corr-01'); +}); + +test('dispatcher returns dispatch_error with safe public summary when handler throws', async () => { + const registry = createCommandRegistry([ + { + commandKey: 'diagnostics.read', + availabilityPolicy: { + actorTypes: { + allow: ['workspace_admin'] + } + }, + handler: () => { + throw new Error('SECRET_TOKEN=should-never-leak'); + } + } + ]); + + const result = await dispatchCommand({ + registry, + parseResult: createParsedCommandResult({ + envelope: BASE_ENVELOPE + }), + context: undefined + }); + + assert.equal(result.ok, false); + if (result.ok) { + assert.fail('Expected dispatch error failure.'); + } + if ('skipped' in result) { + assert.fail('Expected command failure, received skipped result.'); + } + + assert.equal(result.failureClass, 'dispatch_error'); + assert.equal(result.publicSummary, 'Command handler failed.'); + assert.equal(result.publicSummary.includes('SECRET_TOKEN'), false); + assert.equal(result.publicSummary.toLowerCase().includes('stack'), false); +}); + +test('dispatcher returns skipped result for not-a-command parse result', async () => { + const registry = createCommandRegistry([]); + const result = await dispatchCommand({ + registry, + parseResult: createNotACommandParseResult(), + context: undefined + }); + + assert.equal(result.ok, false); + if (!('skipped' in result) || !result.skipped) { + assert.fail('Expected skipped not_a_command result.'); + } + assert.equal(result.reasonCode, 'not_a_command'); +}); diff --git a/packages/core/src/command-framework/contracts.ts b/packages/core/src/command-framework/contracts.ts new file mode 100644 index 0000000..6d5ac2c --- /dev/null +++ b/packages/core/src/command-framework/contracts.ts @@ -0,0 +1,583 @@ +import type { ControlPlaneCapabilityFamily } from '../control-plane/capabilities'; +import type { ChannelKind } from '../control-plane/models'; +import type { + ChannelRef, + ExecutionRunRef, + IsoTimestamp, + PrincipalRef, + ProductInstanceRef, + TraceArtifactRef, + WorkspaceRef +} from '../control-plane/refs'; + +export type KnownCommandActorType = + | 'system_admin' + | 'workspace_admin' + | 'employee' + | 'known_external' + | 'unknown_external' + | 'anonymous'; + +export type CommandActorType = KnownCommandActorType | (string & {}); + +export interface CommandActorContext> { + actorType: CommandActorType; + actorRef?: string | null; + principalRef?: PrincipalRef | null; + workspaceRef?: WorkspaceRef | null; + productInstanceRef?: ProductInstanceRef | null; + capabilityFamilies?: ControlPlaneCapabilityFamily[]; + capabilityTags?: string[]; + metadata?: TMetadata; +} + +export interface CommandChannelContext { + channelKind: ChannelKind; + channelRef?: ChannelRef | null; + integrationRef?: string | null; + threadRef?: string | null; + transportMessageRef?: string | null; +} + +export interface CommandOwnershipContext { + workspaceRef?: WorkspaceRef | null; + productInstanceRef?: ProductInstanceRef | null; + tenantRef?: string | null; + scopeRef?: string | null; +} + +export interface CommandCorrelationContext { + requestId?: string | null; + correlationId?: string | null; + executionRunRef?: ExecutionRunRef | null; + traceArtifactRef?: TraceArtifactRef | null; + occurredAt?: IsoTimestamp | null; + metadata?: Record; +} + +export interface CommandEnvelope< + TArgs = Record, + TRawInput = unknown, + TActorMetadata = Record +> { + commandKey: string; + rawInput: TRawInput; + normalizedArgs: TArgs; + actor: CommandActorContext; + channel: CommandChannelContext; + ownership?: CommandOwnershipContext; + correlation?: CommandCorrelationContext; +} + +export interface CommandParseDiagnostic { + code: string; + message: string; + path?: string | null; + details?: Record; +} + +export interface ParsedCommandResult< + TArgs = Record, + TRawInput = unknown, + TActorMetadata = Record +> { + kind: 'parsed'; + envelope: CommandEnvelope; + diagnostics: CommandParseDiagnostic[]; +} + +export interface NotACommandParseResult { + kind: 'not_a_command'; + diagnostics: CommandParseDiagnostic[]; +} + +export interface FailedCommandParseResult { + kind: 'failed'; + summary: string; + diagnostics: CommandParseDiagnostic[]; +} + +export type CommandParseResult< + TArgs = Record, + TRawInput = unknown, + TActorMetadata = Record +> = + | ParsedCommandResult + | NotACommandParseResult + | FailedCommandParseResult; + +export function createParsedCommandResult< + TArgs = Record, + TRawInput = unknown, + TActorMetadata = Record +>(input: { + envelope: CommandEnvelope; + diagnostics?: CommandParseDiagnostic[]; +}): ParsedCommandResult { + return { + kind: 'parsed', + envelope: input.envelope, + diagnostics: input.diagnostics ? [...input.diagnostics] : [] + }; +} + +export function createNotACommandParseResult(input?: { + diagnostics?: CommandParseDiagnostic[]; +}): NotACommandParseResult { + return { + kind: 'not_a_command', + diagnostics: input?.diagnostics ? [...input.diagnostics] : [] + }; +} + +export function createFailedCommandParseResult(input: { + summary: string; + diagnostics?: CommandParseDiagnostic[]; +}): FailedCommandParseResult { + return { + kind: 'failed', + summary: input.summary, + diagnostics: input.diagnostics ? [...input.diagnostics] : [] + }; +} + +export interface CommandValidationDiagnostic { + code: string; + message: string; + path?: string | null; + details?: Record; +} + +export type CommandValidationResult = + | { + ok: true; + } + | { + ok: false; + summary: string; + diagnostics: CommandValidationDiagnostic[]; + }; + +export interface CommandPolicyRuleSet { + allow?: readonly TValue[]; + deny?: readonly TValue[]; +} + +export interface CommandAvailabilityPolicy { + actorTypes?: CommandPolicyRuleSet; + channelKinds?: CommandPolicyRuleSet; + channelRefs?: CommandPolicyRuleSet; +} + +export type CommandAvailabilityDenyReasonCode = + | 'default_deny' + | 'actor_type_denied' + | 'actor_type_not_allowed' + | 'channel_kind_denied' + | 'channel_kind_not_allowed' + | 'channel_ref_denied' + | 'channel_ref_not_allowed'; + +export type CommandAvailabilityAllowReasonCode = 'policy_allows'; + +export type CommandAvailabilityReasonCode = + | CommandAvailabilityDenyReasonCode + | CommandAvailabilityAllowReasonCode; + +export type CommandAvailabilityDecision = + | { + allowed: true; + reasonCode: CommandAvailabilityAllowReasonCode; + } + | { + allowed: false; + reasonCode: CommandAvailabilityDenyReasonCode; + }; + +function includesValue( + values: readonly TValue[] | undefined, + value: TValue | null +): boolean { + if (!values || value === null) { + return false; + } + + return values.some((entry) => entry === value); +} + +export function evaluateCommandAvailability(input: { + policy?: CommandAvailabilityPolicy | null; + actorType: CommandActorType; + channelKind: ChannelKind; + channelRef?: ChannelRef | null; +}): CommandAvailabilityDecision { + const policy = input.policy ?? null; + + if (!policy) { + return { + allowed: false, + reasonCode: 'default_deny' + }; + } + + if (includesValue(policy.actorTypes?.deny, input.actorType)) { + return { allowed: false, reasonCode: 'actor_type_denied' }; + } + + if (includesValue(policy.channelKinds?.deny, input.channelKind)) { + return { allowed: false, reasonCode: 'channel_kind_denied' }; + } + + if (includesValue(policy.channelRefs?.deny, input.channelRef ?? null)) { + return { allowed: false, reasonCode: 'channel_ref_denied' }; + } + + if (policy.actorTypes?.allow && !includesValue(policy.actorTypes.allow, input.actorType)) { + return { allowed: false, reasonCode: 'actor_type_not_allowed' }; + } + + if ( + policy.channelKinds?.allow && + !includesValue(policy.channelKinds.allow, input.channelKind) + ) { + return { allowed: false, reasonCode: 'channel_kind_not_allowed' }; + } + + if (policy.channelRefs?.allow) { + const hasAllowedRef = includesValue(policy.channelRefs.allow, input.channelRef ?? null); + if (!hasAllowedRef) { + return { allowed: false, reasonCode: 'channel_ref_not_allowed' }; + } + } + + return { + allowed: true, + reasonCode: 'policy_allows' + }; +} + +export interface CommandDefinition< + TArgs = unknown, + TResult = unknown, + TContext = unknown, + TRawInput = unknown, + TActorMetadata = Record +> { + commandKey: string; + description?: string; + tags?: string[]; + metadata?: Record; + availabilityPolicy?: CommandAvailabilityPolicy; + validateArgs?: (input: { + args: TArgs; + envelope: CommandEnvelope; + }) => CommandValidationResult; + handler: (input: { + envelope: CommandEnvelope; + context: TContext; + }) => Promise | TResult; +} + +export interface CommandRegistry< + TDefinition extends CommandDefinition = CommandDefinition< + any, + any, + any, + any, + any + > +> { + readonly byCommandKey: ReadonlyMap; +} + +export type CommandRegistryErrorCode = 'duplicate_command_key' | 'unknown_command'; + +export class CommandRegistryError extends Error { + readonly code: CommandRegistryErrorCode; + readonly details: Record; + + constructor(input: { + code: CommandRegistryErrorCode; + message: string; + details?: Record; + }) { + super(input.message); + this.name = 'CommandRegistryError'; + this.code = input.code; + this.details = input.details ?? {}; + } +} + +function cloneCommandDefinition>( + definition: TDefinition +): TDefinition { + return { + ...definition, + ...(definition.tags ? { tags: [...definition.tags] } : {}) + }; +} + +export function createCommandRegistry< + TDefinition extends CommandDefinition +>( + definitions: ReadonlyArray +): CommandRegistry { + const byCommandKey = new Map(); + + for (const definition of definitions) { + if (byCommandKey.has(definition.commandKey)) { + throw new CommandRegistryError({ + code: 'duplicate_command_key', + message: `Duplicate command key: ${definition.commandKey}`, + details: { + commandKey: definition.commandKey + } + }); + } + + byCommandKey.set(definition.commandKey, cloneCommandDefinition(definition)); + } + + return { + byCommandKey + }; +} + +export function listCommandDefinitions< + TDefinition extends CommandDefinition +>( + registry: CommandRegistry +): TDefinition[] { + return [...registry.byCommandKey.values()].map((definition) => + cloneCommandDefinition(definition) + ); +} + +export function getCommandDefinition< + TDefinition extends CommandDefinition +>( + registry: CommandRegistry, + commandKey: string +): TDefinition | null { + const definition = registry.byCommandKey.get(commandKey); + return definition ? cloneCommandDefinition(definition) : null; +} + +export function requireCommandDefinition< + TDefinition extends CommandDefinition +>( + registry: CommandRegistry, + commandKey: string +): TDefinition { + const definition = getCommandDefinition(registry, commandKey); + + if (!definition) { + throw new CommandRegistryError({ + code: 'unknown_command', + message: `Unknown command key: ${commandKey}`, + details: { + commandKey + } + }); + } + + return definition; +} + +export type CommandDispatchFailureClass = + | 'parse_error' + | 'unknown_command' + | 'validation_error' + | 'access_denied' + | 'dispatch_error'; + +export interface CommandDispatchDiagnostic { + code: string; + message: string; + path?: string | null; + details?: Record; +} + +export interface CommandDispatchSuccess { + ok: true; + commandKey: string; + payload: TResult; + correlationId: string | null; +} + +export interface CommandDispatchFailure { + ok: false; + failureClass: CommandDispatchFailureClass; + commandKey: string | null; + publicSummary: string; + correlationId: string | null; + diagnostics: CommandDispatchDiagnostic[]; + details: Record; +} + +export interface CommandDispatchSkipped { + ok: false; + skipped: true; + reasonCode: 'not_a_command'; + commandKey: null; + publicSummary: string; + correlationId: string | null; + diagnostics: CommandDispatchDiagnostic[]; +} + +export type CommandDispatchResult = + | CommandDispatchSuccess + | CommandDispatchFailure + | CommandDispatchSkipped; + +export function dispatchCommand< + TResult = unknown, + TContext = unknown, + TActorMetadata = Record +>(input: { + registry: CommandRegistry< + CommandDefinition + >; + parseResult: CommandParseResult; + context: TContext; + resolveAvailabilityPolicy?: (input: { + definition: CommandDefinition; + envelope: CommandEnvelope; + }) => CommandAvailabilityPolicy | null | undefined; +}): Promise> { + const parseResult = input.parseResult; + + if (parseResult.kind === 'not_a_command') { + return Promise.resolve({ + ok: false, + skipped: true, + reasonCode: 'not_a_command', + commandKey: null, + publicSummary: 'Input is not a command.', + correlationId: null, + diagnostics: parseResult.diagnostics.map((diagnostic) => ({ ...diagnostic })) + }); + } + + if (parseResult.kind === 'failed') { + return Promise.resolve({ + ok: false, + failureClass: 'parse_error', + commandKey: null, + publicSummary: parseResult.summary, + correlationId: null, + diagnostics: parseResult.diagnostics.map((diagnostic) => ({ ...diagnostic })), + details: {} + }); + } + + const envelope = parseResult.envelope; + const correlationId = envelope.correlation?.correlationId ?? null; + const definition = getCommandDefinition(input.registry, envelope.commandKey); + + if (!definition) { + return Promise.resolve({ + ok: false, + failureClass: 'unknown_command', + commandKey: envelope.commandKey, + publicSummary: `Command ${envelope.commandKey} is not registered.`, + correlationId, + diagnostics: [], + details: {} + }); + } + + const validationResult = definition.validateArgs?.({ + args: envelope.normalizedArgs, + envelope + }); + + if (validationResult && !validationResult.ok) { + return Promise.resolve({ + ok: false, + failureClass: 'validation_error', + commandKey: envelope.commandKey, + publicSummary: validationResult.summary, + correlationId, + diagnostics: validationResult.diagnostics.map((diagnostic) => ({ ...diagnostic })), + details: {} + }); + } + + const internalAvailabilityDecision = evaluateCommandAvailability({ + policy: definition.availabilityPolicy ?? null, + actorType: envelope.actor.actorType, + channelKind: envelope.channel.channelKind, + channelRef: envelope.channel.channelRef ?? null + }); + + if (!internalAvailabilityDecision.allowed) { + return Promise.resolve({ + ok: false, + failureClass: 'access_denied', + commandKey: envelope.commandKey, + publicSummary: 'Command is not available for this actor or channel.', + correlationId, + diagnostics: [], + details: { + reasonCode: internalAvailabilityDecision.reasonCode + } + }); + } + + const externalPolicy = input.resolveAvailabilityPolicy?.({ + definition, + envelope + }); + + if (externalPolicy !== undefined && externalPolicy !== null) { + const externalAvailabilityDecision = evaluateCommandAvailability({ + policy: externalPolicy, + actorType: envelope.actor.actorType, + channelKind: envelope.channel.channelKind, + channelRef: envelope.channel.channelRef ?? null + }); + + if (!externalAvailabilityDecision.allowed) { + return Promise.resolve({ + ok: false, + failureClass: 'access_denied', + commandKey: envelope.commandKey, + publicSummary: 'Command is not available for this actor or channel.', + correlationId, + diagnostics: [], + details: { + reasonCode: externalAvailabilityDecision.reasonCode + } + }); + } + } + + return Promise.resolve() + .then(() => + definition.handler({ + envelope, + context: input.context + }) + ) + .then((payload) => ({ + ok: true as const, + commandKey: envelope.commandKey, + payload, + correlationId + })) + .catch((error: unknown) => { + const errorName = error instanceof Error ? error.name : 'UnknownError'; + return { + ok: false, + failureClass: 'dispatch_error', + commandKey: envelope.commandKey, + publicSummary: 'Command handler failed.', + correlationId, + diagnostics: [], + details: { + errorName + } + } satisfies CommandDispatchFailure; + }); +} diff --git a/packages/core/src/command-framework/index.ts b/packages/core/src/command-framework/index.ts new file mode 100644 index 0000000..c7041c4 --- /dev/null +++ b/packages/core/src/command-framework/index.ts @@ -0,0 +1 @@ +export * from './contracts'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 3e63802..7c1a634 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,3 +1,4 @@ export * from './runtime'; export * from './control-plane'; export * from './governed-content'; +export * from './command-framework';