Skip to content

Hexagonal refactor#321

Draft
ahouseholder wants to merge 103 commits intomainfrom
hexagonal-refactor
Draft

Hexagonal refactor#321
ahouseholder wants to merge 103 commits intomainfrom
hexagonal-refactor

Conversation

@ahouseholder
Copy link
Contributor

@ahouseholder ahouseholder commented Mar 11, 2026

This PR is a major refactoring to bring the code inline with the ports-and-adapters (hexagonal) architecture we have adopted. Significant changes include separating wire format (ActivityStreams 2) objects from core domain (Vultron) objects. These had been tangled previously because the semantic mapping was essentially 1:1. This refactoring allows us to support other protocols for wire formats and transport while still retaining a consistent core that knows the vocabulary of CVD and Vultron.


This pull request updates the AGENTS.md documentation to reflect recent architectural changes, clarify the semantic message processing pipeline, and improve guidance for adding new message types and maintaining layer separation. It also adds a pyright static type checking target to the Makefile. The changes focus on aligning documentation with the current codebase structure, updating terminology, and providing clearer instructions for contributors.

Documentation updates and architecture clarification:

  • Updated the semantic message processing pipeline from three to four stages, explicitly adding the AS2 parser and clarifying the role of each stage. File paths and terminology were revised to match the current codebase organization, especially regarding the move of semantic extraction and handler registration to the wire/as2 and backend/handler_map.py modules, respectively. [1] [2] [3] [4]
  • Clarified handler protocol and function signatures: handlers now accept dispatchable: DispatchEvent and dl: DataLayer as parameters, and access payloads as InboundPayload domain types. Examples and instructions were updated accordingly. [1] [2]
  • Improved guidance for adding new message types, including updated file locations for enums, patterns, handler registration, and tests. The key files map was revised to reflect the new module structure.
  • Refined layer separation and hexagonal architecture sections, specifying the roles of core, wire, and application layers, and clarifying the injection of adapters via ports. [1] [2] [3]
  • Updated naming conventions and type safety guidance, including new recommendations for domain model naming, use of the as_ prefix, and the location of type aliases for string validation. [1] [2]

Developer workflow improvements:

  • Added a pyright static type checking target to the Makefile for improved type safety alongside mypy.

Minor clarifications and corrections:

  • Updated references to test files and clarified the location of activity patterns. [1] [2]
  • Fixed outdated references and improved examples to use the new handler and event types. [1] [2]

These changes ensure that the documentation and development workflow accurately reflect the current architecture and best practices of the codebase.

ahouseholder and others added 30 commits March 10, 2026 13:55
…iggers.py refactor

- Update test count to 777 passing (2026-03-09)
- Mark all PRIORITY-30 tasks complete (P30-4, P30-5, P30-6 were done but not
  reflected in gap analysis or previously-completed list)
- Add Phase PRIORITY-50 as the new top priority, replacing the incorrect
  PRIORITY 150 label from Phase ARCH-1
- Add P50-0: extract domain service layer from triggers.py (1274 lines) into
  vultron/api/v2/backend/trigger_services/ before broader ARCH-1.x work
- Remove duplicate ARCH-1 phase (now absorbed into PRIORITY-50)
- Note TECHDEBT-4 overlap with ARCH-1.1/ARCH-1.3
- Add implementation notes on P50-0 approach and priority rationale

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…o thin routers

- Create vultron/api/v2/backend/trigger_services/ package:
  - _models.py: shared ReportTriggerRequest base (CS-09-002)
  - _helpers.py: shared resolve_actor, resolve_case, not_found, etc.
  - report.py: svc_validate_report, svc_invalidate_report, svc_reject_report, svc_close_report
  - case.py: svc_engage_case, svc_defer_case
  - embargo.py: svc_propose_embargo, svc_evaluate_embargo, svc_terminate_embargo
- Split triggers.py (1274 lines) into three thin routers:
  trigger_report.py, trigger_case.py, trigger_embargo.py
- Delete triggers.py (routers now have zero domain logic)
- Update v2_router.py to register the three new routers
- Split test_triggers.py into test_trigger_report/case/embargo.py
- Add service-layer unit tests in test/api/v2/backend/test_trigger_services.py
  (call service functions directly, independent of HTTP layer)
- 815 tests passing (up from 777 baseline)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ts.py

Separates the domain-layer MessageSemantics enum from the AS2 structural
enums (as_ObjectType, as_TransitiveActivityType, etc.) in vultron/enums.py,
satisfying ARCH-02-001 (V-01).

- Create vultron/core/__init__.py and vultron/core/models/__init__.py
- Create vultron/core/models/events.py containing only MessageSemantics
- Remove MessageSemantics definition from vultron/enums.py; add a
  compatibility re-export so existing code importing from vultron.enums
  continues to work
- Update all 17 direct import sites across vultron/ and test/ to use the
  canonical new location

All 815 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…vity.payload

- Add InboundPayload domain type to vultron/core/models/events.py
- Remove as_Activity import from vultron/types.py; use InboundPayload for payload
- Update behavior_dispatcher.py: build InboundPayload in prepare_for_dispatch,
  remove as_Activity import, use payload.raw_activity in DispatcherBase.dispatch
- Fix verify_semantics in handlers/_base.py to compare dispatchable.semantic_type
  directly instead of re-running find_matching_semantics (ARCH-07-001)
- Update all handler files: activity = dispatchable.payload.raw_activity
- Update tests: wrap activities in InboundPayload, fix mismatch test scenarios

Addresses V-02, V-03 from architecture-review.md (ARCH-01-002).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…(R-03, R-04)

- New vultron/wire/ package with error hierarchy:
  - vultron/wire/errors.py: VultronWireError(VultronError)
  - vultron/wire/as2/errors.py: VultronParseError and subtypes
    (VultronParseMissingTypeError, VultronParseUnknownTypeError,
     VultronParseValidationError)

- vultron/wire/as2/parser.py: wire-layer parse_activity() raises domain
  exceptions instead of HTTPException (R-03, V-06, ARCH-08-001)

- vultron/wire/as2/extractor.py: sole owner of ActivityPattern class, all 37
  pattern instances, SEMANTICS_ACTIVITY_PATTERNS dict, and
  find_matching_semantics() — consolidates vultron/activity_patterns.py and
  vultron/semantic_map.py (R-04, V-05, ARCH-03-001)

- vultron/api/v2/routers/actors.py: parse_activity() is now a thin HTTP
  adapter that delegates to wire parser and maps domain errors to HTTP codes

- vultron/behavior_dispatcher.py: import find_matching_semantics from
  vultron.wire.as2.extractor

- vultron/api/v2/backend/inbox_handler.py: removed raise_if_not_valid_activity
  and VOCABULARY import (V-07 fix); activity-type validation is now entirely
  the wire parser's responsibility

- vultron/activity_patterns.py, vultron/semantic_map.py: converted to
  backward-compat re-export shims

- test/wire/as2/test_parser.py, test_extractor.py: 7 new wire layer tests
- test/api/v2/backend/test_inbox_handler.py: removed test for deleted function

Tests: 822 passed (was 815)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- test/api/v2/backend/test_handlers.py: add dl=None to local test_handler
  signatures in TestVerifySemanticsDecorator, pass dl directly to all
  handler calls (removing monkeypatch of get_datalayer where no longer
  needed), add MagicMock() as dl for reject/log-only handlers
- test/api/test_reporting_workflow.py: update dl fixture to use
  TinyDbDataLayer(db_path=None) for clean in-memory testing, update
  _call_handler to accept and pass dl, update all test calls to pass dl
- test/test_behavior_dispatcher.py: pass mock_dl to DirectActivityDispatcher

Also fix vultron/api/v2/backend/inbox_handler.py: refresh DISPATCHER.dl
from get_datalayer() on each dispatch call so that tests which reset the
DL singleton (e.g. test/api/v2/conftest.py) don't cause demo tests to
see stale DL state via the module-level DISPATCHER.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…pter layer

- Update BehaviorHandler protocol to accept dl: DataLayer parameter
- Update verify_semantics wrapper to forward dl to wrapped function
- Add DataLayer + handler_map injection to DispatcherBase constructor
- Move semantic_handler_map.py logic to vultron/api/v2/backend/handler_map.py
- Keep vultron/semantic_handler_map.py as backward-compat shim
- Remove all get_datalayer() lazy imports from handler function bodies
- Add module-level DataLayer import to each handler file
- Wire up DISPATCHER in inbox_handler.py with injected DL + handler map
- Update tests: pass mock DataLayer directly instead of patching get_datalayer

Addresses ARCH-04-001 (V-09, V-10) from notes/architecture-review.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
824 tests pass. Phase PRIORITY-50 (ARCH-1.1 through ARCH-1.4) is complete.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nd PRIORITY-60 added

- Mark PRIORITY-50 (ARCH-1.1 through ARCH-1.4) as complete in gap analysis
- Add Phase ARCH-CLEANUP with 4 tasks: delete shims (ARCH-CLEANUP-1), move
  AS2 structural enums to wire layer (ARCH-CLEANUP-2), fix V-11/V-12 isinstance
  checks (ARCH-CLEANUP-3), write hexagonal architecture ADR (ARCH-ADR-9)
- Add Phase PRIORITY-60 with 3 tasks: relocate as_vocab to wire layer (P60-1),
  relocate behaviors to core layer (P60-2), stub adapters package (P60-3)
- Update IMPLEMENTATION_NOTES.md with detailed context on remaining shims,
  AS2 enums still in enums.py, V-11/V-12 locations, and P60 sequencing notes
- Test suite confirmed: 824 passed, 5581 subtests (2026-03-10)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove vultron/activity_patterns.py, vultron/semantic_map.py, and
vultron/semantic_handler_map.py (pure re-export shims). Update all
callers to import from canonical locations:

- test/test_semantic_activity_patterns.py: import ActivityPattern and
  SEMANTICS_ACTIVITY_PATTERNS from vultron.wire.as2.extractor
- test/api/test_reporting_workflow.py: import find_matching_semantics
  from vultron.wire.as2.extractor
- test/test_semantic_handler_map.py: use SEMANTICS_HANDLERS from
  vultron.api.v2.backend.handler_map directly; remove shim-specific tests

822 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nums.py

Create vultron/wire/as2/enums.py with as_ObjectType, as_ActorType,
as_IntransitiveActivityType, as_TransitiveActivityType, merge_enums,
as_ActivityType, and as_AllObjectTypes.

Update all callers (4 as_vocab/base/objects/ files, extractor.py, and
3 test files) to import from the new wire-layer location.

Remove AS2 structural enums from vultron/enums.py; it now contains only
OfferStatusEnum, VultronObjectType, and the MessageSemantics re-export.

822 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…1, V-12)

ARCH-CLEANUP-3: Replace isinstance(x, AS2Type) checks in handler/service
code with InboundPayload.object_type and getattr as_type string comparisons.

- handlers/report.py: create_report and submit_report now use
  dispatchable.payload.object_type != 'VulnerabilityReport'; validate_report
  uses getattr(accepted_report, 'as_type', None). Remove local VulnerabilityReport
  imports from those handlers.
- handlers/case.py: update_case uses getattr(incoming, 'as_type', None) ==
  'VulnerabilityCase'; remove local VulnerabilityCase import.
- trigger_services/report.py: _resolve_offer_and_report uses getattr as_type
  check; remove VulnerabilityReport module-level import.
- trigger_services/_helpers.py: resolve_case and update_participant_rm_state
  use getattr as_type checks (VulnerabilityCase import kept for return annotation).
- test/test_behavior_dispatcher.py: remove as_TransitiveActivityType and
  VulnerabilityReport imports; use string 'Create' for as_type assertion;
  use MagicMock for raw_activity in dispatch test to avoid AS2 construction.
- test/api/test_reporting_workflow.py: _call_handler now populates
  InboundPayload.object_type from activity.as_object.as_type (mirrors
  prepare_for_dispatch) so handler type guards work correctly in tests.

822 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…apters)

Documents the decision to structure Vultron around hexagonal architecture,
records the twelve violations V-01 through V-12 identified in the
architectural review, and tracks which were remediated by ARCH-1.1 through
ARCH-1.4 and ARCH-CLEANUP-1 through ARCH-CLEANUP-3. References the
remaining package relocation work deferred to PRIORITY-60 (P60-1 to P60-3).

