<!-- source: openspec/changes/a4-document-the-11-openspec-agent/design.md -->

---
title: Design — Document openspec-* agents in current/db/entities.md
audience:
  - architect
  - executor
---

# Design — Document openspec-* agents in current/db/entities.md

## 1. Scope of edit

Rationale: The audit finding DA-007 misread the schema as enforcing a CHECK constraint on `forge_findings.agent`. The column is in fact free-text (`agent text NOT NULL`), so the defect is documentary, not structural. Fixing it in `current/db/entities.md` keeps the capability spec aligned with reality without a migration. Alternative — add a CHECK constraint now — was rejected: enumerating slugs in SQL would re-introduce the very brittleness the audit flagged, and the UI already tolerates arbitrary strings.

Contract:
- Single file changed: `openspec/specs/db/entities.md` (or the equivalent `current/db/entities.md` path used by the regen toolchain).
- The `forge_findings` entity section gains:
  - Explicit note that `agent` is free-text (`text NOT NULL`, no CHECK), and the UI renders the raw string.
  - Enumerated list of the **v1 six** and the **11 new `openspec-*` slugs**, marked as "known producers" rather than an exhaustive constraint.
- No schema change. No migration. No code change in `apps/forge` or `packages/db`.

Edge cases / failure modes:
- If `current/db/entities.md` is generated rather than hand-authored, the edit belongs in the upstream source the regen reads (likely the capability spec under `openspec/specs/db/`). Confirm via `pnpm openspec:regen` round-trip before committing.
- If the 11 slugs disagree with what the live `openspec-*` agents actually emit, prefer the runtime truth (grep agent registration) over any list copied from the audit report.

## 2. Agent slug inventory

Rationale: The doc must enumerate concrete strings, not gesture at them. Source of truth is the live agent registry, not the (frozen) audit artefact. The audit report is a starting hint; verification is via codebase grep.

Contract:
- **v1 producers (already documented, retained):** the six slugs currently listed in the entities doc and mirrored in the SQL comment on `forge_findings.agent` (`supabase/migrations/20260507140000_add_forge_tables.sql`). Copy the exact strings from that comment; do not rename.
- **New openspec-* producers (to add):** 11 slugs discovered by:
  1. `rg -l "agent:\s*['\"]openspec-" apps/ packages/`
  2. Cross-check against `.forge/audits/openspec-change-2026-06-02T11-05-51-636Z.json` finding DA-007 payload for the names it observed in the wild.
  3. If counts disagree, codebase wins; note the discrepancy in the PR description.
- Each slug listed with a one-line purpose (≤ 12 words), grouped under a subheading `### openspec-* producers`.

Edge cases / failure modes:
- Slug drift between audit report and current code — resolve in favour of code, flag in PR.
- A slug appears in code but is never invoked — still list it; the contract is "known producers", not "active producers".
- Hyphenation or casing mismatches — preserve exactly as emitted at runtime.

## 3. Free-text contract statement

Rationale: Future auditors (human or agent) will repeat DA-007's mistake unless the doc states the contract loudly. A one-paragraph note next to the enumeration prevents the next round of false-positive critical findings.

Contract:
Add a `> Note` block immediately under the `forge_findings.agent` column description, with this shape (wording may be tightened):

```
> `agent` is free-text (`text NOT NULL`, no CHECK constraint). Any string a Forge
> agent emits is persisted verbatim and rendered as-is by the UI. The list below
> enumerates **known producers**, not an enforced enum. Adding a new agent slug
> requires no migration — update this list when the slug ships.
```

Edge cases / failure modes:
- None — this is prose. Verify by reading the rendered markdown.

## 4. Verification

Rationale: The Linear issue's "Done when" defines acceptance. Each clause maps to a concrete check the executor must run.

Contract:
- **Doc check:** `current/db/entities.md` (post-regen) contains all 6 v1 + 11 openspec-* slugs and the free-text note.
- **Persist smoke:** invoke a `--persist` run that writes a finding with `agent = 'openspec-<one of the new slugs>'`; assert row lands in `forge_findings` without DB error. Smallest viable invocation: a unit test against the persistence helper, or a CLI dry-run pointed at a local Supabase. No CHECK constraint exists, so success is "INSERT returns no error".
- **Regen clean:** `pnpm openspec:regen` exits 0 with no diff after re-run (idempotent).
- **No frozen-archive edits:** `git diff` must not touch `openspec/archive/2026-06-02-add-openspec-audit-pass/**`.

Edge cases / failure modes:
- Local Supabase not available — skip the live INSERT and substitute a typed assertion that the persistence helper does not narrow `agent` to a union (i.e. `string`, not `'foo' | 'bar' | ...`).
- `openspec:regen` produces a diff — investigate whether the edit was made in a derived file rather than the spec source; relocate the edit upstream.
