Home / Ops / Housekeeping and Process
Updated Jun 26, 2026 · BUILD-PROGRESS.md
Living log for the phased native build kicked off 2026-06-26. Newest first. Guardrails held: locked demo untouched, no em dashes, every audio chart-driven, verify before claiming done.
Backend (affirmology-studio, commits in e8b26a9/42b4029 swept the seed in with the
concurrent natal_sacred rework, + 007fa2d for the API/tests)
- New AudioMetrics schema on the Structure model (format, identity, transformation, energy,
pacing, emotional_tone, tools, stage, time_of_day, theme, duration_min, voice, bed,
repetition_role, tier_visibility) + a priority flag. Additive, safe defaults, so existing
rows and the locked demo are unaffected.
- Seeded the 14 named starter-palette structures with their Jeff-approved directives + metric
values: origin_soul_song, the_mirror, before_bed (folded into Daily in place), morning_activation,
daytime_anchor, visioning_magnify, hd_reading, hd_embodiment, and the six gk_{activation,venus,
pearl}_{reading,embodiment}. gk_activation_* marked priority. Voices/beds are A/B-candidate
fields, not locked. Engine pace stays standard for the new rows (directive prose carries
cadence; the ElevenLabs speed knob is a later listen-check) except before_bed which keeps deep.
- Categories registry (foundational, daily, human-design, gene-keys) + structures_public /
categories_public helpers.
- APIs: new GET /api/structures (palette + categories with metrics); /api/categories and
/api/categories/{id} now return metrics + category_id + priority; _public_job exposes the
structure's metric profile so Atlas can show/tune per-audio metrics.
- Verified: GET /api/categories + GET /api/structures return all 14; tests
tests/test_starter_palette.py (7); full suite 179 passed, 1 failed = the pre-existing
test_chart_cache nondeterminism.
Atlas (affirmology-atlas, commit 72ec17d): AudioMetrics/Structure/PaletteCategory types
+ studio.structures(); the Create controls panel shows the selected structure's metric chips.
Tuning by talking routes through Hermes. tsc clean.
RESOLVED 2026-06-26 (commit ec2be78) - natal_sacred KILLED, one canonical Origin Soul Song.
Jeff lifted the demo lock (CLAUDE.md) and called to kill natal_sacred. Removed the natal_sacred
structure entirely; origin_soul_song is now the single canonical foundational Origin Soul Song
(empty directive = the hardened engine formula, 4 min target, not A/B-ed on length). Repointed
every default (compose/draft/overview in main.py, the demo bridge DEMO_STRUCTURE_ID in
demo_render.py, Hermes _DEFAULT_STRUCTURE + tool text, overview.py spec key, web Studio default)
to origin_soul_song. affirmology-demo-site (the separate laptop demo) had ZERO natal_sacred
references. Verified: get_structure('natal_sacred') is None; /api/structures + /api/categories
show exactly ONE Origin Soul Song; suite 179 passed, 1 failed (pre-existing test_chart_cache).
Atlas app (new repo affirmology-atlas/, commits c2f1d5c + 621cf87)
- Expo SDK 56, bundle ai.affirmology.atlas, imports @affirmology/shared (git submodule at
./shared, same pattern as the consumer app).
- Screens: magic-link Login (shared flow); the Create centerpiece (chat-primary with a
reachable controls panel for person/structure/length/brief, the council "working" theater that
streams oracle steps while a script composes and an audio renders, co-creation quick-reply chips
from the Origin Soul Song synthesis); People (charts from /api/people, data-driven);
Listening Room (/api/library play + Love/Needs-work/Approve + push-to-person);
Compare (compare/[group], A/B comparative view).
- Wired to the real endpoints: /api/hermes (talk), /api/compose + /api/jobs (draft + poll),
/api/audio (render + poll), /api/library, /api/jobs/{id}/feedback|pick|variant,
/api/variants/{group}, /api/people, /api/categories, /api/roles. Studio bearer is the
synced magic-link session token (StudioTokenSync).
- Structures + people are FETCHED from the backend, never hardcoded, so the palette changes with
NO app release. (Seeding the named palette items, e.g. Origin Soul Song / The Mirror / Visioning,
is a backend/data step to do WITH Jeff, since it shapes script content.)
- Verified: tsc --noEmit clean, iOS bundle export succeeds, expo-doctor 21/21.
Backend additions (affirmology-studio, commit d08c75f, Studio-only, additive, demo untouched)
- Creator roles (api/roles.py): owner/creator/tester/viewer + can_create_for; GET /api/roles;
SOFT enforcement in /api/compose via optional as_person, gated by CREATOR_ROLES_ENFORCED
(off by default, so live behavior is unchanged). Built to elevate beta testers into creators.
- A/B variant groups (api/jobs.py): additive variant_group + variant_label columns,
set_variant/list_by_variant; POST /api/jobs/{id}/variant, GET /api/variants/{group};
variant fields in _public_job and /api/library.
- Tests: tests/test_roles.py + tests/test_variants.py (10). Full suite 172 passed, 1 failed
= the pre-existing test_chart_cache aspect-ordering nondeterminism, unrelated.
FOR JEFF (non-blocking)
1. The studio backend commit d08c75f is LOCAL only (not pushed), per the rule that you push prod
deliberately. Push when ready; it is additive and the demo is untouched.
2. Atlas needs npm install + git submodule update --init on a fresh checkout. Same EAS-submodule
note as Phase 1 applies (push affirmology-shared to GitHub and update the URL for cloud builds).
3. Creator-role enforcement stays OFF until you set CREATOR_ROLES_ENFORCED=1. The opt-in map in
api/roles.py currently lets the circle create for each other; edit it to elevate testers.
4. Apple/EAS: Atlas needs its own App Store Connect app record + signing for ai.affirmology.atlas
(mirrors the consumer app's morning steps). Cannot run the iOS Simulator here (Xcode license is
still unaccepted: run sudo xcodebuild -license accept).
What shipped
- New repo affirmology-shared/ (its own git repo, commit 81f0baa): the ONE source for
both apps. Holds the design system (theme), component kit (ui), API client (api),
magic-link auth context (auth), oracle face map + 17 busts (oracles + assets/oracles),
background/offline player (player), and the offline event queue (eventQueue). Source only,
no build step. Imported as @affirmology/shared (barrel) or @affirmology/shared/<module>.
- Consumer app affirmology-app/ refactored (commit a9c92e9): its old src/* and
assets/oracles/* are gone (583 lines removed); it now consumes the shared foundation as a
git submodule at affirmology-app/shared. Metro maps the alias to ./shared/src via a
resolveRequest hook; tsconfig mirrors the mapping.
Verified (not assumed)
- npx tsc --noEmit -> exit 0.
- npx expo export --platform ios -> succeeds, produces an identical Hermes bundle
(entry-4936fda9...hbc, ~3 MB). No behavior change to the July-priority consumer app.
Why a submodule under the app root, not a sibling package + Metro watchFolders
- Tested the clean sibling layout first. Metro's node crawler (this Mac has no watchman)
refuses to resolve ANY file outside the project root, even a direct relative import, regardless
of watchFolders. Proven by isolation test.
- A submodule puts the real shared files under each app's root, which is what both Metro's
crawler AND EAS (the build upload only contains the project tree) require. It keeps one source
and does NOT reinstall/hoist the consumer app's dependencies (the July regression risk).
FOR JEFF (small, non-blocking) - EAS cloud builds + submodule
1. The submodule URL is currently a LOCAL path (/Users/jeffreyparker/.../affirmology-shared),
which is fine for local dev and EAS local-upload builds. For EAS cloud builds triggered
from GitHub, push affirmology-shared to GitHub and update the URL in affirmology-app/.gitmodules
(and affirmology-atlas/.gitmodules) to that remote, then git submodule sync.
2. Editing shared code is a two-step commit: commit in affirmology-shared, then in each app
git -C shared pull and commit the new submodule pointer. (Documented in the shared README.)
affirmology-shared package.ai.affirmology.atlas) on the shared foundation.CREATOR_ROLES_ENFORCED once the opt-in map reflects who should create for whom.