# Conformance Milestone i — defineFeature + brands + auth.signIn proof

> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Ship the type-level seam of the conformance system — branded wrapper types (`Instrumented<F>`, `Captured<F>`, `Audited<F>`), a `defineFeature` manifest helper, and a branded `ProductionUseCase<I, O, M>` binding slot — then prove the seam works end-to-end by rebinding `auth.signIn` through the new slot, and demonstrate a TS error fires when an unwrapped factory is bound.

**Architecture:** Phantom-type brands attached at wrap time (no runtime cost). The manifest is a typed `as const` object; the binding-slot type is derived from the manifest's use-case entry, demanding `Audited<F>` only when `mutates: true && audits.length > 0`. For `auth.signIn` (read-only) the slot is `Instrumented<F> & Captured<F>`; the existing `withSpan ∘ withCapture` composition satisfies it once the brands are attached.

**Tech Stack:** TypeScript (strict), Vitest, Inversify (existing DI container), `@repo/core-shared/instrumentation` (`withSpan`, `withCapture`), `@repo/core-audit` (audit-log impls). No new dependencies.

---

## File structure

### Create
- `docs/work/README.md` — what `docs/work/` is, how it's used
- `docs/work/conformance-system-v1/_epic.md` — epic record
- `docs/work/conformance-system-v1/01-define-feature-helper/_story.md` — first story record
- `packages/core-shared/src/conformance/brands.ts` — `Instrumented<F>` + `Captured<F>` phantom types
- `packages/core-shared/src/conformance/brands.test.ts` — type-level brand assertions
- `packages/core-shared/src/conformance/define-feature.ts` — `defineFeature` helper + `FeatureManifest` / `UseCaseManifest` types
- `packages/core-shared/src/conformance/define-feature.test.ts` — round-trip type inference
- `packages/core-shared/src/conformance/production-use-case.ts` — `ProductionUseCase<I, O, M>` branded slot type
- `packages/core-shared/src/conformance/production-use-case.test.ts` — assignability tests (positive + `@ts-expect-error` negative)
- `packages/core-shared/src/conformance/index.ts` — barrel re-export
- `packages/core-audit/src/with-audit.ts` — `withAudit` use-case wrapper attaching `Audited<F>`
- `packages/core-audit/src/with-audit.test.ts` — wrapper behavior + brand attachment
- `packages/auth/src/feature.manifest.ts` — `authManifest` declaring `signIn`, `signUp`, `signOut`

### Modify
- `packages/core-shared/src/instrumentation/with-span.ts` — return `Instrumented<F>`
- `packages/core-shared/src/instrumentation/with-span.test.ts` — assert brand on return type
- `packages/core-shared/src/instrumentation/with-capture.ts` — return `Captured<F>`
- `packages/core-shared/src/instrumentation/with-capture.test.ts` — assert brand on return type
- `packages/core-shared/src/instrumentation/index.ts` — re-export brand types from `../conformance`
- `packages/core-audit/src/index.ts` — re-export `withAudit` and `Audited`
- `packages/auth/src/di/bind-production.ts` — rebind `signIn` through `ProductionUseCase<...>`

---

## Task 1: Scaffold `docs/work/` skeleton and epic record

This is a documentation-only task. No TDD; no tests. Establishes the address space for everything else in the plan.

**Files:**
- Create: `docs/work/README.md`
- Create: `docs/work/conformance-system-v1/_epic.md`

- [ ] **Step 1: Create `docs/work/README.md`**

```markdown
# docs/work — the local task system

Filesystem-backed Epic/Story/Task hierarchy used by AI agents and humans alike.
See `docs/architecture/agent-first-workflow-and-conformance.md` for the full
design. Until the `work-system-v1` epic ships orchestration tooling, this
folder is human-driven — agents read the files for context, humans flip
checkboxes.

## Layout

- `prds/<date>-<slug>.prd.md` — source PRDs
- `<epic-slug>/_epic.md` — one folder per epic
- `<epic-slug>/<story-slug>/_story.md` — one folder per story
- `<epic-slug>/<story-slug>/<task-slug>.task.md` — one file per task
- `_templates/` — copy-paste templates (added in work-system-v1)
- `_state.json` — derived index (added in work-system-v1)
```

- [ ] **Step 2: Create the epic file `docs/work/conformance-system-v1/_epic.md`**

```markdown
---
id: conformance-system-v1
prd: null
title: Conformance system v1
type: epic
status: in-progress
features: [cross-cutting]
created: 2026-05-12
---

## Goal
Build the feature-conformance enforcement system so AI agents get layered,
sub-second feedback on drift between manifest and code.

## Why
See `docs/architecture/feature-conformance-explainer.html` and
`docs/architecture/agent-first-workflow-and-conformance.md`.

## In scope
- defineFeature helper + brand types
- assertConformance + boot wiring
- AST-aware ESLint rules
- CI drift gate
- Generator updates for manifest + contracts + test stubs
- Documentation rewrite (manifest-first workflow)
- Migration of auth feature as the reference

## Out of scope
- Migration of blog, media, navigation, marketing-pages (Phase 3)
- Sandcastle orchestration (Phase 2: work-system-v1 epic)

## Stories
- [ ] [01 — defineFeature helper + Instrumented/Captured/Audited brands](01-define-feature-helper/_story.md)
- [ ] 02 — `assertConformance` + boot wiring (later plan)
- [ ] 03 — AST-aware ESLint rules (later plan)
- [ ] 04 — CI drift gate (later plan)
- [ ] 05 — Generator emits manifest + contracts + test stubs (later plan)
- [ ] 06 — Documentation rewrite (later plan)
- [ ] 07 — Migrate auth feature reference (later plan)
```

- [ ] **Step 3: Commit**

```bash
git add docs/work/README.md docs/work/conformance-system-v1/_epic.md
git commit -m "docs(work): scaffold docs/work and conformance-system-v1 epic"
```

---

## Task 2: First story record — `01-define-feature-helper/_story.md`

**Files:**
- Create: `docs/work/conformance-system-v1/01-define-feature-helper/_story.md`

- [ ] **Step 1: Write the story file**

```markdown
---
id: 01-define-feature-helper
epic: conformance-system-v1
title: defineFeature helper + Instrumented/Captured/Audited brands
type: technical-story
status: in-progress
feature: core-shared
depends-on: []
blocks: [02-boot-assertions]
---

## Goal
Manifest helper + brand types enable type-level enforcement that every
use-case binding is wrapped with `withSpan` + `withCapture`
(and `withAudit` when mutating with audits declared).

## Why
Compile-time feedback is the cheapest layer and the foundation every other
milestone reads.

## Done when
Compile-time TS2322 fires when an unwrapped factory is bound through
`ProductionUseCase<...>`, and `auth.signIn` is rebound through the new slot.

## In scope
- `Instrumented<F>` and `Captured<F>` brand types in `@repo/core-shared/conformance`
- Brand attachment in `withSpan` and `withCapture`
- `Audited<F>` brand and `withAudit` wrapper in `@repo/core-audit`
- `defineFeature` helper + `FeatureManifest` / `UseCaseManifest` types
- `ProductionUseCase<I, O, M>` branded slot type
- `authManifest` declaring `signIn`, `signUp`, `signOut`
- `auth.signIn` rebound through the branded slot

## Out of scope
- `auth.signUp` / `auth.signOut` rebinding through branded slots (separate tasks within this story or a follow-up story; signUp requires `Audited<F>` once we declare its `audits`)
- Boot-time `assertConformance` (story 02)
- ESLint rules reading the manifest (story 03)
- Generator emitting manifest stubs (story 05)

## Tasks
- [ ] Brand types: `Instrumented<F>` and `Captured<F>`
- [ ] `withSpan` attaches `Instrumented`
- [ ] `withCapture` attaches `Captured`
- [ ] `defineFeature` helper + manifest types
- [ ] `ProductionUseCase<I, O, M>` slot type
- [ ] `withAudit` wrapper + `Audited` brand
- [ ] `authManifest` declaration
- [ ] `auth.signIn` rebound through branded slot
- [ ] Negative test: unwrapped factory rejected at type level
```

- [ ] **Step 2: Commit**

```bash
git add docs/work/conformance-system-v1/01-define-feature-helper/_story.md
git commit -m "docs(work): story 01 — defineFeature helper + brands"
```

---

## Task 3: Brand types `Instrumented<F>` and `Captured<F>`

**Files:**
- Create: `packages/core-shared/src/conformance/brands.ts`
- Create: `packages/core-shared/src/conformance/brands.test.ts`

- [ ] **Step 1: Write the failing test**

`packages/core-shared/src/conformance/brands.test.ts`:

```ts
import { describe, it, expectTypeOf } from "vitest";
import type { Instrumented, Captured } from "@/conformance/brands";

describe("brand types", () => {
  it("Instrumented<F> is structurally F plus a phantom flag", () => {
    type Fn = (n: number) => Promise<string>;
    expectTypeOf<Instrumented<Fn>>().toBeCallableWith(1);
    expectTypeOf<Instrumented<Fn>>().returns.resolves.toEqualTypeOf<string>();
    // The flag is readonly and required for assignability checks.
    expectTypeOf<Instrumented<Fn>["__instrumented"]>().toEqualTypeOf<true>();
  });

  it("Captured<F> is structurally F plus a phantom flag", () => {
    type Fn = (n: number) => Promise<string>;
    expectTypeOf<Captured<Fn>>().toBeCallableWith(1);
    expectTypeOf<Captured<Fn>["__captured"]>().toEqualTypeOf<true>();
  });

  it("brands compose without conflict", () => {
    type Fn = (n: number) => Promise<string>;
    type Both = Instrumented<Fn> & Captured<Fn>;
    expectTypeOf<Both>().toBeCallableWith(1);
    expectTypeOf<Both["__instrumented"]>().toEqualTypeOf<true>();
    expectTypeOf<Both["__captured"]>().toEqualTypeOf<true>();
  });
});
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @repo/core-shared test conformance/brands`
Expected: FAIL — `Cannot find module '@/conformance/brands'`

- [ ] **Step 3: Write the brand types**

`packages/core-shared/src/conformance/brands.ts`:

```ts
/**
 * Phantom-type brands attached at wrap time by `withSpan`, `withCapture`,
 * and `withAudit`. Pure type-level — no runtime cost, no proxy, no
 * `Object.assign`. The conformance system uses these as the type-level
 * seam the binding signature checks; a use-case factory that hasn't been
 * wrapped is not assignable to a `ProductionUseCase<...>` slot.
 */
export type Instrumented<F> = F & { readonly __instrumented: true };
export type Captured<F> = F & { readonly __captured: true };
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @repo/core-shared test conformance/brands`
Expected: PASS, 3 tests.

- [ ] **Step 5: Commit**

```bash
git add packages/core-shared/src/conformance/brands.ts packages/core-shared/src/conformance/brands.test.ts
git commit -m "feat(core-shared/conformance): Instrumented<F> and Captured<F> brand types"
```

---

## Task 4: `withSpan` attaches `Instrumented` brand

**Files:**
- Modify: `packages/core-shared/src/instrumentation/with-span.ts`
- Modify: `packages/core-shared/src/instrumentation/with-span.test.ts`

- [ ] **Step 1: Add the failing brand assertion to `with-span.test.ts`**

Make two changes to `packages/core-shared/src/instrumentation/with-span.test.ts`:

(a) Extend the existing first import line to include `expectTypeOf`. Change:

```ts
import { describe, it, expect, vi } from "vitest";
```

to:

```ts
import { describe, it, expect, expectTypeOf, vi } from "vitest";
```

(b) Add this import line near the other imports at the top of the file:

```ts
import type { Instrumented } from "@/conformance/brands";
```

(c) Append this `describe` block at the end of the file (after the existing `describe("withSpan", …)` block):

```ts
describe("withSpan — brand", () => {
  it("returns an Instrumented<F>", () => {
    const { tracer } = makeRecordingTracer();
    const fn = async (a: number) => a + 1;
    const wrapped = withSpan(tracer, { name: "test.brand", op: "use-case" }, fn);
    expectTypeOf(wrapped).toMatchTypeOf<Instrumented<typeof fn>>();
  });
});
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @repo/core-shared test with-span`
Expected: FAIL — `wrapped` is `(a: number) => Promise<number>`, not assignable to `Instrumented<typeof fn>`.

- [ ] **Step 3: Update `with-span.ts` to return the branded type**

Replace the entire file `packages/core-shared/src/instrumentation/with-span.ts`:

```ts
import type { ITracer, SpanOpts } from "./tracer.interface";
import type { Instrumented } from "../conformance/brands";

export function withSpan<Args extends unknown[], R>(
  tracer: ITracer,
  opts: SpanOpts | ((args: Args) => SpanOpts),
  fn: (...args: Args) => Promise<R>,
): Instrumented<(...args: Args) => Promise<R>> {
  const wrapped: (...args: Args) => Promise<R> = (...args) => {
    const resolved = typeof opts === "function" ? opts(args) : opts;
    return tracer.startSpan(resolved, () => fn(...args));
  };
  // Cast is the only runtime concession — the brand is a phantom type;
  // there is no real `__instrumented` property at runtime.
  return wrapped as Instrumented<(...args: Args) => Promise<R>>;
}
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @repo/core-shared test with-span`
Expected: PASS, all existing tests + the new brand test.

- [ ] **Step 5: Commit**

```bash
git add packages/core-shared/src/instrumentation/with-span.ts packages/core-shared/src/instrumentation/with-span.test.ts
git commit -m "feat(core-shared/instrumentation): withSpan returns Instrumented<F>"
```

---

## Task 5: `withCapture` attaches `Captured` brand

**Files:**
- Modify: `packages/core-shared/src/instrumentation/with-capture.ts`
- Modify: `packages/core-shared/src/instrumentation/with-capture.test.ts`

- [ ] **Step 1: Add the failing brand assertion to `with-capture.test.ts`**

Make two changes to `packages/core-shared/src/instrumentation/with-capture.test.ts`:

(a) Extend the existing first import line to include `expectTypeOf`. Change:

```ts
import { describe, it, expect, vi } from "vitest";
```

to:

```ts
import { describe, it, expect, expectTypeOf, vi } from "vitest";
```

(b) Add this import line near the other imports at the top of the file:

```ts
import type { Captured } from "@/conformance/brands";
```

(c) Append this `describe` block at the end of the file:

```ts
describe("withCapture — brand", () => {
  it("returns a Captured<F>", () => {
    const logger = makeLogger();
    const fn = async (a: number) => a + 1;
    const wrapped = withCapture(logger, { layer: "use-case" }, fn);
    expectTypeOf(wrapped).toMatchTypeOf<Captured<typeof fn>>();
  });
});
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @repo/core-shared test with-capture`
Expected: FAIL — wrapped is not assignable to `Captured<typeof fn>`.

- [ ] **Step 3: Update `with-capture.ts` to return the branded type**

Replace the function in `packages/core-shared/src/instrumentation/with-capture.ts` (keep the docblock as-is; only the function signature + body change):

```ts
import type { ILogger } from "./logger.interface";
import type { Captured } from "../conformance/brands";
import { isReported, markReported } from "./reported-flag";

// (keep the existing docblock here)

export function withCapture<Args extends unknown[], R>(
  logger: ILogger,
  tags: Record<string, string>,
  fn: (...args: Args) => Promise<R>,
): Captured<(...args: Args) => Promise<R>> {
  const wrapped: (...args: Args) => Promise<R> = async (...args) => {
    try {
      return await fn(...args);
    } catch (err) {
      if (!isReported(err)) {
        logger.captureException(err, { tags });
        markReported(err);
      }
      throw err;
    }
  };
  return wrapped as Captured<(...args: Args) => Promise<R>>;
}
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @repo/core-shared test with-capture`
Expected: PASS, all existing tests + the new brand test.

- [ ] **Step 5: Commit**

```bash
git add packages/core-shared/src/instrumentation/with-capture.ts packages/core-shared/src/instrumentation/with-capture.test.ts
git commit -m "feat(core-shared/instrumentation): withCapture returns Captured<F>"
```

---

## Task 6: `defineFeature` helper + manifest types

**Files:**
- Create: `packages/core-shared/src/conformance/define-feature.ts`
- Create: `packages/core-shared/src/conformance/define-feature.test.ts`

- [ ] **Step 1: Write the failing test**

`packages/core-shared/src/conformance/define-feature.test.ts`:

```ts
import { describe, it, expectTypeOf } from "vitest";
import { defineFeature, type FeatureManifest } from "@/conformance/define-feature";

describe("defineFeature", () => {
  it("preserves literal types of a manifest declared with `as const`", () => {
    const manifest = defineFeature({
      name: "auth",
      requiredCores: ["audit"],
      useCases: {
        signIn: {
          mutates: false,
          audits: [],
          publishes: [],
          consumes: [],
        },
        signUp: {
          mutates: true,
          audits: ["user.created"],
          publishes: ["auth.signed-up"],
          consumes: [],
        },
      },
      realtimeChannels: [],
      jobs: [],
    } as const);

    // Literal preservation: name is the literal "auth", not string
    expectTypeOf(manifest.name).toEqualTypeOf<"auth">();
    // Use-case keys preserved
    expectTypeOf(manifest.useCases.signUp.audits).toEqualTypeOf<readonly ["user.created"]>();
    expectTypeOf(manifest.useCases.signUp.mutates).toEqualTypeOf<true>();
    expectTypeOf(manifest.useCases.signIn.mutates).toEqualTypeOf<false>();
  });

  it("FeatureManifest type accepts the shape", () => {
    const manifest = defineFeature({
      name: "blog",
      requiredCores: [],
      useCases: {},
      realtimeChannels: [],
      jobs: [],
    } as const);
    expectTypeOf(manifest).toMatchTypeOf<FeatureManifest>();
  });
});
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @repo/core-shared test define-feature`
Expected: FAIL — module not found.

- [ ] **Step 3: Write `define-feature.ts`**

`packages/core-shared/src/conformance/define-feature.ts`:

```ts
/**
 * Per-use-case manifest entry. Declares what the use case does at the contract
 * level: whether it mutates state, what audit events it emits, what cross-feature
 * events it publishes or consumes. The conformance system reads these to
 * derive binding-slot types and to verify code against manifest declarations.
 */
export type UseCaseManifest = {
  readonly mutates: boolean;
  readonly audits: readonly string[];
  readonly publishes: readonly string[];
  readonly consumes: readonly string[];
};

/**
 * The feature-level manifest. One per feature package, conventionally exported
 * as `<featureName>Manifest` from `src/feature.manifest.ts`.
 */
export type FeatureManifest = {
  readonly name: string;
  readonly requiredCores: readonly string[];
  readonly useCases: { readonly [k: string]: UseCaseManifest };
  readonly realtimeChannels: readonly string[];
  readonly jobs: readonly string[];
};

/**
 * Identity helper that exists purely to widen the input type to satisfy
 * `FeatureManifest` while preserving the literal types of the `as const`
 * input. Downstream types (`ProductionUseCase<I, O, M>`) consume the
 * preserved literals to derive binding-slot brand requirements.
 *
 * Usage:
 *
 *   export const authManifest = defineFeature({ name: "auth", ... } as const);
 */
export function defineFeature<const M extends FeatureManifest>(manifest: M): M {
  return manifest;
}
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @repo/core-shared test define-feature`
Expected: PASS, 2 tests.

- [ ] **Step 5: Commit**

```bash
git add packages/core-shared/src/conformance/define-feature.ts packages/core-shared/src/conformance/define-feature.test.ts
git commit -m "feat(core-shared/conformance): defineFeature helper + manifest types"
```

---

## Task 7: `ProductionUseCase<I, O, M>` branded slot type

**Files:**
- Create: `packages/core-shared/src/conformance/production-use-case.ts`
- Create: `packages/core-shared/src/conformance/production-use-case.test.ts`

- [ ] **Step 1: Write the failing test**

`packages/core-shared/src/conformance/production-use-case.test.ts`:

```ts
import { describe, it, expectTypeOf } from "vitest";
import type { ProductionUseCase } from "@/conformance/production-use-case";
import type { Instrumented, Captured } from "@/conformance/brands";

describe("ProductionUseCase<I, O, M>", () => {
  it("requires Instrumented + Captured for any use case", () => {
    type Manifest = {
      mutates: false;
      audits: readonly [];
      publishes: readonly [];
      consumes: readonly [];
    };
    type Slot = ProductionUseCase<{ x: number }, { y: string }, Manifest>;
    type Wrapped = Instrumented<(input: { x: number }) => Promise<{ y: string }>> &
      Captured<(input: { x: number }) => Promise<{ y: string }>>;

    expectTypeOf<Wrapped>().toMatchTypeOf<Slot>();
  });

  it("a plain factory is NOT assignable to the slot", () => {
    type Manifest = {
      mutates: false;
      audits: readonly [];
      publishes: readonly [];
      consumes: readonly [];
    };
    type Slot = ProductionUseCase<{ x: number }, { y: string }, Manifest>;
    const factory = async (input: { x: number }) => ({ y: String(input.x) });

    // @ts-expect-error — factory has no __instrumented / __captured brand
    const bad: Slot = factory;
    void bad;
  });
});
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @repo/core-shared test production-use-case`
Expected: FAIL — module not found.

- [ ] **Step 3: Write `production-use-case.ts`**

`packages/core-shared/src/conformance/production-use-case.ts`:

```ts
import type { UseCaseManifest } from "./define-feature";
import type { Instrumented, Captured } from "./brands";

/**
 * Type-level binding slot for production use cases. Derived from the manifest
 * entry: every binding must be Instrumented + Captured; mutating use cases
 * that declare audits additionally must be Audited. The Audited brand lives
 * in `@repo/core-audit` because the wrap helper that attaches it depends on
 * `IAuditLog` — feature packages import the merged slot type implicitly
 * by typing their bindings as `ProductionUseCase<I, O, AuthManifest["useCases"]["signIn"]>`.
 *
 * The Audited requirement is encoded conditionally so this type stays usable
 * without depending on core-audit. When `mutates: true` AND `audits` is
 * non-empty, the slot demands a marker type with a `__audited` flag; the
 * concrete `Audited<F>` from core-audit satisfies it.
 */
export type ProductionUseCase<I, O, M extends UseCaseManifest> =
  & Instrumented<(input: I) => Promise<O>>
  & Captured<(input: I) => Promise<O>>
  & (M["mutates"] extends true
      ? M["audits"]["length"] extends 0
        ? unknown
        : { readonly __audited: true }
      : unknown);
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @repo/core-shared test production-use-case`
Expected: PASS, 2 tests.

- [ ] **Step 5: Commit**

```bash
git add packages/core-shared/src/conformance/production-use-case.ts packages/core-shared/src/conformance/production-use-case.test.ts
git commit -m "feat(core-shared/conformance): ProductionUseCase<I, O, M> branded slot type"
```

---

## Task 8: Conformance barrel + package subpath export

**Files:**
- Create: `packages/core-shared/src/conformance/index.ts`
- Modify: `packages/core-shared/src/instrumentation/index.ts`
- Modify: `packages/core-shared/package.json`

- [ ] **Step 1: Create the conformance barrel**

`packages/core-shared/src/conformance/index.ts`:

```ts
export type { Instrumented, Captured } from "./brands";
export type { FeatureManifest, UseCaseManifest } from "./define-feature";
export { defineFeature } from "./define-feature";
export type { ProductionUseCase } from "./production-use-case";
```

- [ ] **Step 2: Add `./conformance` to `packages/core-shared/package.json` exports**

Open `packages/core-shared/package.json` and find the `"exports"` object. Add a new line for `./conformance` next to the existing subpath exports (e.g. immediately after `"./audit"`):

```json
"./conformance": "./src/conformance/index.ts",
```

The resulting `exports` map should include `"./conformance"` alongside the existing `"."`, `"./audit"`, `"./di"`, `"./instrumentation"`, etc.

- [ ] **Step 3: Re-export brand types from instrumentation/index for ergonomics**

Modify `packages/core-shared/src/instrumentation/index.ts` — append at the bottom:

```ts
// Re-export brand types alongside the wrappers that attach them, so callers
// can `import { withSpan, type Instrumented } from "@repo/core-shared/instrumentation"`.
export type { Instrumented, Captured } from "../conformance/brands";
```

- [ ] **Step 4: Verify the package builds**

Run: `pnpm --filter @repo/core-shared typecheck`
Expected: PASS, no errors.

- [ ] **Step 5: Commit**

```bash
git add packages/core-shared/src/conformance/index.ts packages/core-shared/src/instrumentation/index.ts packages/core-shared/package.json
git commit -m "feat(core-shared/conformance): barrel + ./conformance subpath export"
```

---

## Task 9: `withAudit` wrapper + `Audited` brand in `@repo/core-audit`

**Files:**
- Create: `packages/core-audit/src/with-audit.ts`
- Create: `packages/core-audit/src/with-audit.test.ts`
- Modify: `packages/core-audit/src/index.ts`

- [ ] **Step 1: Write the failing test**

`packages/core-audit/src/with-audit.test.ts`:

```ts
import { describe, it, expect, expectTypeOf, vi } from "vitest";
import { withAudit, type Audited } from "@/with-audit";
import type { IAuditLog } from "@/audit-log.interface";

function makeAuditLog(): IAuditLog {
  return {
    record: vi.fn().mockResolvedValue(undefined),
    eraseSubject: vi.fn().mockResolvedValue(undefined),
  };
}

describe("withAudit", () => {
  it("returns an Audited<F>", () => {
    const auditLog = makeAuditLog();
    const fn = async (input: { id: string }) => ({ ok: true });
    const wrapped = withAudit(auditLog, fn);
    expectTypeOf(wrapped).toMatchTypeOf<Audited<typeof fn>>();
  });

  it("passes input and output through unchanged", async () => {
    const auditLog = makeAuditLog();
    const fn = async (input: { id: string }) => ({ ok: true, id: input.id });
    const wrapped = withAudit(auditLog, fn);
    const result = await wrapped({ id: "abc" });
    expect(result).toEqual({ ok: true, id: "abc" });
  });

  it("propagates errors", async () => {
    const auditLog = makeAuditLog();
    const err = new Error("boom");
    const wrapped = withAudit(auditLog, async () => {
      throw err;
    });
    await expect(wrapped({})).rejects.toBe(err);
  });
});
```

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @repo/core-audit test with-audit`
Expected: FAIL — module not found.

- [ ] **Step 3: Write `with-audit.ts`**

`packages/core-audit/src/with-audit.ts`:

```ts
import type { IAuditLog } from "./audit-log.interface";

/**
 * Phantom-type brand attached at wrap time by `withAudit`. The conformance
 * system uses this as the type-level seam for mutating use cases that
 * declare `audits: [...]` in their manifest — without `__audited`, the
 * binding is not assignable to `ProductionUseCase<I, O, M>` when M demands
 * it.
 */
export type Audited<F> = F & { readonly __audited: true };

/**
 * Use-case wrapper applied at DI bind time. In milestone i this is a
 * brand-only attachment: it does not yet automatically call `auditLog.record`.
 * Use cases continue to call `auditLog.record(...)` in their own bodies; the
 * wrapper exists to make "binding was bound through the audit-aware path"
 * type-checkable at compile time.
 *
 * A future story may move auditing logic out of factory bodies and into the
 * wrapper itself (driven by manifest declarations) — but that requires the
 * manifest's `audits[]` entries to fully specify what gets recorded, which
 * is out of scope here.
 */
export function withAudit<Args extends unknown[], R>(
  // The auditLog is part of the signature for two reasons: (1) callers must
  // pass it at bind time, ensuring the dep is available, and (2) future
  // versions of this wrapper will use it to emit audit events from the
  // declarative manifest entry directly.
  auditLog: IAuditLog,
  fn: (...args: Args) => Promise<R>,
): Audited<(...args: Args) => Promise<R>> {
  void auditLog;
  return fn as Audited<(...args: Args) => Promise<R>>;
}
```

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @repo/core-audit test with-audit`
Expected: PASS, 3 tests.

- [ ] **Step 5: Re-export from core-audit barrel**

Append to `packages/core-audit/src/index.ts`:

```ts
export { withAudit, type Audited } from "./with-audit";
```

- [ ] **Step 6: Verify the package builds**

Run: `pnpm --filter @repo/core-audit typecheck`
Expected: PASS.

- [ ] **Step 7: Commit**

```bash
git add packages/core-audit/src/with-audit.ts packages/core-audit/src/with-audit.test.ts packages/core-audit/src/index.ts
git commit -m "feat(core-audit): withAudit wrapper + Audited<F> brand"
```

---

## Task 10: `authManifest` declaration

**Files:**
- Create: `packages/auth/src/feature.manifest.ts`

- [ ] **Step 1: Write the manifest**

`packages/auth/src/feature.manifest.ts`:

```ts
import { defineFeature } from "@repo/core-shared/conformance";

/**
 * The auth feature's conformance manifest. Drives binding-slot types in
 * `di/bind-production.ts` and is read by ESLint, the boot assertion, and
 * the CI drift gate (later milestones).
 *
 * Conventions:
 * - `mutates: true` for any use case that creates, updates, or deletes state
 * - `audits` lists every audit event the use case emits (must match calls
 *   to `auditLog.record(...)` in the factory body — ESLint enforces this
 *   in a later story)
 * - `publishes` / `consumes` cover cross-feature events through `IEventBus`
 */
export const authManifest = defineFeature({
  name: "auth",
  requiredCores: [],
  useCases: {
    signIn: {
      mutates: false,
      audits: [],
      publishes: [],
      consumes: [],
    },
    signUp: {
      mutates: true,
      audits: [],
      publishes: [],
      consumes: [],
    },
    signOut: {
      mutates: true,
      audits: [],
      publishes: [],
      consumes: [],
    },
  },
  realtimeChannels: [],
  jobs: [],
} as const);

export type AuthManifest = typeof authManifest;
```

> Note: `signUp` and `signOut` declare `mutates: true` but empty `audits` to keep this milestone scoped to brand checking. Adding audits is its own task in a future story; the `Audited<F>` requirement only fires when `mutates && audits.length > 0`.

- [ ] **Step 2: Verify the manifest typechecks**

Run: `pnpm --filter @repo/auth typecheck`
Expected: PASS — manifest infers correctly and `AuthManifest` derives without error.

- [ ] **Step 3: Commit**

```bash
git add packages/auth/src/feature.manifest.ts
git commit -m "feat(auth): declare authManifest with signIn/signUp/signOut"
```

---

## Task 11: Rebind `auth.signIn` through `ProductionUseCase<...>`

**Files:**
- Modify: `packages/auth/src/di/bind-production.ts`

- [ ] **Step 1: Locate the existing `signIn` binding**

Read the existing binding block in `packages/auth/src/di/bind-production.ts`. The current pattern is:

```ts
const wrappedSignIn = withSpan(
  tracer,
  { name: "auth.signIn", op: "use-case" },
  withCapture(
    logger,
    { feature: "auth", layer: "use-case", name: "auth.signIn" },
    signInUseCase(repo, authService),
  ),
);
```

There is no explicit slot type today.

- [ ] **Step 2: Add the typed binding for `signIn`**

Replace the `wrappedSignIn` assignment with an explicitly typed slot:

```ts
import type { ProductionUseCase } from "@repo/core-shared/conformance";
import { authManifest, type AuthManifest } from "../feature.manifest";
import type { SignInInput, SignInOutput } from "../application/use-cases/sign-in.use-case";

// ... existing imports ...

// Inside bindProductionAuth, replacing the existing wrappedSignIn assignment:
const wrappedSignIn: ProductionUseCase<
  SignInInput,
  SignInOutput,
  AuthManifest["useCases"]["signIn"]
> = withSpan(
  tracer,
  { name: "auth.signIn", op: "use-case" },
  withCapture(
    logger,
    { feature: "auth", layer: "use-case", name: "auth.signIn" },
    signInUseCase(repo, authService),
  ),
);
```

Place the new imports next to the existing imports at the top of the file. Keep the `void authManifest` no-op or use it (see Step 3) so TypeScript doesn't warn about the unused import — but since `AuthManifest` is referenced in the slot type, only `authManifest` may be unused. If unused, drop the value import and keep only the type:

```ts
import type { AuthManifest } from "../feature.manifest";
```

- [ ] **Step 3: Run typecheck and the auth test suite**

Run: `pnpm --filter @repo/auth typecheck`
Expected: PASS.

Run: `pnpm --filter @repo/auth test`
Expected: PASS, no test regressions.

- [ ] **Step 4: Commit**

```bash
git add packages/auth/src/di/bind-production.ts
git commit -m "feat(auth): bind signIn through ProductionUseCase<I, O, M> branded slot"
```

---

## Task 12: Negative test — unwrapped factory rejected at the type level

**Files:**
- Create: `packages/auth/src/di/bind-production.types.test.ts`

This is a type-only test file that asserts the *failure* of an unwrapped factory to satisfy the branded slot. The `@ts-expect-error` annotation makes the file pass `tsc` only when the suppressed line actually has an error.

- [ ] **Step 1: Write the type test**

`packages/auth/src/di/bind-production.types.test.ts`:

```ts
import { describe, it } from "vitest";
import type { ProductionUseCase } from "@repo/core-shared/conformance";
import type { AuthManifest } from "../feature.manifest";
import type {
  SignInInput,
  SignInOutput,
} from "../application/use-cases/sign-in.use-case";
import { signInUseCase } from "../application/use-cases/sign-in.use-case";

describe("auth.signIn binding slot (type-level)", () => {
  it("rejects an unwrapped factory", () => {
    type Slot = ProductionUseCase<
      SignInInput,
      SignInOutput,
      AuthManifest["useCases"]["signIn"]
    >;

    // Build the unwrapped factory exactly as it would be at the use-case file.
    // It returns a function with no brand attached — must not be assignable.
    const fakeRepo = {} as never;
    const fakeAuth = {} as never;
    const unwrapped = signInUseCase(fakeRepo, fakeAuth);

    // @ts-expect-error — unwrapped factory has no __instrumented / __captured brand
    const _bad: Slot = unwrapped;
    void _bad;
  });
});
```

- [ ] **Step 2: Run typecheck — the `@ts-expect-error` must consume a real error**

Run: `pnpm --filter @repo/auth typecheck`
Expected: PASS. If the line under `@ts-expect-error` does NOT error, tsc will report "Unused '@ts-expect-error' directive." That signals a hole in the brand check.

- [ ] **Step 3: Run the test (no runtime assertions; it just needs to load)**

Run: `pnpm --filter @repo/auth test bind-production.types`
Expected: PASS — the test body has no runtime assertions, so the test passes as long as the module loads.

- [ ] **Step 4: Commit**

```bash
git add packages/auth/src/di/bind-production.types.test.ts
git commit -m "test(auth): assert unwrapped factory rejected at branded slot"
```

---

## Task 13: Final verification + story checkbox

**Files:**
- Modify: `docs/work/conformance-system-v1/01-define-feature-helper/_story.md`
- Modify: `docs/work/conformance-system-v1/_epic.md`

- [ ] **Step 1: Run the full type-check and test suite**

```bash
pnpm typecheck
pnpm test
```

Expected: PASS, no regressions.

- [ ] **Step 2: Run lint to confirm no new violations**

```bash
pnpm lint
```

Expected: PASS, no errors.

- [ ] **Step 3: Verify the boundaries graph still validates**

```bash
pnpm turbo boundaries
```

Expected: PASS.

- [ ] **Step 4: Tick the story's task checkboxes and flip the story status**

Edit `docs/work/conformance-system-v1/01-define-feature-helper/_story.md`:
- Change frontmatter `status: in-progress` → `status: done`
- Change all `- [ ]` task checkboxes in the Tasks section to `- [x]`

- [ ] **Step 5: Tick the story in the epic**

Edit `docs/work/conformance-system-v1/_epic.md`:
- Change `- [ ] [01 — defineFeature helper + Instrumented/Captured/Audited brands](01-define-feature-helper/_story.md)` to `- [x] [01 — defineFeature helper + Instrumented/Captured/Audited brands](01-define-feature-helper/_story.md)`

- [ ] **Step 6: Commit the milestone close**

```bash
git add docs/work/conformance-system-v1/01-define-feature-helper/_story.md docs/work/conformance-system-v1/_epic.md
git commit -m "docs(work): close story 01 — defineFeature + brands + auth.signIn proof"
```

---

## Done — what this leaves behind

- `Instrumented<F>`, `Captured<F>` brands in `@repo/core-shared/conformance`
- `Audited<F>` brand + `withAudit` (skeleton) in `@repo/core-audit`
- `defineFeature` helper + `FeatureManifest` / `UseCaseManifest` types
- `ProductionUseCase<I, O, M>` branded slot type
- `authManifest` declared
- `auth.signIn` bound through the typed slot
- Negative test confirms an unwrapped factory does NOT type-check at the slot
- All existing tests pass; no behavioral changes; pure type-system seam added

## What comes next (separate plans)

- Milestone ii: `assertConformance` boot-time runtime check + wire into all three apps' `bindAll`
- Milestone iii: AST-aware ESLint rules (`manifest-usecase-signature-matches`, `no-undeclared-event-publish`, `no-undeclared-audit`, `required-cores-installed`)
- Milestone iv: `pnpm conformance` CI script (event closure, scaffold drift, required-cores)
- Generator updates: `turbo gen feature` emits `feature.manifest.ts` + contracts + test stubs
- Documentation rewrite: `CLAUDE.md`, `AGENTS.md`, `docs/guides/tdd-workflow.md`, new agent-workflow guide
- Auth migration polish: bind `signUp` / `signOut` through the slot (and add audits, exercising `Audited<F>`)
