Active request: October 22, 2026. Read the existing specification, milestones, technical design, acceptance tests and build status. COLLECTOR_EXPECTED_BEHAVIOR.md and supplied mockup images are absent. This implementation follows the written layout. The new request explicitly restores Unreviewed summary; other plain-English labels remain.
The application uses one owned contacts record with separate related rows, a right-hand Contacts editor, an expanded version of that editor, and a compact recognition card. Reads use contactSelect → mergedLibrary → authenticated /api/library or /api/contacts. Saves use a revision-checked transaction, original-note revision actions, private photo uploads, explicit review actions and reversible linked-record combines. This remains the architecture.
| Existing fields / records / actions | Redesigned destination | Persistent read/write path |
|---|---|---|
| ID, owner, revision, creation time, combined-original mapping | Internal ownership/concurrency; saved date in Additional details; combined originals visible | Existing contacts/RLS, guarded mutations and combine/undo |
| Display name, aliases/nicknames | Header; Edit name and location | contacts; section update only these fields |
Email/phone/profile links (methods) |
Contact information; repeatable rows | Existing contacts.methods, section update |
| Private photos, source IDs, paths, creation time | Header + all saved photos in Additional details; Add a photo | Existing private /api/photos, original photo/source rows retained |
| Affiliation organization, role, kind, dates, current/former/unknown, primary display, IDs and provenance | Experience, Education (school kind), organization entries; entry editors; primary header label | Existing affiliations extended in place; section add/update/archive; history retained |
Affiliation history (previous, changed_at) |
Additional details → past workplace/school details | Existing history trigger and reads; no row IDs changed |
First meeting (meeting_context) |
Header and Meetings & encounters, distinct from later meetings | Existing first context stays immutable once supplied; append corrections in notes |
| Subsequent encounters, dates, sources | Meetings & encounters; Add meeting | Existing encounters, appended source-linked row |
| Original notes, bodies, versions, sources, superseded versions | Original notes; Add, correct, delete with existing confirmation | Existing notes, revise_original_note, history/invalidation unchanged |
| Memory cues, manual/generated origin, review state, pins, edited flag, multi-note references | Things to remember directly below header; same records in panel and recognition card | Existing MemoryCues actions/source links; no approval gate added to display |
| Manual and AI observations, fields/values, sources, timestamps, confirmed/pending/rejected/superseded | Appearance & voice; Additional observations and history for legacy fields/values | Existing observations extended; manual edits append/supersede only selected fields; pending never promoted |
| Photo suggestions, original photo, certainty, job/review state/time | Additional observations history; working review controls in Review details | Existing review pipeline; photo analysis vocabulary remains bounded |
custom_traits and raw initial/imported text, filenames, source metadata |
Additional details; preserved original text, editable custom details | Existing contacts.custom_traits/sources; restricted/internal metadata not displayed |
| Relationships (saved target or external label, source) | Groups & relationships; entry add/edit/remove | Existing owned relationships; actual saved target name when available |
| Manual memberships, nested groups, rule-based groups, inherited combined memberships | Header chips; Groups & relationships | Existing inGroup evaluator; direct membership edits only, rules remain in Organize groups |
| Contact priority and manual/assisted mode | Additional details; contextual controls | Existing contacts flags; Settings remains account-wide control |
| Save/create/delete, photo upload, side-panel expansion/collapse, close/focus return | Existing panel and expanded profile quick actions | Existing auth, upload, deletion and refresh paths retained |
| Duplicate comparison/keep separate/review later/combine/undo | Existing Review details workflow; combined-original information in profile | Existing explicit approval transactions and fingerprint-based undo |
| Imports/mapping, group management, Settings controls | Existing screens remain | Existing APIs and preferences unchanged |
| Location, About, descriptions, employment type/workplace type, education degree/field/expected status | New explicit profile/affiliation fields (no source data moved into them) | Additive migration and validated section API |
| Exact height/units, race/ethnicity, clothing, skills, attachments, cover images, follow-ups | No dedicated existing implementation/data columns found. Custom/imported text remains accessible. New exact-height preservation fields and optional self-described identity are explicit additions. No attachment/notification/cover service added. | No legacy content coerced into a new field; identity fields stay profile-only |
Read-only local audit before changes: 16 contacts, 12 affiliations, 31 observations, 10 notes, 24 sources, 2 photos, 2 groups; 0 relationship/encounter/cue/photo-suggestion rows. Observations include superseded manual values and pending AI values, all in the four existing field families. Personal content was not printed. Source snapshot: /tmp/collector-before-profile.tar.gz (no environment secrets).
components/contact-profile.tsx and components/profile-section-editor.tsx: full profile and scoped editors; primitives.tsx stops nested Escape events from closing the parent; contact-editor.tsx and workspace.tsx preserve the side panel/recognition views and their search/session state. app/globals.css reuses the existing theme, compact spacing and responsive patterns.lib/domain/characteristics.ts, profile.ts, model.ts, identify-projection.ts, identify.ts, groups.ts, duplicates.ts: shared choices, validation, explicit matching projection, adaptive questions, archived-affiliation handling and combined-original access. No second contact store, provider, dependency or search service.app/api/contacts/route.ts: validated PATCH section saves with authentication, beta membership, same-origin checks, owner scope, transaction and revision checking. Existing POST/create, GET and DELETE remain.tests/profile.test.ts, profile.integration.test.ts, profile-migration.ts, browser/profile.spec.ts, plus existing recognition/enrichment tests cover the new behavior. npm run test:profile runs the new local backend suite.Before applying 013, tests/profile-migration.ts seed added an isolated synthetic rich contact to the old schema and saved hashes of original-column values across 13 tables. It included multiple current/former roles, original exact dates plus partial-date source text, relationships, groups, custom details, old observations, original notes, a multi-note unreviewed cue, private photo and pending suggestion. After npx supabase migration up --local, tests/profile-migration.ts verify compared every original row/column hash and count, including preexisting data, and passed. The fixture user and temporary snapshot were removed. No preexisting personal content was printed or used as a test fixture.
Backend tests verify section isolation, old-editor round trips, every allowed hair/voice choice, height preservation, partial-date validation, archival/restoration, pending/rejected review states, cue/source retention, direct-RPC ownership and revision checks, and combined originals/undo. Browser tests exercise actual API writes, recoverable network failure with retained draft, Cancel, source links, keyboard focus, reload, narrow layout and theme/compact preferences. See BUILD_STATUS for final command results.
Structured self-described identity, its source, legacy details, About, derived metadata and memory cues are absent from the allowed matching document. Questions use only explicitly approved fields with useful confirmed/manual recorded differences. Missing fields, pending/rejected facts, inapplicable values and merge conflicts do not become negative evidence. The old glasses/facial-hair facts remain editable and usable as explicit typed clues, but no longer drive the default appearance questions. Legacy Blond/Red aliases compare with Blonde/Ginger without rewriting stored values; ambiguous Bald / shaved remains distinct.
Matching documents are recomputed from current account-owned data; there is no persisted index to rebuild. Original notes and recognition cues use a conservative English sentence filter for explicit identity statements; original source content remains available unchanged. This is a bounded lexical safeguard, not a semantic classifier for arbitrary or multilingual prose. Saved person/organization fields are deliberately not globally stripped of identity-like words. Rule-based groups support affiliation predicates only; no identity predicate or inferred mapping was introduced.
Profile editing does not activate AI. Existing automatic note cues, master paid permission, server restrictions and budgets remain in force. AI tests use fake providers, which do not establish live-provider accuracy or billing behavior. Voice is manual only; height is selected or explicitly converted from a saved measurement. No microphone, audio recognition, race inference, portrait-height estimation, export service, cover-image service, skills/attachments infrastructure, notification delivery or synchronization was added.
Partial date text overlays existing exact date columns without falsifying them. Old original exact dates remain in history/additional details; an expanded-profile edit is required for partial periods. Archived affiliations can be restored. Original first-meeting context remains preserved under the existing rule; later encounters/corrections are separate.