feat(contracts): Ever Works integration enums, ActorTypeEnum.Agent, EmployeeKindEnum (G-P1-1)

Merged
EV
11d ago
+198-17

What

G-P1-1 (contracts) of the Gauzy ↔ Ever Works integration plan (docs/superpowers/specs/2026-10-15-gauzy-ever-works-integration/06-gauzy-implementation-plan.md in ever-co/homelab). This PR is additive and behaviour-neutral: it only adds enum members. No migration, and no runtime path changes for existing values.

ContractAddition
IntegrationEnumEVER_WORKS = 'Ever_Works'
IntegrationEntityGOAL='Goal', KEY_RESULT='KeyResult', ORGANIZATION_TEAM='OrganizationTeam', STRATEGIC_INITIATIVE='StrategicInitiative', COMMENT='Comment', DOCUMENT='Document', INBOX_ITEM='InboxItem', AGENT='Agent'. The columns are varchar, so no migration is needed.
ActorTypeEnumAgent = 'Agent', stored as 2 by ActorTypeTransformer. System 0 and User 1 are unchanged, and unknown or missing values still map to System 0.
EmployeeKindEnum (new)HUMAN = 'human', AGENT = 'agent'. The employee.kind column ships in the next PR.
BaseEntityEnumGoal, KeyResult, InboxItem, InboxEmail

Every exhaustive use checked

  • GraphQL enum IntegrationEntity (integration/schema/integration.type.gql) is a hand-declared closed vocabulary. It gains the same 8 values, and so does the committed snapshot schema.graphql. Adding enum values is ENUM_VALUE_ADDED, which the schema gate treats as additive. A new spec, integration-entity.vocabulary.spec.ts, pins the GraphQL enum to Object.values(IntegrationEntity) so the two cannot drift.

  • ENTITY_ICONS / ENTITY_LINKS (ui-core/.../favorite/entities-mapping.ts) are Record<BaseEntityEnum, …>. Each new member gets an entry:

    • Goal and KeyResult → /pages/goals;
    • InboxItem and InboxEmail → /pages/dashboard, because the Inbox page comes with the Inbox plugin.

    favorite-links.routes.spec.ts already resolves both targets.

  • MCP server copies of the actor-type vocabulary (packages/mcp-server/src/lib/input-schemas.ts, schema.ts; the MCP server does not depend on @gauzy/contracts) now list Agent too, and actor-type-transform.spec.ts holds both copies to Object.values(ActorTypeEnum) (review: Greptile).

  • ActorTypeEnum has no other exhaustive map. actorType is a nullable int column in all 5 entities (Comment, Mention, Reaction, EntitySubscription, ActivityLog). GraphQL carries it as String, so the schema does not change.

  • IntegrationEnum / IntegrationEntity switches (GitHub, Hubstaff, Upwork, AI UI, integration-tenant delete) all have default branches. The seeds that pick Object.values(...) at random write varchar.

Tests

  • shared/pipes/actor-type-transform.spec.ts (new): values 0, 1 and 2 round-trip, and unknown, null and undefined values map to System as before.
  • integration/integration-entity.vocabulary.spec.ts (new): the GraphQL enum equals the contract enum.
  • Local: core tsc clean for the changed files; the GraphQL snapshot round-trips through printSchema unchanged; the 30 node-only gates of static-checks.yml pass.

Plan item: G-P1-1 (contracts slice). The plugin lane (integration-ever-works, G-P1-2) builds on this.

🤖 Generated with Claude Code