mirror of
https://gh-proxy.org/https://github.com/klinsmaya/multica.git
synced 2026-11-09 01:46:46 +08:00
* feat(properties): add actor / multi_actor custom property types (MUL-6286) Custom issue properties gain their first reference type: `actor` (single) and `multi_actor` (multiple), holding workspace members and agents. Value shape is a prefixed string — "member:<user_id>" / "agent:<agent_id>", multi being an array of them. Keeping it a plain string rather than an object means the existing @> containment filter, the jsonb_path_ops GIN index and the client value schema all keep working unchanged; an object-shaped value would have been silently dropped by the client preprocess that guards against unknown value shapes. Scope decisions: - Squads are out. The assignee pair accepts member/agent/squad, but a squad is a routing target rather than a person. The stored form carries the kind, so widening later needs no migration and no new type. - Referencing an agent is NOT an assignment: nothing is enqueued, routed or notified. The picker therefore does not gate agents on runtime binding or invoke permission the way the assignee picker does — it gates on visibility, matching the server. - Agent identity still needs protecting, so writes and facet reads both run through accessibleAgentIDs: a private agent never becomes referenceable or discoverable by id. - multi_actor dedupes but preserves insertion order instead of canonicalizing like multi_select. There is no config order to sort against, and sorting by id would reshuffle the avatar row on every edit. @> containment is order-insensitive, so filtering is unaffected. - Actor properties are filterable (including "= me", with the signed-in member sorted first) but not sortable or groupable — the same position multi_select already holds. Both types ship together because a property's type is immutable: shipping single-only would have forced anyone wanting multi to recreate the property and re-enter its values. Co-authored-by: multica-agent <[email protected]> * refactor(properties): narrow actor properties to members only (MUL-6286) Scope change after review: `actor` / `multi_actor` hold workspace members only. Agents are out — a passive reference had to answer agent-visibility questions (private / non-allow-listed agents must not become discoverable by id) and carry a "referencing is not assigning" caveat everywhere, all for a use case nobody has asked for. The original request was for members. The envelope is unchanged on purpose, so this stays a one-line widening later rather than a migration: the types are still named `actor` / `multi_actor`, the stored value is still the kind-prefixed "member:<user_id>", and the migration still allows both type names. Adding "agent" back means appending to `actorPropertyKinds` — existing definitions would gain the kind in place, with no new property type and no value rewrite. What this removes: - The agent branch of `resolveActorRefs`, including the accessibleAgentIDs visibility gate and the archived-agent check. - `filterAccessibleActorFacetValues` entirely. Facet keys are now all `member:<uuid>`, and workspace membership is already visible to every member, so there is nothing left to gate. - The agent section of the actor picker, and agents from the filter dropdown's candidate list. - The "reference, not an assignment" framing from the skill and product docs — that distinction only existed because agents were allowed, and keeping it would now confuse rather than clarify. `actorPropertyKinds` carries the note that any future kind which is not universally visible to every member must restore the visibility gate on both the write path and the facet read path. Tests updated to match: agent refs are now rejected at the kind check, and the private-agent visibility test is replaced by TestIssueActorPropertyFacets, which covers the facet path that backs the "= me" filter. Co-authored-by: multica-agent <[email protected]> * fix(properties): address actor-property review findings (MUL-6286) Four defects from review, plus one pre-existing bug found next to them. 1. Editing a multi_actor value silently deleted kinds the client did not recognise. The picker rebuilt the array from `actorRefsFromValue`, which filters unknown kinds — so once the backend widens actorPropertyKinds, an installed desktop build would drop every agent reference the moment the user toggled a member. The edit path now round-trips the RAW string list via the new `actorRefValuesFromValue`, and the toggle is extracted to `toggleActorRefValue` so the guarantee is directly testable. 2. Actor ids were stored exactly as received. `uuid.Parse` also accepts uppercase, braces and the urn: form, and every consumer (member directory lookup, "= me" filter, @> containment) compares reference strings exactly — so `member:<UPPERCASE-UUID>` passed validation and then rendered as Unknown and matched no filter. `parseActorRef` now stores the canonical form. 3. The CLI, docs and skill all promised member email as a way to address a value, but `resolveAssignee` only matched id and name. Email is now an exact-match alias ranked with id matches (it is as unambiguous as an id), so the documented behaviour is real. This also makes `--assignee` accept an email, which is a strict improvement. 4. An active actor-property filter rendered as a bare count. The chips bar loads each directory lazily and gated the member directory on assignee/creator filters only, then looked names up in `config.options`, which actor properties do not have. It now detects actor-typed filters, loads the directory, and renders names plus an avatar stack. Found while fixing 4: the chips bar keyed its actor-name map by the membership row id (`m.id`) while every actor filter value carries `user_id`, so member names never resolved in the assignee and creator chips either. One token, same expression, fixed here rather than left next to the new code. Also drops two comments still describing the member/agent scope. Co-authored-by: multica-agent <[email protected]> * fix(properties): stop a single actor value overwriting an unreadable ref (MUL-6286) Round-two review finding. The previous fix only protected `multi_actor`: its toggle round-trips raw strings, so a reference kind this build cannot parse survives an edit. Single `actor` had no such protection. Once the backend widens actorPropertyKinds, an older client reading `agent:<id>` in a single actor property would filter it out, render the field as empty, and then — when the user "filled in the empty field" — replace it outright. The user sees themselves setting a blank field; what actually happens is a value they were never shown gets deleted. The editor now degrades to read-only when a single actor value holds a reference it cannot parse, and the display says so instead of showing the empty-state label. Clear is still offered, so a genuinely stale value can be removed deliberately. `multi_actor` stays editable — its toggle is already non-destructive. The read-only decision moved into an exported `isCustomPropertyReadOnly`, so all three reasons it can fire (archived, unknown type, unreadable actor ref) are covered by tests rather than being inline in the component. Also closes the two non-blocking gaps from the same review: - The "email outranks a name substring match" CLI test asserted a ranking its fixture could not actually exercise — no candidate's name contained the email. Added an agent named "Mailer for [email protected]", so the test now fails if email stops being ranked with id matches. - Extracted `buildChipActorNames` and asserted a member resolves by `user_id` and NOT by the membership row id — the pre-existing bug fixed in the last commit now has a test that would catch its return. Co-authored-by: multica-agent <[email protected]> * chore(migrations): renumber actor-types migration to 341 (MUL-6286) 332 was taken by 332_issue_status on main while this PR was open; the migration lint test caught the collision in CI. Co-authored-by: multica-agent <[email protected]> --------- Co-authored-by: Bohan-J <[email protected]> Co-authored-by: multica-agent <[email protected]>