feat: profiles — the who-is-working dimension - #457
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Too many files changed for review (3000 files, 100 file limit). |
|
Important Review skippedToo many files! This PR contains 2269 files, which is 1969 over the limit of 300. To get a review, reduce the PR to 300 files or fewer by splitting it into smaller PRs or changing its base branch. Usage-priced reviews support at most 300 files. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (731)
📒 Files selected for processing (2269)
You can disable this status message by setting the |
|
React Doctor found 2 issues in 2 files · 1 error & 1 warning · score 67 / 100 (Needs work) · vs Errors
1 warning
|
| const anchor = selectedIndex === -1 ? 0 : selectedIndex; | ||
| const active = Math.min(Math.max(cursor ?? anchor, 0), Math.max(cells.length - 1, 0)); | ||
|
|
||
| const gridId = id ?? React.useId(); |
There was a problem hiding this comment.
React Doctor · react-doctor/rules-of-hooks (error)
useId changes Hook order between renders when called conditionally, so React can attach state to the wrong Hook.
Fix → Call hooks at the top level of a React function component or custom Hook so React sees the same hook order on every render.
…op legibility) Pull from origin/main bringing 54 commits including: - feat: profiles — the who-is-working dimension (compozy#457) - build: prepare release v0.3.0 (compozy#450) - feat: complete production demo seed (compozy#453) - fix: recover ACP sessions after provider disconnects (compozy#454) - feat: make loop runs legible and task lists calm (compozy#452) - and many more Resolved Makefile .PHONY conflict by keeping both cross-build-windows and build-windows targets alongside the new test-e2e-desktop target.
Warning
This PR is being merged as an explicit checkpoint to unblock dependent work. It does not complete Task 13, does not claim that the full QA program passed, and does not have a fresh final
make gate-fullrecord. This section supersedes the historical Verification, QA status, blockers, and risks sections preserved below.Latest checkpoint
Commit
be0b2db6fixes the QA failures that were investigated before the checkpoint:COMPOZY_HOME, operatorHOME, and the registered project directory in browser E2E;all_profiles=true;defaultwhile preserving their durable fallback provenance;Fresh focused evidence after the last mutation:
go test -race ./internal/profile ./internal/api/core -count=1— 1,855 passed.TEARDOWN_CLEAN=trueforprofiles-consumer-saas-growth-20260824-051710-813419.Required post-merge work
main; inspect conflicting PRs/specs before resolving business logic.make test-e2e-runtimeandmake test-e2e-weblanes. The last complete Web run, before the focused fixes above, was 74 passed / 171 failed / 3 skipped and therefore is not completion evidence.make gate-fullonce after the final post-merge mutation. The historical gate fingerprint below is stale afterbe0b2db6.docs/qa/reports/2026-08-24-profiles.md, update scenario verdicts, mark Task 13/QA execution complete only when evidence supports it, and publish the final PR screenshots.Current repository truth remains:
task_13.status: in_progress,qa.report_done: true, andqa.execution_done: false.Original implementation description and historical evidence
Profiles gives CompozyOS a who-is-working dimension. One daemon, one database, one fixed set of workspaces — and every piece of work carries the profile that owns it. Switching profile re-scopes what you read without moving a file, restarting anything, or forking state. Profiles are a separation of work, not a security boundary, and the UI says so in those words.
Five layers carry the model end to end: identity and lifecycle (
internal/profile), read scope (task 06's enforcement sweep), resources and credentials (task 08), extensions and presets (task 09), and per-profile client state (task 10). An aggregate lens —All profiles— reads across every profile and labels each row with its owner, and it composes with the existing global/workspace lens rather than replacing it.50 commits · 3,235 files · +118,968 / −28,477 against merge base
7d659eaa.Changes by surface
Runtime and storage
internal/profile/— 21 new files, +5,250 lines:manager,catalog,create/rename/archive/delete,resolve,selection,availability,lifecycle_finalize,lifecycle_journal,mcp_auth_lifecycle,persistence,plans,removal_inventory,validation,events.internal/store(+13,138),internal/api(+12,094),internal/daemon(+9,055). New schema definitions05_profiles.sql,98_profile_integrity.sql,99_workspace_scope_integrity.sql, and theprofile_attention.sqlquery set.Migrations — globaldb
00081–00085; memory00002and00003_profile_decision_identity; bothatlas.sumfiles refreshed. Append-only: no existing migration bytes, versions or ordering were touched.CLI / HTTP / UDS — 15 new files under
internal/cli(profile_commands,profile_lifecycle_commands,profile_client,profile_flag,profile_resolution,profile_read_scope,profile_output,profile_errors, plussecretandextension_enablement).openapi/compozy.jsonregenerated (+16,171 / −5,682 — the largest single file change), with ~24 regeneratedsdk/go/contracts/types_0NN_gen.go, a newsdk/go/extension_describe_profiles.go, andsdk/typescript/src/generated/contracts.ts.Config, credentials, resources —
internal/config/profile_overlay.go,profile_layer_diagnostics.go,hook_overlay_read.go,write_override.go. Profile-scoped config writes, layered credential resolution, and per-profile resource shadowing.Web —
web/src/systems/profiles/is 69 new files, +6,507 lines:ProfileSwitcher+ menu + slot,ProfileGlyph, the five lifecycle dialogs,ProfilesSettingsPage,ProfilePaletteRow+ palette view,ProfileOwnerTag,ProfileDestinationChip,ProfileOwnerBanner,WorkspaceProfilesHint. Owner tags were wired into sessions, tasks, automation, bridges, loops, worktrees and the dashboard.packages/uigains one new primitive,SymbolPicker(with story and tests).Docs and skill — new
packages/site/content/docs/profiles/section pluscli/profile/,cli/secret/,cli/notification-preset/andcli/provider/inspect.mdx.skills/compozy/gainsreferences/profiles.mdand updates 9 existing files.Compozy Impact Audit
compozy__profile_listandcompozy__profile_current(internal/tools/builtin_ids.go:122), bothRiskRead, registered ininternal/toolmeta/native_entries.go:178-179, implemented ininternal/tools/builtin/profiles.goandinternal/daemon/native_profile_catalog_tools.go, present intestdata/native-tool-catalog.json. Every othercompozy__*ID touched by the diff already existed onmainand was modified only for profile scoping.98_profile_integrity.sqland99_workspace_scope_integrity.sql.Verification
make gateclassified the diff and auto-escalated to the fullmake verify. The record is CURRENT at fingerprintb8da482ad2c5226729051090f00f5950cdbdcbb9(full pass, finished 2026-08-24T00:28:17Z). The gate was deliberately not re-run for this evidence pass, because nothing tracked changed —git statusis clean atb7f65fe5andmake gate-statusstill reports the same fingerprint.Deep review
911 canonical findings (6 critical / 182 major / 62 minor): 887 resolved, 23 suppressed or dismissed, across 19 remediation batches.
RD0258 remains open. It reported that the Visual Contract evidence bundles required by tasks 05/07/09 did not exist. This PR produces that evidence tree for controller verification — it does not self-certify the finding as discharged, and no deep-review status was mutated. The verdicts below are the honest result, not a clearance.
RD0259 named two stale generated-CLI doc gaps; both now exist on this branch (
packages/site/content/docs/cli/secret/{index,set,rm}.mdxandcli/provider/inspect.mdx). Its status is likewise left for controller verification.Visual Contract evidence
All 33 declared rows have a materialised bundle directory under
.compozy/tasks/profiles/evidence/visual/task_{05,07,09}/<VC-ID>/. Materialised ≠ passing:validate-visual-contract.mjsexits 0reference.pngonly — the cited implementation state could not be rendered truthfully, so no implementation/diff/comparison was fabricated. The six-file shape is deliberately not met and the validator fails these by designMethod: every
reference.pngis a real 1440×900 capture of the cited OpenDesign board section, scrolled to itsdata-od-idthrough a throwaway clone-and-patch wrapper (the canonical boards were never modified, and the wrappers were deleted). Implementations came from the shipped Storybook stories and from the real UI driven against an isolated daemon lab. Every captured pair was reviewed personally — no subagent issued any verdict. The 15 comparison reviews were written individually; the 18 BLOCKED records were generated from explicit per-row reasons and then checked by the controller. The validator schema only treatsverdict: PASSas passing, so BLOCKED review frontmatter is intentionallyverdict: FAIL; the table separates capture blockers from rendered comparisons with visual divergences.task_05/VC-01sw-quiettask_05/VC-02sw-finaltask_05/VC-03sw-alltask_05/VC-04st-finaltask_05/VC-05st-create+st-validationtask_05/VC-06pk-finaltask_05/VC-07pk-emoji+ §03pk-emptytask_05/VC-08pk-hextask_05/VC-09lc-renametask_05/VC-10defaultpermanencelc-rename-edgestask_05/VC-11lc-archivetask_05/VC-12lc-deletetask_05/VC-13lc-unarchivetask_05/VC-14cp-finaltask_05/VC-15profile.*actionscp-roottask_05/VC-16cp-handofftask_07/VC-01ag-finaltask_07/VC-02ag-createtask_07/VC-03ag-create-toasttask_07/VC-04ag-bannertask_07/VC-05ag-emptytask_07/VC-06ag-usagetask_07/VC-07sw-globe(scoped)task_07/VC-08sw-globe(All)task_07/VC-09cp-aggregatetask_09/VC-01ex-installtask_09/VC-02ex-placementstask_09/VC-03ex-needstask_09/VC-04ex-dormanttask_09/VC-05hi-finaltask_09/VC-06hi-partialtask_09/VC-07st-presetstask_09/VC-08cp-extensionPublic object prefix:
https://pub-6cb601c36b3b4de9bc57fae6b15686d0.r2.dev/profiles/b7f65fe5/— the prefix itself is not a browsable index; use the object links above. All 48 linked objects were verified200+content-type: image/png. Local manifest:.compozy/tasks/profiles/evidence/visual/upload-manifest.json.What the seven FAIL rows found
Two of them are genuine product findings, not capture problems:
task_05/VC-01— with onlydefaultpresent, the shipped switcher menu renders anAll profilesrow that the reference's quiet state deliberately excludes ("Nothing else in the product mentions profiles"). An aggregate lens over a single profile reads identically to the scoped view. No canonical owner authorises the extra row, so it is reported rather than waved through.task_05/VC-13— the unarchive bundle captures the post-commit report ("old-agency is back", singleDone) rather than the cited pre-commit confirm (Cancel+Unarchive), and the per-item reactivation toggles the reference shows are absent.Three are contract-shape problems — the row cites two mutually exclusive product states that cannot share one 1440×900 frame:
task_05/VC-05(create dialog + validation), which additionally cannot fit both cited board stages: measured 873px required inside an 856px scroller. It also shows the shipped create dialog embedding the wholeSymbolPicker, where the prototype defers identity to a separate board.task_05/VC-11(archive confirm + blocked-by-running) andtask_05/VC-12(delete enumeration + owns-work routing). Each needs splitting into two rows, or re-scoping.One is a capture-scoping gap:
task_07/VC-06— the per-profile usage breakdown (home-profile-share) sits below the 900px fold of the dashboard story, so the cited region was never in frame. The fixtures do contain the data; the story simply needs scrolling to that section first.One is a surface-substitution failure:
task_07/VC-02requires the new-session surface withAll profilesactive, but the captured implementation is the worktree creation dialog with amarketingdestination and no visible aggregate lens. The shared chip looks correct, but this frame does not prove the required session flow.Why 18 rows are BLOCKED
task_05/VC-14,VC-15,VC-16,task_07/VC-09) — the palette overlay never rendered in the headless harness. Both theControlOrMeta+Kpath used by the shippedopenCommandPalettehelper and a direct click on the shipped[data-slot="os-menubar-command"]trigger leftos-command-paletteinvisible for the full 20s window.task_09/VC-01–VC-04,VC-08) — need an installed extension that declares profiles.web/src/systems/extensions/mocks/fixtures.tscarries nodeclared_profiles/placements, soExtensionDeclaredProfilesearly-returnsnull; the daemon lane needsextension-registry-server.ts+bundled-extension-seeder/wired into a capture run.review.mdnames the exact selector and precondition.Blockers found in the shipped E2E suite
Diagnosing the capture harness surfaced two real defects in the committed profiles E2E suite. Both are reported, not fixed — they touch tracked files outside this pass's scope:
web/e2e/fixtures/workspace.ts::ensureGlobalWorkspaceregisters the daemon HOME directory, which this branch's own phase-0 change now rejects:400 workspace_home_forbidden— "the home folder cannot be registered as a workspace; choose a project folder instead". 14 of the 15 journeys inweb/e2e/__tests__/profiles.spec.tscall it; E2E-022 already creates a temporary project workspace. Verified directly by running the shipped-g "E2E-019", which fails with that exact error. The current pattern is a temp project folder (web/e2e/__tests__/jobs-hardening.spec.ts:468).web/e2e/__tests__/profiles.spec.ts:410(E2E-015) archives with an empty body, but the endpoint requires a plan revision:400 profile_input_invalid … 'PlanRevision' failed on the 'required' tag.These defects break the committed profiles E2E lane as written and should be repaired before the post-merge task 13 work reuses it. They do not establish that the broader real-user QA plan is blocked.
QA status
Task 12 shipped the plan: 7 journeys · 8 new scenarios · 39 scenarios reconciled · 11 charters settling 49 unique scenario rows, each row settled by exactly one charter. Re-derived from
docs/qa/immediately before writing this: parsing thescenarios:lists of the 11 profiles charters yields exactly 49 unique ids, and all 49 are currentlyqa_status: untested.Task 13 (Real-User QA Execution) is intentionally deferred to a separate post-merge branch. It was not executed here, no scenario verdict was changed, and no claim is made that real-user QA passed.
state.yamlstill readsqa.execution_done: falsewithtask_13pending.Risks and follow-ups
untested.All profilesrow in the single-profile switcher (VC-01), and the unarchive confirm's missing per-item reactivation controls (VC-13).VC-05,VC-11,VC-12): each cites two mutually exclusive states in one bundle, which no single truthful frame can satisfy.task_07/VC-02needs a new-session capture withAll profilesactive; the current worktree frame is a surface substitution.Evidence tree and manifest live under
.compozy/tasks/profiles/evidence/visual/(gitignored, not committed). No production code, test, schema, config or QA verdict was changed by this pass;make gate-statusstill reports the pre-existing fingerprint.🤖 Generated with Claude Code