Indexes ADR-0009 in docs/adr/index.md and marks ARCH-ADR-9 complete in
plan/IMPLEMENTATION_PLAN.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
vultron/as_vocab moved to vultron/wire/as2/vocab. 822 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Copied entire vultron/behaviors/ tree to vultron/core/behaviors/
- Updated all internal imports within moved files
- Updated 3 external callers in vultron/api/ and 8 test files
- Deleted vultron/behaviors/ (no shim retained)
- 822 tests pass

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…arch refactor

- AGENTS.md: update pipeline description (4 stages, correct file paths),
  handler signature (dl: DataLayer param), registry locations, Key Files Map,
  BT node paths (core/behaviors/), as_vocab -> wire/as2/vocab paths,
  architectural constraints, Last Updated date (2026-03-10)
- specs/behavior-tree-integration.md: vultron/behaviors/ -> core/behaviors/
- specs/triggerable-behaviors.md: bridge.py path updated
- specs/message-validation.md: parse_activity and as_vocab paths updated
- specs/code-style.md: as_vocab/base path updated
- specs/case-management.md: as_vocab/objects paths updated
- specs/prototype-shortcuts.md: behaviors/report paths updated

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- specs/architecture.md: update 'Current state' annotations to reflect
  all V-01..V-12 violations remediated (ARCH-1.x and ARCH-CLEANUP-x);
  replace 'Deferred to Post-Prototype' with 'Remediation Status' table
- docs/adr/0009-hexagonal-architecture.md: mark P60-1 and P60-2 as
  complete; update Remaining section to P60-3 only; remove 'Until these
  moves land' text
- notes/architecture-review.md: add status banner noting all 12
  violations remediated; add 'Remediated by' notes to V-01..V-12;
  rename section headers to indicate completion
- notes/architecture-ports-and-adapters.md: update File Layout to show
  current wire/as2/vocab and core/behaviors/ locations; add 'Design
  Note: Use Cases as Incoming Ports' section; fix bare code fences

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- specs/agentic-readiness.md: add MCP Server Adapter section (AR-09-001
  through AR-09-004) as a driving adapter requirement
- notes/bt-integration.md: vultron/behaviors/ -> vultron/core/behaviors/
- notes/codebase-structure.md: rewrite Top-Level Module Reorganization
  section to reflect completed moves; update Enum Refactoring; update
  Vocabulary Examples module path to wire/as2/vocab/
- notes/case-state-model.md: as_vocab/objects/ -> wire/as2/vocab/objects/
- notes/activitystreams-semantics.md: update cross-reference paths
- notes/do-work-behaviors.md: as_vocab/objects/ -> wire/as2/vocab/objects/

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- plan/IDEAS.md: strikethrough MCP item with reference to specs capture
- plan/IMPLEMENTATION_NOTES.md: add capture notes for P60-1, P60-2,
  ARCH-CLEANUP-3, 'use cases as ports' insight, and transitions module note
- docs/reference/code/hexagonal_architecture.md: whitespace lint fixes
- notes/demo-future-ideas.md, notes/federation_ideas.md: whitespace

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- notes/README.md: add missing use-case-behavior-trees.md entry
- notes/codebase-structure.md: rename top-level section to 'pending
  future relocation'; add explicit future cleanup task list (post-P60);
  add 'State Machine Library Consideration' for transitions library
- notes/domain-model-separation.md: add 'DataLayer as a Port, TinyDB
  as a Driven Adapter' section

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ahouseholder and others added 30 commits March 11, 2026 15:12
…22, V-23)

Replace all wire-layer AS2 type imports (as_Offer, as_Accept, as_Service,
VulnerabilityReport, VulnerabilityCase, CaseParticipant, as_Base, as_Actor)
in core/behaviors/ test files with domain types from vultron_types.py.

Changes:
- Add VultronOffer, VultronAccept domain types to vultron_types.py
- Add VultronOutbox + outbox field to VultronCaseActor (required for
  UpdateActorOutbox BT node to call model_dump() via save_to_datalayer)
- Widen VultronCase.case_participants to list[str | VultronParticipant]
- Update test/core/behaviors/report/test_nodes.py
- Update test/core/behaviors/report/test_validate_tree.py
- Update test/core/behaviors/report/test_prioritize_tree.py
- Update test/core/behaviors/case/test_create_tree.py
- Update test/core/behaviors/test_performance.py

All 880 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- notes/architecture-review.md: update V-03-R with P65-4 remediation plan
  (move extract_intent() upstream, delete/relocate prepare_for_dispatch,
  test migration path)
- notes/domain-model-separation.md: add P65-6a section documenting that
  extract_intent() should return a discriminated VultronEvent union
- notes/codebase-structure.md: enrich Enum Refactoring section with target
  layout and migration guidance; add CVDRoles StrEnum design decision;
  add Core Object Modules section (split vultron_types.py)
- specs/code-style.md: rework CS-07 as-prefix policy (wire-only; core uses
  trailing underscore + alias); add CS-11-001 (avoid Any); add CS-12-001
  (domain-centric class names, not wire-format parallels)
- specs/testability.md: add TB-10-001 (PROD_ONLY) for architecture boundary
  tests post-separation
- specs/prototype-shortcuts.md: add PROTO-07-001 deferring performance tests
- AGENTS.md: update Naming Conventions and Validation rules to reference new
  CS-07-002, CS-11-001, CS-12-001
- specs/README.md, notes/README.md: update tables for new content
- plan/IMPLEMENTATION_NOTES.md: mark all items with strikethrough and
  back-references to where they were captured

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…0-4/5, PRIORITY-75

- Mark all P65-1 through P65-7 as complete (V-01–V-23 fully resolved)
- Confirm P65-4 (V-03-R), P65-6b (V-15–19), P65-7 (V-22–23) complete by code inspection
- Add ARCH-DOCS-1: update stale notes/architecture-review.md violation markers
- Add TECHDEBT-13a/b/c: residual V-23 cleanup, V-24 fix, TYPE_CHECKING shim cleanup
- Add TECHDEBT-14: split vultron_types.py into per-type modules
- Add P70-4: move TinyDB DataLayer to adapters/driven/activity_store.py
- Add P70-5: remove api/v2/datalayer shims after P70-4
- Add Phase PRIORITY-75: extract handlers + trigger services → core/use_cases/
  - P75-1: define VultronEvent domain event types
  - P75-2: migrate handlers to use cases
  - P75-3: migrate trigger services to use cases
  - P75-4: update driving adapter stubs to call core use cases
  - P75-5: decide api/v1 disposition (already architecturally compliant)
- Update IMPLEMENTATION_NOTES with refresh #24 findings

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ully resolved

All violations V-01 through V-23 are now resolved:
- V-03-R (P65-4): behavior_dispatcher.py wire imports removed
- V-15/16/17/18/19 (P65-6b): core/behaviors AS2 wire type imports replaced
  with domain types from vultron.core.models.vultron_types
- V-22/23 (P65-7): core BT test files updated to use domain type fixtures

Updated status header block, section headers for 'Active Regressions' and
'New Violations', remediation plans R-09 (complete), R-10 (complete), and
added R-11 (complete P65-2) in place of the open remediation stubs.

Resolves ARCH-DOCS-1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
13a: Replace VulnerabilityReport (wire layer) with VultronReport (core layer)
     in test/core/behaviors/report/test_policy.py. Removes residual V-23.

13b: Remove all adapter-layer imports from wire/as2/vocab/examples/_base.py.
     DataLayer annotation now uses vultron.core.ports.activity_store;
     initialize_examples() requires an explicit DataLayer argument (no default/
     get_datalayer fallback); objects passed directly to datalayer.create().
     Fixes V-24.

13c: Update TYPE_CHECKING guards in vultron/types.py and behavior_dispatcher.py
     to import DataLayer from vultron.core.ports.activity_store instead of the
     api.v2.datalayer.abc shim.

880 tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add vultron/core/ports/delivery_queue.py and vultron/core/ports/dns_resolver.py
as Protocol-only port definitions. The driven adapter stubs in
vultron/adapters/driven/ referenced these files as their port interfaces
but the files did not yet exist.

- DeliveryQueue: enqueue(activity_id, recipient_id) + drain() -> int
- DnsResolver: resolve_txt(domain) -> list[str]

No adapter-layer imports in either file. 880 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move OfferStatusEnum from vultron/enums.py to vultron/core/models/status.py
- Add VultronObjectType to new vultron/core/models/enums.py (core domain layer)
- Update all callers (13 files) to import from new locations
- Delete vultron/enums.py (no remaining callers; MessageSemantics already
  imported directly from vultron.core.models.events by all callers)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The authoritative implementation of the TinyDB-backed DataLayer adapter
now lives in vultron/adapters/driven/activity_store.py.

vultron/api/v2/datalayer/tinydb_backend.py becomes a backward-compat
re-export shim for TinyDbDataLayer, get_datalayer, and reset_datalayer.
All existing callers continue to work via the shim (P70-5 will remove it).

880 tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move vultron/api/v2/datalayer/db_record.py → vultron/adapters/driven/db_record.py
- Delete backward-compat shims: abc.py, tinydb_backend.py, db_record.py
  from vultron/api/v2/datalayer/
- Update ~50 files in vultron/ and test/ to import DataLayer from
  vultron.core.ports.datalayer, TinyDbDataLayer/get_datalayer/reset_datalayer
  from vultron.adapters.driven.datalayer_tinydb, and Record/object_to_record
  from vultron.adapters.driven.db_record
- No module imports from vultron.api.v2.datalayer.* after this change
- 880 tests pass, 0 regressions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ted in P65-6a

All 39 MessageSemantics values have corresponding VultronEvent subclasses in
vultron/core/models/events/. EVENT_CLASS_MAP covers all semantics. No wire or
adapter imports in the events package. 880 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ype loss

When Create(EmbargoEvent) and similar activities are processed, the
activity is stored then rehydrated from the DataLayer. After round-trip,
typed objects (EmbargoEvent, CaseStatus, etc.) lose their subtype and
become base types (as_Event, as_Object), because find_in_vocabulary
returns the base type. This caused isinstance checks to fail and
obj_to_store to be None.

Fix: add optional wire_object/wire_activity parameters to all affected
use case functions. Handlers now pass dispatchable.wire_object and
dispatchable.wire_activity directly, bypassing the round-trip type loss.
Functions fall back to the domain event fields when wire objects are
not provided (backward-compatible).

Also fix add_case_status_to_case and add_participant_status_to_participant
to append the wire status object rather than a string ID, enabling proper
structured access on subsequent reads.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ire.as2.vocab.activities

Renamed 34 classes across case.py, case_participant.py, embargo.py, and
report.py that inherit from vultron.wire.as2.vocab.base classes but did
not end in 'Activity':

case.py:
  AddReportToCase        -> AddReportToCaseActivity
  AddStatusToCase        -> AddStatusToCaseActivity
  CreateCase             -> CreateCaseActivity
  CreateCaseStatus       -> CreateCaseStatusActivity
  AddNoteToCase          -> AddNoteToCaseActivity
  UpdateCase             -> UpdateCaseActivity
  RmEngageCase           -> RmEngageCaseActivity
  RmDeferCase            -> RmDeferCaseActivity
  RmCloseCase            -> RmCloseCaseActivity
  OfferCaseOwnershipTransfer  -> OfferCaseOwnershipTransferActivity
  AcceptCaseOwnershipTransfer -> AcceptCaseOwnershipTransferActivity
  RejectCaseOwnershipTransfer -> RejectCaseOwnershipTransferActivity
  RmInviteToCase         -> RmInviteToCaseActivity
  RmAcceptInviteToCase   -> RmAcceptInviteToCaseActivity
  RmRejectInviteToCase   -> RmRejectInviteToCaseActivity

case_participant.py:
  CreateParticipant          -> CreateParticipantActivity
  CreateStatusForParticipant -> CreateStatusForParticipantActivity
  AddStatusToParticipant     -> AddStatusToParticipantActivity
  AddParticipantToCase       -> AddParticipantToCaseActivity
  RemoveParticipantFromCase  -> RemoveParticipantFromCaseActivity

embargo.py:
  EmProposeEmbargo       -> EmProposeEmbargoActivity
  EmAcceptEmbargo        -> EmAcceptEmbargoActivity
  EmRejectEmbargo        -> EmRejectEmbargoActivity
  ChoosePreferredEmbargo -> ChoosePreferredEmbargoActivity
  ActivateEmbargo        -> ActivateEmbargoActivity
  AddEmbargoToCase       -> AddEmbargoToCaseActivity
  AnnounceEmbargo        -> AnnounceEmbargoActivity
  RemoveEmbargoFromCase  -> RemoveEmbargoFromCaseActivity

report.py:
  RmCreateReport     -> RmCreateReportActivity
  RmSubmitReport     -> RmSubmitReportActivity
  RmReadReport       -> RmReadReportActivity
  RmValidateReport   -> RmValidateReportActivity
  RmInvalidateReport -> RmInvalidateReportActivity
  RmCloseReport      -> RmCloseReportActivity

All 53 consumer files updated (demo scripts, API routers, handlers,
trigger services, examples, tests). Refactored in two stages:
  1. Added FooActivity as Foo aliases in all consumers; tests passed.
  2. Removed aliases and replaced all usages inline; tests passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…onventions between wire activities and core events
…andler tangles

After P75-2, three architectural issues must be resolved before P75-3:
1. Core domain models are less rich than wire models (P75-2a)
2. DispatchActivity carries wire objects; rename to DispatchEvent (P75-2b)
3. Handler layer is vestigial; dispatcher needs formal driving-port model (P75-2c)

Also clarify dispatch (driving port) vs emit (driven port) terminology in NOTES.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add semantically relevant fields absent from Vultron* domain types:
- VultronCaseStatus: name
- VultronParticipantStatus: name, case_status (ID ref); fix vfd_state extraction
- VultronReport: summary, url, media_type, published, updated
- VultronCase: url, published, updated
- VultronActivity: origin
- VultronNote: summary, url
- VultronEmbargoEvent: published, updated

Update extract_intent() to populate all new fields from wire objects.
Also wire up VultronParticipant.case_roles and participant_case_name
extraction (fields existed in domain model but were not being populated).

Add 8 round-trip tests in test/wire/as2/test_extractor.py verifying
each new field survives wire-to-domain translation.

888 tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ields

- Rename DispatchActivity → DispatchEvent in vultron/types.py; add backward-
  compat alias. Update all handler files, dispatcher, inbox_handler, tests,
  specs, AGENTS.md, and docs.
- Remove wire_activity and wire_object fields from DispatchEvent. Remove
  wire-object pass-through params from all use case functions.
- Fix extractor _build_domain_kwargs() to use as_type string comparisons
  instead of isinstance checks against wire subtypes; the parser deserialises
  nested objects as as_Object base class so isinstance checks always failed.
- Fix VultronCaseStatus.pxa_state and VultronParticipantStatus.vfd_state
  serialisers to output .name strings (matching wire type format) so that
  DataLayer round-trips do not produce [0,0,0] list values that wire
  validators cannot coerce back to CS_pxa / CS_vfd.
- Fix add_case_status_to_case and add_participant_status_to_participant to fall
  back to event.status when dl.read() returns a non-model TinyDB Document.
- 888 tests pass, 0 regressions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Split vultron/core/models/vultron_types.py (273 lines, 11 classes) into
individual modules following the wire/as2/vocab/objects/ pattern:

- _helpers.py       — shared _now_utc / _new_urn factories
- case_event.py     — VultronCaseEvent
- case_status.py    — VultronCaseStatus
- participant_status.py — VultronParticipantStatus
- participant.py    — VultronParticipant
- case_actor.py     — VultronCaseActor, VultronOutbox
- activity.py       — VultronActivity, VultronOffer, VultronAccept,
                      VultronCreateCaseActivity
- report.py         — VultronReport
- case.py           — VultronCase
- note.py           — VultronNote
- embargo_event.py  — VultronEmbargoEvent

vultron_types.py is now a backward-compatibility re-export shim so all
existing callers continue to work without change. 887 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant