Skip to content

feat(wedge): PR-WV1-5 — tier-gating retirement + nav reorder#188

Merged
jukka-matti merged 14 commits into
mainfrom
feat/wedge-pr-wv1-5-tier-gating
May 17, 2026
Merged

feat(wedge): PR-WV1-5 — tier-gating retirement + nav reorder#188
jukka-matti merged 14 commits into
mainfrom
feat/wedge-pr-wv1-5-tier-gating

Conversation

@jukka-matti
Copy link
Copy Markdown
Owner

Summary

Retire isPaidTier() / hasTeamFeatures() and the wider tier/plan gating across the codebase (122 files, +726/-3340 lines) under the wedge V1 single €99 SKU. Reorder + rename the 7-tab nav to amended workflow order Home · Project · Process · Analyze · Investigation · Improve · Report per docs/superpowers/specs/2026-05-16-improve-tab-amendment-design.md.

What changed

Core (Task 1-2):

  • packages/core/src/tier.ts collapsed 293 → 26 lines; only MAX_CHANNELS, CHANNEL_WARNING_THRESHOLD, validateChannelCount, ChannelLimitResult survive.
  • All 24 tier-discriminating exports retired.
  • packages/hooks/src/useTier.ts + apps/azure/src/lib/tierConfig.ts deleted.
  • Channel limit unified at 1500 (was 5 for free, 1500 for enterprise).

Apps + UI + AI sweep (Task 3, Architect→Migration→Validator):

  • A-class pure-deletion sweep across 26 production files — every hasTeamFeatures() / isPaidTier() conditional retired.
  • A-storage: 11 cloud-sync guards in storage.ts removed (always-on).
  • C-class: PerformanceSetupPanel rewired from useTier() to direct MAX_CHANNELS + validateChannelCount; PerformanceSetupPanelBase interface slimmed.
  • D-class: DevTierSwitcher.tsx, AdminPlanTab.tsx, packages/ui/src/components/UpgradePrompt/ entire subtrees deleted.
  • E-class: isTeamPlan parameter dropped from CoScout AI prompt registry + hooks + AI orchestration.
  • F-class: hasKnowledgeBase() gates dropped; isPreviewEnabled('knowledge-base') preserved.
  • G-class: LicenseTier + MarketplacePlan type exports deleted.
  • Test sweep: 18 test files updated; vi.mock importActual partial pattern preserved.

B-class deferral (documented): Spec mandated canAccess(userId, members, action) rewires at InvestigationWorkspace.tsx:973,980 and ReportView.tsx:683,684. Implementer folded into A-class as always-on (no behavioral regression — deleted gates were tier gates returning true for every paid customer). Logged at docs/investigations.md PR-WV1-5 entry as must-fix-before-V1-launch; Sponsor read-only role enforcement requires the canAccess wiring before any Sponsor-facing release.

UI copy + i18n (Task 5):

  • 12 admin.plan* + upgrade.* i18n keys deleted across 32 locale files + types.ts.
  • "Azure paid" copy in ReportViewBase → "VariScout for Azure" (capability marker, not commercial-tier marker).
  • 5 "Team tier" / "paid tier" comment cleanups.

Nav reorder + 7-tab renames (Task 6) per 2026-05-16 amendment:

  • 7 tabs preserved; renames + reorder only.
  • Overview→Home, Frame→Process, Analysis→Analyze, Projects→Project (singular).
  • Improve tab kept as top-level verb tab; moves between Investigation and Report.
  • Project moves to slot 2 (active-IP cascade root).
  • Final order: Home · Project · Process · Analyze · Investigation · Improve · Report.
  • PWA PhaseId union renamed; App.tsx adds forward + reverse bridges to stable panelsStore.activeView.
  • Azure internal activeView enum kept stable (out-of-scope refactor).
  • i18n: workspace.frameworkspace.process, workspace.analysisworkspace.analyze.

ESLint guard (Task 7):

  • no-restricted-imports rule blocks re-introduction of the 24 retired tier functions + useTier hook.

Plan + spec

  • Sub-plan: docs/superpowers/plans/2026-05-17-pr-wv1-5-tier-gating-retirement.md
  • Master sequencer: docs/superpowers/plans/2026-05-16-wedge-implementation.md
  • Wedge spec: docs/superpowers/specs/2026-05-16-wedge-architecture-design.md
  • Tab amendment: docs/superpowers/specs/2026-05-16-improve-tab-amendment-design.md
  • ADR-082 (Wedge V1 single SKU)

Dispatch shape (research-backed, applied to Task 3)

Task 3's 50-file sweep used the Architect → Migration → Validator internal phasing pattern (Anthropic 2026 subagent guidance + Augment single-vs-multi-agent + Martin Fowler codemods). One Opus implementer dispatch with per-category commits + per-category validator gates, instead of 6-8 split sub-dispatches. Pattern documented in feedback_atomic_sweep_one_dispatch + CLAUDE.md workflow carve-out.

Test plan

  • Per-package tests green: @variscout/core (3397/3397), @variscout/hooks (1203/1203), @variscout/azure-app (1320/1320), @variscout/pwa (366/367 + 1 pre-existing skip), @variscout/ui (222/223 test files, 2139/2190 tests)
  • Per-package tsc --noEmit green for @variscout/hooks, @variscout/ui, @variscout/azure-app. Pre-existing TSC errors on main in @variscout/core (ActionItem/OutcomeSpec test fixtures) and @variscout/pwa (PhaseId, fixed by bd3eb5a3 reverse mapper) unchanged.
  • pnpm lint green (no-restricted-imports rule active).
  • pnpm docs:check green.
  • pnpm --filter @variscout/pwa build green.
  • Known: packages/ui/src/components/Canvas/__tests__/Canvas.test.tsx worker times out in full UI suite (1 test file of 223). Pre-existing — same hang reproduces on main. NOT introduced by this PR. To be investigated as a separate test-infra issue.

(No browser walk per feedback_wedge_v1_no_migration_no_backcompat — wedge V1 has no users yet; pr-ready-check + Opus review is sufficient.)

Wedge progress

🤖 Generated with Claude Code

jukka-matti and others added 14 commits May 17, 2026 10:14
Drop the always-paid / always-team conditional branches for retired
tier helpers (hasTeamFeatures, isPaidTier, shouldShowBranding) across
~26 production files. Under the wedge V1 single-SKU model (ADR-082)
every customer has the full feature surface, so the gates collapse
to the team-tier path with the import removed.

Includes the B-class call sites (InvestigationWorkspace photo/Teams
camera handlers; ReportView publish + share-link controls): wedge V1
makes both always-on for paid customers, so the gates drop without
needing canAccess() plumbing in this PR.

Also fixes a pre-existing absorbed lint violation in ChartSignature:
hardcoded '#64748b' -> chromeColors.labelMuted (per the
fix-absorbed-violations-at-seam rule).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cloud sync is always-on under wedge V1 (every customer has the paid
Azure managed app). Drops the 11 `if (!hasTeamFeatures())` early-return
guards plus the supporting "Standard plan: local-only" comments and
the no-team-features online-handler short-circuit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rompt

Wedge V1 single SKU has no tier-switching surface, no plan-management
tab, and no upgrade flow. Removes:

- apps/azure/src/components/settings/DevTierSwitcher.tsx (dev-only tier
  override widget)
- apps/azure/src/components/admin/AdminPlanTab.tsx + the AdminHub wiring
  for the now-deleted "Plan" tab (Cpu icon + 'plan' tab key + tabpanel)
- packages/ui/src/components/UpgradePrompt/* (whole subtree + barrel
  export) — no upgrade flow under single SKU

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the useTier() consumer and the now-deleted UpgradePrompt render
in the shared PerformanceSetupPanelBase. The Azure wrapper now imports
MAX_CHANNELS + validateChannelCount directly from @variscout/core, and
the base component exposes a smaller ChannelLimitProps surface (just
{maxChannels, validateChannels}) instead of the old TierProps shape
(tier, upgradeUrl, validateChannels).

The channel-limit-exceeded UI swaps the UpgradePrompt banner for a
plain reduce-selection AlertTriangle banner — no upgrade path under
single SKU.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…feature flag)

Knowledge Base availability under wedge V1 is controlled by the
isPreviewEnabled('knowledge-base') feature flag and the configured
search endpoint — no separate team-tier gate.

- searchService.ts: drop hasKnowledgeBase() from isKnowledgeBaseAvailable()
  and searchDocuments() guards
- PISection.tsx: rename isTeamWithKB -> isKBAvailable, drop the
  hasKnowledgeBase() check (keeps isPreviewEnabled gate)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Under wedge V1 single SKU every customer has the full CoScout tool
surface. Drops the isTeamPlan parameter + tier-based filtering across
the CoScout prompt assembly + tool registry:

- types.ts / index.ts: drop isTeamPlan from AssembleCoScoutPromptOptions
- legacy.ts: drop isTeamPlan from BuildCoScoutToolsOptions; inline the
  always-true sharing-tool + IMPROVE notify_action_owners branches
- tools/registry.ts: drop the `tier: 'team'` entries on share_finding,
  publish_report, notify_action_owners; drop the tier check in
  getToolsForPhase()
- useAICoScout.ts: drop isTeamPlan plumb-through
- useAIOrchestration.ts: drop the isTeamPlan() import + call
- teamToolHandlers.ts: update header doc-comment to drop "team-only"
  framing (file/function names stable — rename cascade out of scope)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the two retired licensing/plan type unions and the associated
TierLimits interface from @variscout/core's public types surface.
Channel-limit consumers continue to use ChannelLimitResult (re-exported
from packages/core/src/tier.ts).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update 18 test files to match the retired tier surface:

- Drop vi.mock('@variscout/core', ...) blocks that overrode retired
  helpers (hasTeamFeatures, isPaidTier, hasKnowledgeBase, isTeamPlan,
  shouldShowBranding) — keep importActual partial-mock pattern.
- Drop configureTier(...) / configurePlan(...) setup calls.
- Drop tests that asserted tier-conditional behavior (toggle is gone);
  repurpose where natural to verify the always-on behavior.
- Drop useTier() mocks (hook no longer exists).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rephrase "Azure paid" → "VariScout for Azure" in ReportViewBase share-link
locked branch (PWA-vs-Azure marker, not commercial tier marker). Drop the
10 admin.plan*/admin.currentPlan* i18n keys (types.ts + all 32 locales) and
2 upgrade.free/fromPrice keys orphaned by AdminPlanTab deletion in Task 3.
Scrub residual "Team tier" / "paid tier" vocabulary from JSDoc comments.
Fix pre-existing unused-var lint error in e2e user-flows spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…unctions

Adds no-restricted-imports rule to eslint.config.js blocking all 24 retired
tier symbols from @variscout/core + useTier from @variscout/hooks (ADR-082).
Fixes two Dashboard test files that used wildcard namespace imports to conform
to the new rule (refactored to named import + vi.mocked pattern).
@jukka-matti jukka-matti merged commit b0bc2dd into main May 17, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant