# Activix Integration Best Practices Checklist

Use this as the operational checklist for integrating `@x12i/activix` correctly and consistently.

## 1) Ownership and boundaries

- Treat **Activix** as the activity-domain layer:
  - lifecycle semantics (`start` / `in_progress` / `complete` / `fail`)
  - activity contract validation
  - run-context correlation persistence
- Treat **xronox-store** as the data tier:
  - cache, write mode, retry policy, Mongo persistence behavior
  - collection/index management
  - generic primary-key storage mechanics

## 2) Construct once, reuse instance

- Prefer one `Activix` instance per service process (or one shared `XronoxStore` with `skipStoreInit: true`).
- Do not create a new `Activix` per tiny unit of work unless architecture requires it.
- If multi-instance is expected, pass `diagnostics` metadata so logs are self-identifying.

```ts
// Production: omit storageMode when mongoUri is set (defaults to database)
const ax = new Activix({
  mongoUri: process.env.MONGO_URI!,
  collection: 'task-activities',
  diagnostics: {
    owner: '@your-org/your-service',
    component: 'graph-executor',
    instanceLabel: 'worker-main',
    workerId: process.pid.toString(),
  },
});
await ax.init();

// Dev / playground only: explicit automatic probes Mongo once and may fall back to local
// const ax = new Activix({ storageMode: 'automatic', collection: 'task-activities', ... });
```

## 3) Define collection contract explicitly

- Set collection names in code (`collection` or `collections`).
- Keep `primaryKey` and `primaryKeyPrefix` intentional.
- If you index `activityId` uniquely, Activix must always persist a non-null `activityId` (current behavior).
- Ensure store-side visibility matches `purgeAtField` if using soft purge.

## 4) Always pass run context at write time

- `runContext` is runtime context, not constructor config.
- Always pass a real `sessionId` from true upstream when available.
- Forward run context through layers; do not replace inherited correlation IDs.

```ts
const { activityId } = await ax.startRecord({
  runContext: {
    sessionId: request.sessionId,
    jobId: request.jobId,
    taskId: request.taskId,
  },
  outer: {
    input: payload,
    output: null,
    metadata: { type: 'task' },
  },
});
```

## 5) Use lifecycle APIs as intended

- `startRecord()` first; keep returned `activityId`.
- Use the same `activityId` for all follow-ups:
  - `markInProgress(activityId, ...)`
  - `completeRecord(activityId, ...)`
  - `failRecord(activityId, ...)`
  - `patchRecord(activityId, ...)`
  - `getRecord(activityId)`
- Never pass empty IDs; treat missing ID as integration bug and fail fast.

## 6) Respect payload ownership rules

- Integrators should provide domain payload (`outer`/`inner`/`runContext`).
- Do not provide lifecycle-owned fields manually:
  - `activityId` / configured primary key
  - `status`, `startTime`, `endTime`, `duration`
  - `createdAt`, `updatedAt`
  - `error` (except via `failRecord`)

## 7) Validate shape and observability expectations

- `outer` is required and must contain:
  - `input`
  - `output` (or omitted initially and normalized)
  - `metadata` object
- Optional `outer.cost` should use a stable shape:
  - `usd?: number`
  - `tokens?: { input?: number; output?: number; total?: number }`
  - `provider?`, `model?`, `unit?`, `details?`
- Optional `inner` is an array of internal sub-activities. Each item should contain:
  - `input`, `output`, `metadata`
  - `startedAt` (ISO string), `endedAt` (ISO string or null), optional `durationMs`
  - optional `stepId` / `stepName` / `status`
  - optional `cost` with the same shape as `outer.cost`
- Enable logs during rollout:
  - `ENABLE_ACTIVIX_LOGXER=true`
  - `ACTIVIX_LOGS_LEVEL=debug`
  - `XRONOX_STORE_LOG=1`

## 8) Multi-instance init diagnostics

If `storageMode: 'automatic'`, each Activix instance performs:

1. one Mongo probe
2. one store init

Use these fields to distinguish healthy multi-instance behavior from bugs:

- `activixInstanceId`
- `alreadyInitialized`
- `usingInitPromise`
- `initCallCount`

Expected pattern: one probe + one store init per `activixInstanceId`.

## 9) Reliability and retry expectations

- Retry/classification policy belongs to xronox-store.
- For deterministic Mongo failures (e.g. duplicate key), rely on current store behavior/version policy.
- Keep `@x12i/xronox-store` up to date and pin known-good versions in CI.

## 10) Minimum production readiness checklist

- [ ] Single shared Activix instance (or intentional multi-instance with diagnostics metadata)
- [ ] Stable collection configuration committed in code
- [ ] `runContext.sessionId` passed from upstream for correlated runs
- [ ] `startRecord` return value (`activityId`) propagated through full lifecycle
- [ ] Logging flags documented for operations team
- [ ] Integration test path covers start -> progress -> complete/fail
- [ ] Dependency version policy defined for `@x12i/xronox-store`

---

For deeper reference, see:

- `README.md`
- `.docs/run-context-object.md`
- `.docs/session-id-usage.md`
- `.docs/activity-structure.md`
- `.docs/logging-stack.md`
