Uh oh!
There was an error while loading. Please reload this page.
feat(cli): opportunities crowdfunding fields + WIP - #18
Conversation
Pairs with FREELABEL/fl-api#62 + FREELABEL/fl-elon-web-ui#68. After binaries are copied (and before the existing email/code TTY prompt), opens web.heyiris.io/pricing in the user's browser and polls fl-api for an SDK token. The Stripe webhook mints the token tied to the installer's UUID when checkout completes; this script polls until it appears, then writes ~/.iris/sdk/.env and auto-registers a Hive node. Behavior: - Skips on pre-seeded installs (--token flag) and re-installs (.env exists) - Falls through to the existing email/code prompt on timeout — that path remains the escape hatch for existing customers re-auth'ing on a new machine - Cross-platform browser open (open / xdg-open / start) - 3-tier UUID generation (uuidgen / /proc / python3 / /dev/urandom) - 10-minute poll window, Ctrl+C-interruptible Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#16) Inverts the order from #14. Was: Stripe paywall always opened on fresh install, with email/code as a 10-min-timeout fallback. New: email/code runs first (always), then GET /api/v1/cli/auth/me checks subscription state. Stripe checkout only opens if the user has no active subscription. Behavior matrix: Existing customer (paid sub, new machine): email/code → done in ~10s New user (no sub): email/code → Stripe → done Pre-seeded --token install: unchanged (skips both) Email/code skipped (empty email): no paywall (auth not done) cli/auth/me network error: no paywall (don't block on infra) Pairs with FREELABEL/fl-api PR adding cli/auth/me endpoint. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # install
- iris opportunities create/push: forward funding_goal_cents, equity_pool_bps, roles, pitch_sections - iris opportunities board list/add/remove - iris opportunities milestones list/add/remove - Includes related WIP from feature branch Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR mixes several WIP additions into the opencode/IRIS CLI and page content: new device- and system-scan-related CLI surfaces, installer subscription-gating changes, seeded page JSON content, and a set of product/spec docs. In the broader codebase, it extends the CLI surface area and adds more packaged page artifacts, but it also introduces unrelated work beyond the stated opportunities changes.
Changes:
- Adds new CLI/device tooling (
iris device,iris scan) plus a Python AFC bridge and installer subscription-gate updates. - Adds multiple landing/dashboard page JSON files and a how-to recipe.
- Adds internal spec/refactor markdown documents for future lead-linking, event production, and iMessage/contact work.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| scaffold/how-to/deals.md | New how-to guide for deals/payment-gate workflows. |
| pages/moody-beauty.json | New published landing page content for Moody Beauty. |
| pages/kevins-air-quality.json | New draft landing page content for Kevin's Air Quality. |
| pages/dent-society.json | New published landing page content for Dent Society. |
| packages/opencode/src/cli/scripts/device-afc.py | New Python bridge for iOS device/AFC queries and app actions. |
| packages/opencode/src/cli/lib/device.ts | New TypeScript device utility layer wrapping the Python bridge and Mac storage helpers. |
| packages/opencode/src/cli/cmd/platform-scan.ts | New CLI command to detect local productivity-stack signals and post a stack profile. |
| packages/opencode/src/cli/cmd/platform-device.ts | New CLI command group for device status, storage, iCloud, cleanup, and offload flows. |
| packages/opencode/pages/test-invalid.json | New invalid page fixture/component example. |
| packages/opencode/pages/pathways-dashboard.json | New packaged analytics dashboard page for Pathways. |
| packages/opencode/pages/kevins-air-quality.json | New packaged published page for Kevin's Air Quality. |
| packages/opencode/pages/dent-society-dashboard.json | New packaged analytics dashboard page for Dent Society. |
| packages/opencode/pages/catodrive-dashboard.json | New packaged operations dashboard page for CatoDrive. |
| packages/opencode/pages/catodrive-contact.json | New packaged contact/lead-capture page for CatoDrive. |
| install | Replaces trial flow with post-auth subscription gate logic in installer. |
| SPEC_LEAD_LINKING.md | Product spec for future lead-to-lead linking CLI/API work. |
| SPEC_EVENT_PRODUCTION_CLI.md | Product spec for future event production CLI work. |
| REFACTOR_IMESSAGE_CONTACTS.md | Refactor plan for shared iMessage/contact-resolution utilities. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function runScript(action: string, args: string[] = [], timeout = 30000): any { | ||
| const cmd = ["python3", SCRIPT_PATH, action, ...args].join(" ") | ||
| try { | ||
| const raw = execSync(cmd, { encoding: "utf-8", timeout }) |
| export const PlatformDeviceCommand = cmd({ | ||
| command: "device", | ||
| aliases: ["ios", "iphone"], | ||
| describe: "audit and manage device storage — real numbers via AFC, iCloud diagnosis, app offloading", |
| type: "string", | ||
| choices: ["iphone", "mac"] as const, | ||
| describe: "target device (default: auto-detect iPhone, fall back to Mac)", | ||
| }) |
| // Suggest connectors: providers detected locally but NOT yet connected | ||
| const suggested: string[] = [] | ||
| for (const [key, det] of Object.entries(detections)) { | ||
| if (det.confidence < 35) continue | ||
| const matchesAny = integrationKeys.some((ik) => key.includes(ik) || ik.includes(key)) |
| "url": "#about" | ||
| }, | ||
| { | ||
| "label": "Lashes", | ||
| "url": "#services" | ||
| }, | ||
| { | ||
| "label": "Story", | ||
| "url": "#story" | ||
| }, | ||
| { | ||
| "label": "Contact", | ||
| "url": "#contact" |
| "label": "About", | ||
| "url": "#about" | ||
| }, | ||
| { |
| """Offload an app (remove binary, keep data).""" | ||
| try: | ||
| from pymobiledevice3.lockdown import create_using_usbmux | ||
| from pymobiledevice3.services.installation_proxy import InstallationProxyService | ||
| lockdown = await create_using_usbmux() | ||
| async with InstallationProxyService(lockdown) as inst: | ||
| await inst.uninstall(bundle_id) | ||
| output({"success": True, "bundle_id": bundle_id}) | ||
| except Exception as e: | ||
| error(f"Offload failed for {bundle_id}: {e}") | ||
| export const PlatformScanCommand = cmd({ | ||
| command: "scan", | ||
| describe: "scan the local system to build a productivity-stack profile (apps, sync folders, integrations)", |
| "url": "#story" | ||
| }, | ||
| { | ||
| "label": "Contact", | ||
| "url": "#contact" |
| "title": "Marcus T. u2014 BMW 3 Series", | ||
| "subtitle": "Apr 5-8 u00b7 DFW Airport Pickup", |
Replaces the inline 7-field completeness % with a call to
GET /api/v1/leads/{id}/readiness?include=history. The TUI, the cron
snapshots, and the daily digest now all show the same number.
What renders now:
- Pulse: 32/100 failing (canonical readiness score)
- Trend: ▁▃▄▆█ (sparkline from history rows)
- Signals: req 60/100 · live — · comms 0/100 · cfg 0/100
(per-signal breakdown; '—' = signal not measurable for this lead)
Removed: lines 1525-1542 inline completeness calc.
Kept: every other panel (duplicates, notes, channels, links, deals).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Uh oh!
There was an error while loading. Please reload this page.
Summary
Test plan
🤖 Generated with Claude Code