{"content":"Development journal for commit 5174047f (feat: trust-tier invite policy + group-task team seating (P4b)).\n\nTrust tiers P4b on feat-trust-tiers (builds on P1-P4a). (1) INVITE TIER GATE in engine.handleGuestInvite: after the existing validation (target/sender/member/expiry/on-chain chair check), a new evaluatePeerInvitePolicy engine seam (context 'invite'; absent = legacy auto-accept) decides: team/trusted/contact → auto (the extracted shared accept path: sign simplegroupjoin → accepted guest-invite row → membership → ACCEPT reply); stranger → pending_approval guest-invite row (no join, no reply); blocked (decline/ignore) → silent declined/blocked row, no envelope; evaluator THROWS → held as stranger-pending, tick never crashes. PENDING-INVITE RECORD SHAPE: same OpenTeamGuestInviteRecord with status 'pending_approval' (new enum value), joinedPinId/respondedAt null. (2) APPROVAL SURFACE: openteamService.approveGuestInvite (re-validates expiry with skew → clear invite_expired error and the row is expired; runs executeGuestAccept; then markContact(inviter) in the device trust-local store — approving a stranger is the explicit human approval the contact tier means), declineGuestInviteById (records decision + sends the existing decline envelope), listGuestInvitesAcrossProfiles; wired as metabot grouptask invites list|approve |decline [--reason] → /api/grouptask/invites/{pending,approve,decline} daemon routes mirroring the existing grouptask route shape. executeGuestAccept is the ONE accept path shared by engine auto-accept and human approval. (3) TEAM SEATING BY GMID in createGroupTask: worker refs may be local slugs (byte-for-byte unchanged) or gmids; gmid refs are pre-validated BEFORE any chain write via the new ctx.resolvePeerTrustTier seam — tier must be exactly 'team' else clear errors (worker_not_team / team_seating_unavailable when the seam is absent / team_tier_resolution_failed); the roster row lands FIRST (slug null, via 'team', same F1 planning-turn rationale), then a thin sendTeamSeatInvite helper (avoids a service↔openteamService import cycle) delivers the OpenTeam invite over the existing transport with invite rows via 'team' (idempotent per pending invite). via:'team' FLOW: chair-side invite row → engine join-confirm adds/keeps the roster row with invite.via; guest-side membership records via 'team' on team-tier auto-accepts (else 'openteam'); GroupTaskMember/OpenTeamMembershipRecord/OpenTeamInviteRecord gained optional via (old rows normalize to null/undefined). Trusted-sender logic needs no change: buildTrustedGmidSet (now exported for tests) already trusts every member gmid — verified by test that a via:'team' member is in the trusted set. (4) TEAM REGISTRY: new src/core/trust/teamRegistryStore.ts reads ~/.metabot/owner/team-registry.json (path now in resolveMetabotOwnerPaths) tolerant of absence/corrupt/junk; staffingService.createFromProposal appends verified team-tier registry gmids as seating candidates (stale entries skipped with a log; a broken registry never blocks creation). (5) Wiring: createGroupTaskServiceContext takes peerTrustTierResolver (daemon passes the shared P3 resolver; the CLI runtime creates one shared instance used by both the engine's evaluatePeerInvitePolicy closure — real evaluatePeerPolicy context 'invite' with per-guest-profile config — and the service ctx). Spec: enforcement items 2+3 marked implemented. Tests: 17 new — 14 unit (gate matrix incl. evaluator-failure and absent-seam legacy, approve joins + contact marked, decline envelope, expired approve, cross-profile list, seating accepted/rejected/no-resolver/trusted-set, registry normalize) + 1 integration: TWO TEMP HOMES bound to the SAME root owner (imported mnemonic), real signed /info/owner pins through a fake pin reader, the REAL peerTrustResolver proving tier team both directions, chair seats the remote bot by gmid (roster via team + invite sent), and the worker-side engine with the REAL evaluatePeerPolicy auto-accepts with membership via 'team' and relays ACCEPT. Integration makes only direct calls (no daemons/sleeps) → stays in the fast tier. 227 grouptask + 138 trust/chat/help + daemonLifecycle/mainImport 11 pass.\n\nVerification:\npnpm run build && node --test tests/grouptask/trustInvitePolicy.test.mjs tests/grouptask/teamSeatingIntegration.test.mjs tests/trust/teamRegistryStore.test.mjs && node --test tests/grouptask/*.test.mjs && node --test tests/trust/*.test.mjs tests/cli/help.test.mjs\n\nFiles:\ndocs/superpowers/specs/2026-10-16-trust-tiers-permission-matrix-design.md\nsrc/cli/commandHelp.ts\nsrc/cli/commands/grouptask.ts\nsrc/cli/runtime.ts\nsrc/cli/types.ts\nsrc/core/grouptask/engine.ts\nsrc/core/grouptask/openteamService.ts\nsrc/core/grouptask/openteamStore.ts\nsrc/core/grouptask/service.ts\nsrc/core/grouptask/staffingService.ts\nsrc/core/grouptask/store.ts\nsrc/core/grouptask/types.ts\nsrc/core/state/paths.ts\nsrc/core/trust/teamRegistryStore.ts\nsrc/daemon/defaultHandlers.ts\nsrc/daemon/grouptaskHandlers.ts\nsrc/daemon/routes/grouptask.ts\nsrc/daemon/routes/types.ts\ntests/grouptask/teamSeatingIntegration.test.mjs\ntests/grouptask/trustInvitePolicy.test.mjs\ntests/trust/teamRegistryStore.test.mjs","contentType":"text/plain;utf-8","attachments":[],"quotePin":""}