forkit-connect 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -942,7 +942,7 @@ function buildInteractiveOverviewSections(service, sessionState, accountLimits)
942
942
  sections.push({
943
943
  title: 'Inbox',
944
944
  lines: [
945
- shellLine('Draft-first review', overview.draft_first_count),
945
+ shellLine('Private review', overview.draft_first_count),
946
946
  shellLine('Ready to connect', otherReadyCount),
947
947
  shellLine('Needs confirmation', overview.needs_confirmation_count),
948
948
  shellLine('Connected', overview.connected_count),
@@ -972,7 +972,7 @@ function buildInteractiveOverviewSections(service, sessionState, accountLimits)
972
972
  lines: [
973
973
  shellLine('Workspace', formatScopeReferenceLabel(preparedWorkspace || null, 'workspace')),
974
974
  shellLine('Project', formatScopeReferenceLabel(preparedProject || null, 'project')),
975
- shellLine('Draft-first review', overview.draft_first_count),
975
+ shellLine('Private review', overview.draft_first_count),
976
976
  shellLine('Ready to connect', otherReadyCount),
977
977
  shellLine('Needs confirmation', overview.needs_confirmation_count),
978
978
  ],
@@ -1433,7 +1433,7 @@ function formatSmartInboxActionLabel(item) {
1433
1433
  if (item.item_type === 'model'
1434
1434
  && item.recommended_action === 'create_passport_draft'
1435
1435
  && String(item.details_received_automatically.registration_flow_state || '').trim() === 'private_draft_required') {
1436
- return 'Open Draft Path';
1436
+ return 'Continue Registration';
1437
1437
  }
1438
1438
  return formatSmartInboxActionValue(item.recommended_action, item.item_type, String(item.details_received_automatically.connectable_model_name || '').trim());
1439
1439
  }
@@ -1488,7 +1488,7 @@ function printPublicStatusOverview(status) {
1488
1488
  console.log(`- scope=${status.workspace_id && status.project_id ? `${status.workspace_id} / ${status.project_id}` : 'not selected'}`);
1489
1489
  console.log(`- daemon=${status.daemon_status}`);
1490
1490
  console.log(`- local inventory=models ${status.models_discovered} · agents ${status.agents_discovered} · runtimes ${status.runtimes_discovered}`);
1491
- console.log(`- review queue=draft first ${status.draft_first_count} · ready ${otherReadyCount} · needs review ${status.needs_confirmation_count}`);
1491
+ console.log(`- review queue=private review ${status.draft_first_count} · ready ${otherReadyCount} · needs review ${status.needs_confirmation_count}`);
1492
1492
  console.log(`- connected records=${status.connected_count}`);
1493
1493
  console.log(`- pending runtime sync=${status.c2_sync_pending}`);
1494
1494
  console.log(`- privacy=${status.privacy_mode}`);
@@ -2131,7 +2131,7 @@ async function run() {
2131
2131
  {
2132
2132
  title: 'Queue',
2133
2133
  lines: [
2134
- shellLine('Draft-first review', payload.draft_first_count),
2134
+ shellLine('Private review', payload.draft_first_count),
2135
2135
  shellLine('Ready to connect', otherReadyCount),
2136
2136
  shellLine('Needs confirmation', payload.needs_confirmation_count),
2137
2137
  shellLine('Connected', payload.connected_count),
@@ -3892,11 +3892,11 @@ async function run() {
3892
3892
  if (raw === 'MODEL_SELECTION_AMBIGUOUS')
3893
3893
  return 'Model selection is ambiguous. Use a full discoveryHash.';
3894
3894
  if (raw === 'DRAFT_ALREADY_EXISTS')
3895
- return 'A backend draft already exists for this model. No duplicate draft created.';
3895
+ return 'Registration is already started privately for this model. No duplicate registration was created.';
3896
3896
  if (raw === 'SIMILAR_PASSPORT_EXISTS')
3897
- return 'A similar or existing passport already exists in your Forkit.dev account. Review existing records before creating a new draft.';
3897
+ return 'A similar or existing passport already exists in your Forkit.dev account. Review existing records before creating another registration.';
3898
3898
  if (raw === 'INVALID_DRAFT_VISIBILITY')
3899
- return 'This registration must start as a private draft. Review it in inbox/start first, or choose publish only when Forkit is ready to finish the passport.';
3899
+ return 'Forkit needs one private review step before this passport can finish publishing. Continue the registration from inbox/start first.';
3900
3900
  if (raw === 'WORKSPACE_PROJECT_BINDING_REQUIRED')
3901
3901
  return 'No governed workspace/project scope is linked yet. Select or create scope first.';
3902
3902
  if (raw === 'DRAFT_CREATION_NOT_ALLOWED_BY_BINDING')
@@ -3907,13 +3907,13 @@ async function run() {
3907
3907
  if (action === 'already_bound')
3908
3908
  return 'Model is already connected to an existing passport.';
3909
3909
  if (action === 'already_pending')
3910
- return 'Model already has a pending draft. No duplicate draft created.';
3910
+ return 'Registration already started privately. No duplicate registration was created.';
3911
3911
  if (action === 'passport_registered')
3912
- return 'Passport published successfully.';
3912
+ return 'Passport registered successfully.';
3913
3913
  if (action === 'draft_created')
3914
- return 'Draft created successfully.';
3914
+ return 'Private review started. Continue registration from inbox/start.';
3915
3915
  if (action === 'draft_queued')
3916
- return 'Draft queued locally and will sync when backend access is available.';
3916
+ return 'Registration saved locally and will sync when backend access is available.';
3917
3917
  return action;
3918
3918
  };
3919
3919
  const accountLimits = await loadCliAccountLimits().catch(() => null);
@@ -3937,7 +3937,9 @@ async function run() {
3937
3937
  });
3938
3938
  const runRegisterOne = async (targetModelSelector, displayNameHint) => {
3939
3939
  try {
3940
- const result = await service.connectDetectedModel(targetModelSelector);
3940
+ const result = await service.connectDetectedModel(targetModelSelector, hasFlag('--draft-only')
3941
+ ? { destination: 'draft', visibility: 'private' }
3942
+ : { destination: 'passport', visibility: 'public' });
3941
3943
  return {
3942
3944
  ok: true,
3943
3945
  model: result.model.model,
@@ -4501,7 +4503,10 @@ async function run() {
4501
4503
  return;
4502
4504
  }
4503
4505
  try {
4504
- const result = await service.connectDetectedModel(selector);
4506
+ const result = await service.connectDetectedModel(selector, {
4507
+ destination: 'passport',
4508
+ visibility: 'public',
4509
+ });
4505
4510
  if (result.action === 'already_bound') {
4506
4511
  console.log('Model is already bound to a Passport.');
4507
4512
  if (result.gaid) {
@@ -4510,14 +4515,22 @@ async function run() {
4510
4515
  return;
4511
4516
  }
4512
4517
  if (result.action === 'already_pending') {
4513
- console.log('Model already has a pending Passport draft.');
4518
+ console.log('Registration already started privately for this model.');
4514
4519
  if (result.draftId) {
4515
4520
  console.log(`Draft ID: ${result.draftId}`);
4516
4521
  }
4517
4522
  return;
4518
4523
  }
4524
+ if (result.action === 'passport_registered') {
4525
+ console.log('Passport registered successfully.');
4526
+ console.log(`Model: ${result.model.model}`);
4527
+ if (result.gaid) {
4528
+ console.log(`Passport GAID: ${result.gaid}`);
4529
+ }
4530
+ return;
4531
+ }
4519
4532
  if (result.action === 'draft_created') {
4520
- console.log('Passport draft created from detected model.');
4533
+ console.log('Registration started privately for review.');
4521
4534
  console.log(`Model: ${result.model.model}`);
4522
4535
  if (result.draftId) {
4523
4536
  console.log(`Draft ID: ${result.draftId}`);
@@ -4527,9 +4540,9 @@ async function run() {
4527
4540
  }
4528
4541
  return;
4529
4542
  }
4530
- console.log('Passport draft queued locally from detected model.');
4543
+ console.log('Registration saved locally and will sync when Forkit Connect can reach Forkit.dev.');
4531
4544
  console.log(`Model: ${result.model.model}`);
4532
- console.log('Complete login later and run scan or queue processing to sync it.');
4545
+ console.log('Complete login later and run scan or queue processing to continue it.');
4533
4546
  return;
4534
4547
  }
4535
4548
  catch (error) {
package/dist/launcher.js CHANGED
@@ -434,7 +434,7 @@ function formatBindingStatusLabel(status) {
434
434
  return { label: 'Published', meta: 'Live on Forkit.dev', tone: 'ok' };
435
435
  }
436
436
  if (normalized === 'pending') {
437
- return { label: 'Draft', meta: 'In progress', tone: 'warn' };
437
+ return { label: 'Private review', meta: 'In progress', tone: 'warn' };
438
438
  }
439
439
  if (normalized === 'ignored') {
440
440
  return { label: 'Archived', meta: 'Not active locally', tone: 'muted' };
@@ -449,7 +449,7 @@ function formatPassportHistoryLabel(type) {
449
449
  return { label: 'Passport linked', tone: 'ok' };
450
450
  case 'model_draft_created':
451
451
  case 'model_draft_synced':
452
- return { label: 'Draft created', tone: 'warn' };
452
+ return { label: 'Private review started', tone: 'warn' };
453
453
  case 'passport_draft_requested':
454
454
  case 'model_draft_queued':
455
455
  return { label: 'Registration queued', tone: 'warn' };
@@ -538,10 +538,10 @@ function normalizeDiscoveryRegistrationFailure(message) {
538
538
  if (normalized === 'INVALID_DRAFT_VISIBILITY') {
539
539
  return {
540
540
  code: normalized,
541
- message: 'This registration needs to start as a private draft before it can be published.',
541
+ message: 'Forkit needs one private review step before this passport can finish publishing.',
542
542
  nextActions: [
543
- 'Keep the item in review or open the draft path first.',
544
- 'Choose publish only when Forkit is ready to finish the passport.',
543
+ 'Continue registration privately first.',
544
+ 'Publish only after Forkit has finished the private review step.',
545
545
  ],
546
546
  };
547
547
  }
@@ -694,17 +694,17 @@ function buildDiscovery(service) {
694
694
  actionTone = 'muted';
695
695
  }
696
696
  else if (draftPending) {
697
- statusLabel = 'Draft created';
698
- statusMeta = 'Registration draft is already waiting in Passports.';
697
+ statusLabel = 'Registration in progress';
698
+ statusMeta = 'Forkit already started this privately. Continue it in Passports instead of starting over.';
699
699
  statusTone = 'warn';
700
- actionLabel = 'Review';
700
+ actionLabel = 'Continue';
701
701
  actionTone = 'accent';
702
702
  }
703
703
  else if (registrationState === 'private_draft_required') {
704
- statusLabel = 'Draft first';
705
- statusMeta = registrationGuidance ?? 'This model needs to go through the private draft path before publishing.';
704
+ statusLabel = 'Finish privately first';
705
+ statusMeta = registrationGuidance ?? 'Forkit needs one private review step before this passport can finish publishing.';
706
706
  statusTone = 'warn';
707
- actionLabel = 'Review';
707
+ actionLabel = 'Continue';
708
708
  actionTone = 'accent';
709
709
  }
710
710
  else if (group === 'connected') {
@@ -741,6 +741,7 @@ function buildDiscovery(service) {
741
741
  recommendedAction: entry.recommended_action,
742
742
  workspaceId: entry.workspaceId,
743
743
  projectId: entry.projectId,
744
+ draftId: binding?.draftId ?? null,
744
745
  passportGaid: entry.passport_gaid,
745
746
  matchedPassportGaid: entry.matched_passport_gaid,
746
747
  detailSummary: verificationSummary ?? scopeSuggestion ?? matchReason,
@@ -791,10 +792,10 @@ function buildDiscovery(service) {
791
792
  actionTone = 'accent';
792
793
  }
793
794
  else if (draftId || trackingStatus === 'draft_created') {
794
- statusLabel = 'Draft created';
795
- statusMeta = 'Pending review in Passports.';
795
+ statusLabel = 'Registration in progress';
796
+ statusMeta = 'Forkit already started this privately. Continue it in Passports.';
796
797
  statusTone = 'warn';
797
- actionLabel = 'Review';
798
+ actionLabel = 'Continue';
798
799
  actionTone = 'accent';
799
800
  }
800
801
  else if (group === 'connected' || linkedPassportGaid) {
@@ -835,6 +836,7 @@ function buildDiscovery(service) {
835
836
  recommendedAction: entry.recommended_action,
836
837
  workspaceId: entry.workspaceId,
837
838
  projectId: entry.projectId,
839
+ draftId,
838
840
  passportGaid: linkedPassportGaid,
839
841
  matchedPassportGaid: entry.matched_passport_gaid,
840
842
  detailSummary: statusMeta,
@@ -929,7 +931,7 @@ function buildDiscovery(service) {
929
931
  localDetection: state.detected_runtimes.length > 0 || state.detected_models.length > 0 ? 'active' : 'attention',
930
932
  metadataExtraction: state.detected_models.length > 0 ? 'active' : 'attention',
931
933
  duplicateMatching: inbox.existing_passport_match_candidates.length > 0 || state.model_bindings.length > 0 ? 'active' : 'attention',
932
- passportReadiness: `${draftFirstCount} draft-first · ${otherReadyCount} ready · ${inbox.summary.needs_confirmation_count} review · ${inbox.summary.connected_count} linked`,
934
+ passportReadiness: `${draftFirstCount} private review · ${otherReadyCount} ready · ${inbox.summary.needs_confirmation_count} review · ${inbox.summary.connected_count} linked`,
933
935
  },
934
936
  groups: {
935
937
  ready_to_connect: inbox.groups.ready_to_connect.length,
@@ -1799,7 +1801,9 @@ function renderLauncherHtml(launcherToken) {
1799
1801
  .quick-review-chip:focus-visible,
1800
1802
  .quick-review-primary:focus-visible,
1801
1803
  .quick-review-options-button:focus-visible,
1804
+ .review-mode-button:focus-visible,
1802
1805
  .quick-review-field select:focus-visible,
1806
+ .discovery-review-field select:focus-visible,
1803
1807
  .quick-review-options-menu button:focus-visible {
1804
1808
  outline: 2px solid rgba(157, 238, 245, 0.72);
1805
1809
  outline-offset: 2px;
@@ -1991,12 +1995,66 @@ function renderLauncherHtml(launcherToken) {
1991
1995
  gap: 10px;
1992
1996
  }
1993
1997
 
1998
+ .review-mode-group {
1999
+ display: grid;
2000
+ gap: 8px;
2001
+ }
2002
+
2003
+ .review-mode-label {
2004
+ font-size: 0.74rem;
2005
+ text-transform: uppercase;
2006
+ letter-spacing: 0.12em;
2007
+ font-weight: 700;
2008
+ color: rgba(241, 235, 223, 0.62);
2009
+ }
2010
+
2011
+ .review-mode-toggle {
2012
+ display: inline-grid;
2013
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2014
+ gap: 8px;
2015
+ padding: 6px;
2016
+ border-radius: 18px;
2017
+ border: 1px solid rgba(241, 235, 223, 0.08);
2018
+ background: rgba(255,255,255,0.04);
2019
+ }
2020
+
2021
+ .review-mode-button {
2022
+ min-height: 42px;
2023
+ border: 1px solid rgba(241, 235, 223, 0.08);
2024
+ border-radius: 14px;
2025
+ background: transparent;
2026
+ color: rgba(241, 235, 223, 0.72);
2027
+ font: inherit;
2028
+ font-size: 0.88rem;
2029
+ font-weight: 600;
2030
+ cursor: pointer;
2031
+ transition: border-color 160ms ease, background 160ms ease, color 160ms ease, transform 160ms ease;
2032
+ }
2033
+
2034
+ .review-mode-button:hover {
2035
+ border-color: rgba(157, 238, 245, 0.26);
2036
+ color: #fff8ef;
2037
+ transform: translateY(-1px);
2038
+ }
2039
+
2040
+ .review-mode-button.active {
2041
+ border-color: rgba(157, 238, 245, 0.34);
2042
+ background: linear-gradient(135deg, rgba(55, 68, 86, 0.62), rgba(31, 36, 56, 0.92));
2043
+ color: #fff8ef;
2044
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
2045
+ }
2046
+
1994
2047
  .quick-review-scope-grid {
1995
2048
  display: grid;
1996
2049
  grid-template-columns: 1fr 1fr;
1997
2050
  gap: 10px;
1998
2051
  }
1999
2052
 
2053
+ .quick-review-scope-grid[hidden],
2054
+ .discovery-review-scope-grid[hidden] {
2055
+ display: none;
2056
+ }
2057
+
2000
2058
  .quick-review-field {
2001
2059
  display: grid;
2002
2060
  gap: 6px;
@@ -6454,7 +6512,7 @@ function renderLauncherHtml(launcherToken) {
6454
6512
  <div class="quick-review-summary-grid">
6455
6513
  <div class="quick-review-summary-pill">
6456
6514
  <span class="quick-review-summary-label">Action</span>
6457
- <span class="quick-review-summary-value" id="quick-review-action-summary">Approve and register</span>
6515
+ <span class="quick-review-summary-value" id="quick-review-action-summary">Register on this account now</span>
6458
6516
  </div>
6459
6517
  <div class="quick-review-summary-pill">
6460
6518
  <span class="quick-review-summary-label">Scope</span>
@@ -6463,7 +6521,14 @@ function renderLauncherHtml(launcherToken) {
6463
6521
  </div>
6464
6522
  <div class="quick-review-status" id="quick-review-status">Waiting for review.</div>
6465
6523
  <div class="quick-review-scope" id="quick-review-scope" hidden>
6466
- <div class="quick-review-scope-grid">
6524
+ <div class="review-mode-group" id="quick-review-mode">
6525
+ <span class="review-mode-label">Register as</span>
6526
+ <div class="review-mode-toggle" role="group" aria-label="Quick review registration path">
6527
+ <button class="review-mode-button active" id="quick-review-mode-solo" type="button" aria-pressed="true">Solo</button>
6528
+ <button class="review-mode-button" id="quick-review-mode-workspace" type="button" aria-pressed="false">Governed workspace</button>
6529
+ </div>
6530
+ </div>
6531
+ <div class="quick-review-scope-grid" id="quick-review-scope-grid" hidden>
6467
6532
  <div class="quick-review-field">
6468
6533
  <label for="quick-review-workspace">Workspace</label>
6469
6534
  <select id="quick-review-workspace"></select>
@@ -6867,7 +6932,14 @@ function renderLauncherHtml(launcherToken) {
6867
6932
  <p class="discovery-review-detail" id="discovery-review-detail">Registering creates or updates a Forkit Passport. Nothing is published automatically.</p>
6868
6933
  <div class="discovery-review-status" id="discovery-review-status">Select an item to continue.</div>
6869
6934
  <div class="discovery-review-scope" id="discovery-review-scope" hidden>
6870
- <div class="discovery-review-scope-grid">
6935
+ <div class="review-mode-group" id="discovery-review-mode">
6936
+ <span class="review-mode-label">Register as</span>
6937
+ <div class="review-mode-toggle" role="group" aria-label="Discovery review registration path">
6938
+ <button class="review-mode-button active" id="discovery-review-mode-solo" type="button" aria-pressed="true">Solo</button>
6939
+ <button class="review-mode-button" id="discovery-review-mode-workspace" type="button" aria-pressed="false">Governed workspace</button>
6940
+ </div>
6941
+ </div>
6942
+ <div class="discovery-review-scope-grid" id="discovery-review-scope-grid" hidden>
6871
6943
  <div class="discovery-review-field">
6872
6944
  <label for="discovery-review-workspace">Workspace</label>
6873
6945
  <select id="discovery-review-workspace"></select>
@@ -7252,7 +7324,7 @@ function renderLauncherHtml(launcherToken) {
7252
7324
  <div class="scope-modal-backdrop" id="scope-modal" hidden>
7253
7325
  <div class="scope-modal" role="dialog" aria-modal="true" aria-labelledby="scope-modal-title">
7254
7326
  <h3 id="scope-modal-title">Choose registration scope</h3>
7255
- <p id="scope-modal-copy">Select the workspace and project that should own this Passport registration.</p>
7327
+ <p id="scope-modal-copy">Register on your account now, or choose a governed workspace/project when you need governed ownership.</p>
7256
7328
  <div class="scope-field-grid">
7257
7329
  <div class="scope-field">
7258
7330
  <label for="scope-workspace-select">Workspace</label>
@@ -7400,9 +7472,53 @@ function renderLauncherHtml(launcherToken) {
7400
7472
  return true;
7401
7473
  }
7402
7474
 
7475
+ function focusPassportByDraftId(draftId, options) {
7476
+ const normalizedDraftId = String(draftId || '').trim();
7477
+ if (!normalizedDraftId) return false;
7478
+ const passports = latestPassports && Array.isArray(latestPassports.items) ? latestPassports.items : [];
7479
+ const match = passports.find((entry) => String(entry.draftId || '').trim() === normalizedDraftId);
7480
+ if (!match) return false;
7481
+ selectedPassportId = match.id;
7482
+ passportHistoryVisible = Boolean(options && options.showHistory);
7483
+ selectedWorkspaceScope = ALL_SCOPE_VALUE;
7484
+ selectedProjectScope = ALL_SCOPE_VALUE;
7485
+ renderGlobalLaunchHeaderAndCards();
7486
+ setView('passports', { skipRouteUpdate: true });
7487
+ renderPassportsRows();
7488
+ updateRoute('passports', { passport: match.gaid || match.id, ...(passportHistoryVisible ? { focus: 'history' } : {}) });
7489
+ return true;
7490
+ }
7491
+
7492
+ function getReviewScopeMode(workspaceId, projectId) {
7493
+ return String(workspaceId || '').trim() && String(projectId || '').trim() ? 'workspace' : 'solo';
7494
+ }
7495
+
7496
+ function isContinuationReviewItem(item) {
7497
+ return Boolean(item && (
7498
+ item.actionLabel === 'Continue'
7499
+ || item.statusLabel === 'Registration in progress'
7500
+ || item.statusLabel === 'Finish privately first'
7501
+ ));
7502
+ }
7503
+
7504
+ function shouldOpenReviewContext(item) {
7505
+ return Boolean(
7506
+ item
7507
+ && (
7508
+ item.kind === 'runtime'
7509
+ || item.passportGaid
7510
+ || item.matchedPassportGaid
7511
+ || item.actionLabel === 'Open'
7512
+ || item.actionLabel === 'Review'
7513
+ || isContinuationReviewItem(item)
7514
+ )
7515
+ );
7516
+ }
7517
+
7403
7518
  async function openDiscoveryContext(item) {
7404
7519
  if (!item) return false;
7405
7520
  const preferredPassportGaid = String(item.passportGaid || item.matchedPassportGaid || '').trim();
7521
+ const preferredDraftId = String(item.draftId || '').trim();
7406
7522
  if (preferredPassportGaid) {
7407
7523
  if (!latestPassports) {
7408
7524
  await refreshPassports();
@@ -7411,6 +7527,14 @@ function renderLauncherHtml(launcherToken) {
7411
7527
  return true;
7412
7528
  }
7413
7529
  }
7530
+ if (preferredDraftId) {
7531
+ if (!latestPassports) {
7532
+ await refreshPassports();
7533
+ }
7534
+ if (focusPassportByDraftId(preferredDraftId, { showHistory: true })) {
7535
+ return true;
7536
+ }
7537
+ }
7414
7538
  if (item.kind === 'model' || item.kind === 'agent') {
7415
7539
  await openRegistrationScopeDialog(item);
7416
7540
  return true;
@@ -7500,6 +7624,53 @@ function renderLauncherHtml(launcherToken) {
7500
7624
  status.className = 'quick-review-status' + (tone ? ' ' + tone : '');
7501
7625
  }
7502
7626
 
7627
+ function canChooseReviewScope(item) {
7628
+ return Boolean(canReviewRegister(item) && !shouldOpenReviewContext(item));
7629
+ }
7630
+
7631
+ function getReviewRegistrationMode(prefix) {
7632
+ const scope = document.getElementById(prefix + '-scope');
7633
+ if (!scope) return 'solo';
7634
+ return String(scope.dataset.mode || '').trim() === 'workspace' ? 'workspace' : 'solo';
7635
+ }
7636
+
7637
+ function setReviewRegistrationMode(prefix, mode) {
7638
+ const normalized = mode === 'workspace' ? 'workspace' : 'solo';
7639
+ const scope = document.getElementById(prefix + '-scope');
7640
+ const scopeGrid = document.getElementById(prefix + '-scope-grid');
7641
+ if (scope) {
7642
+ scope.dataset.mode = normalized;
7643
+ }
7644
+ if (scopeGrid) {
7645
+ scopeGrid.hidden = normalized !== 'workspace';
7646
+ }
7647
+ ['solo', 'workspace'].forEach((candidate) => {
7648
+ const button = document.getElementById(prefix + '-mode-' + candidate);
7649
+ if (!button) return;
7650
+ const active = candidate === normalized;
7651
+ button.classList.toggle('active', active);
7652
+ button.setAttribute('aria-pressed', active ? 'true' : 'false');
7653
+ });
7654
+ return normalized;
7655
+ }
7656
+
7657
+ function getPassiveReviewScopeSummary(item) {
7658
+ if (!item) return 'Review';
7659
+ if (item.kind === 'runtime') {
7660
+ return item.statusTone === 'error' ? 'Runtime fix' : 'Runtime review';
7661
+ }
7662
+ if (isContinuationReviewItem(item)) {
7663
+ return 'Private review';
7664
+ }
7665
+ if (item.passportGaid) {
7666
+ return 'Linked passport';
7667
+ }
7668
+ if (item.matchedPassportGaid) {
7669
+ return 'Existing passport';
7670
+ }
7671
+ return 'Full review';
7672
+ }
7673
+
7503
7674
  function resetReviewResolutionActions(prefix) {
7504
7675
  setReviewResolutionActions(prefix, []);
7505
7676
  }
@@ -7514,13 +7685,14 @@ function renderLauncherHtml(launcherToken) {
7514
7685
  ].map((value) => String(value || '').trim()).find(Boolean) || '';
7515
7686
  }
7516
7687
 
7517
- function getReviewPrimaryLabel(item) {
7688
+ function getReviewPrimaryLabel(item, scopeMode) {
7689
+ const effectiveScopeMode = scopeMode === 'workspace' ? 'workspace' : 'solo';
7518
7690
  if (!item) return 'Review';
7519
7691
  if (item.kind === 'runtime') {
7520
7692
  return item.statusTone === 'error' ? 'Open runtime fix' : 'Open runtime review';
7521
7693
  }
7522
- if (item.statusLabel === 'Draft created') {
7523
- return 'Open draft';
7694
+ if (isContinuationReviewItem(item)) {
7695
+ return 'Continue registration';
7524
7696
  }
7525
7697
  if (item.passportGaid) {
7526
7698
  return 'Open passport';
@@ -7534,16 +7706,17 @@ function renderLauncherHtml(launcherToken) {
7534
7706
  if (item.actionLabel === 'Open' || item.actionLabel === 'Review') {
7535
7707
  return 'Review in context';
7536
7708
  }
7537
- return 'Approve & register';
7709
+ return effectiveScopeMode === 'workspace' ? 'Register in workspace' : 'Register solo';
7538
7710
  }
7539
7711
 
7540
- function getReviewActionSummary(item) {
7712
+ function getReviewActionSummary(item, scopeMode) {
7713
+ const effectiveScopeMode = scopeMode === 'workspace' ? 'workspace' : 'solo';
7541
7714
  if (!item) return 'Review';
7542
7715
  if (item.kind === 'runtime') {
7543
7716
  return item.statusTone === 'error' ? 'Resolve runtime attention' : 'Open runtime lane';
7544
7717
  }
7545
- if (item.statusLabel === 'Draft created') {
7546
- return 'Continue the existing draft';
7718
+ if (isContinuationReviewItem(item)) {
7719
+ return 'Continue the private review step before this passport finishes publishing';
7547
7720
  }
7548
7721
  if (item.passportGaid) {
7549
7722
  return 'Open the linked passport';
@@ -7557,7 +7730,9 @@ function renderLauncherHtml(launcherToken) {
7557
7730
  if (item.actionLabel === 'Open' || item.actionLabel === 'Review') {
7558
7731
  return 'Open full review';
7559
7732
  }
7560
- return 'Approve and register here';
7733
+ return effectiveScopeMode === 'workspace'
7734
+ ? 'Register this item in the selected workspace'
7735
+ : 'Register this item on your account now';
7561
7736
  }
7562
7737
 
7563
7738
  function getReviewDetailText(item) {
@@ -7567,8 +7742,11 @@ function renderLauncherHtml(launcherToken) {
7567
7742
  ? 'Runtime attention is required before linked models can keep registering cleanly.'
7568
7743
  : 'Open runtime review to confirm health, scope, and connected models.';
7569
7744
  }
7570
- if (item.statusLabel === 'Draft created') {
7571
- return 'A draft already exists. Continue it in Passports instead of creating another one.';
7745
+ if (item.statusLabel === 'Registration in progress') {
7746
+ return 'Forkit already started this registration privately. Continue it in Passports instead of creating a second record.';
7747
+ }
7748
+ if (item.statusLabel === 'Finish privately first') {
7749
+ return 'Forkit needs one private review step before it can publish this passport. Continue registration and finish the private step first.';
7572
7750
  }
7573
7751
  if (item.matchedPassportGaid && !item.passportGaid) {
7574
7752
  return 'Forkit Connect found a matching passport. Reuse it before creating anything new.';
@@ -7608,7 +7786,7 @@ function renderLauncherHtml(launcherToken) {
7608
7786
  : result && result.code === 'SIMILAR_PASSPORT_EXISTS'
7609
7787
  ? 'Matching passport exists · reuse it instead of creating another'
7610
7788
  : result && result.code === 'INVALID_DRAFT_VISIBILITY'
7611
- ? 'Draft first · keep this registration private until it is ready to publish'
7789
+ ? 'Private review first · continue registration privately before publishing'
7612
7790
  : result && (result.code === 'WORKSPACE_PROJECT_BINDING_REQUIRED' || result.code === 'DRAFT_CREATION_NOT_ALLOWED_BY_BINDING')
7613
7791
  ? 'Scope required · choose workspace and project'
7614
7792
  : null,
@@ -7728,15 +7906,19 @@ function renderLauncherHtml(launcherToken) {
7728
7906
  }
7729
7907
  }
7730
7908
 
7731
- function updateQuickReviewScopeSummary(governedMode) {
7909
+ function updateQuickReviewScopeSummary(scopeMode) {
7732
7910
  const workspaceSelect = document.getElementById('quick-review-workspace');
7733
7911
  const projectSelect = document.getElementById('quick-review-project');
7734
7912
  const workspaceId = workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
7735
7913
  const projectId = projectSelect ? String(projectSelect.value || '').trim() : '';
7736
7914
  const workspaceLabel = readSelectedOptionLabel(workspaceSelect);
7737
7915
  const projectLabel = readSelectedOptionLabel(projectSelect);
7916
+ if (scopeMode !== 'workspace') {
7917
+ setText('quick-review-scope-summary', 'Account scope');
7918
+ return;
7919
+ }
7738
7920
  if (!workspaceId) {
7739
- setText('quick-review-scope-summary', governedMode ? 'Choose governed scope' : 'Account scope');
7921
+ setText('quick-review-scope-summary', 'Choose governed workspace');
7740
7922
  return;
7741
7923
  }
7742
7924
  if (!projectId) {
@@ -7746,14 +7928,41 @@ function renderLauncherHtml(launcherToken) {
7746
7928
  setText('quick-review-scope-summary', [workspaceLabel, projectLabel].filter(Boolean).join(' · ') || 'Governed project');
7747
7929
  }
7748
7930
 
7749
- async function loadQuickReviewProjects(workspaceId, selectedProjectId, governedMode) {
7931
+ function syncQuickReviewRegistrationMode(item, mode) {
7932
+ const reviewScopeMode = setReviewRegistrationMode('quick-review', mode);
7933
+ const workspaceSelect = document.getElementById('quick-review-workspace');
7934
+ const projectSelect = document.getElementById('quick-review-project');
7935
+ const primaryButton = document.getElementById('quick-review-primary');
7936
+ const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect
7937
+ ? String(workspaceSelect.value || '').trim()
7938
+ : '';
7939
+ const projectId = reviewScopeMode === 'workspace' && projectSelect
7940
+ ? String(projectSelect.value || '').trim()
7941
+ : '';
7942
+ if (primaryButton && item) {
7943
+ primaryButton.textContent = getReviewPrimaryLabel(item, reviewScopeMode);
7944
+ primaryButton.disabled = item.inboxGroup === 'ignored' || (reviewScopeMode === 'workspace' && (!workspaceId || !projectId));
7945
+ }
7946
+ if (item) {
7947
+ setText('quick-review-action-summary', getReviewActionSummary(item, reviewScopeMode));
7948
+ }
7949
+ updateQuickReviewScopeSummary(reviewScopeMode);
7950
+ return reviewScopeMode;
7951
+ }
7952
+
7953
+ async function loadQuickReviewProjects(workspaceId, selectedProjectId, scopeMode) {
7750
7954
  const projectSelect = document.getElementById('quick-review-project');
7751
7955
  const primaryButton = document.getElementById('quick-review-primary');
7752
7956
  if (!projectSelect) return;
7753
7957
  if (!workspaceId) {
7754
- setScopeOptions(projectSelect, [{ id: '', label: governedMode ? 'Choose workspace first' : 'Account scope / no project' }], '');
7755
- if (primaryButton) primaryButton.disabled = governedMode;
7756
- updateQuickReviewScopeSummary(governedMode);
7958
+ if (scopeMode === 'workspace') {
7959
+ setScopeOptions(projectSelect, [{ id: '', label: 'Choose a workspace first' }], '');
7960
+ if (primaryButton) primaryButton.disabled = true;
7961
+ } else {
7962
+ setScopeOptions(projectSelect, [{ id: '', label: 'Solo registration / no project' }], '');
7963
+ if (primaryButton) primaryButton.disabled = false;
7964
+ }
7965
+ updateQuickReviewScopeSummary(scopeMode);
7757
7966
  return;
7758
7967
  }
7759
7968
  setScopeOptions(projectSelect, [{ id: '', label: 'Loading projects...' }], '');
@@ -7773,14 +7982,14 @@ function renderLauncherHtml(launcherToken) {
7773
7982
  if (primaryButton) {
7774
7983
  primaryButton.disabled = !projects.length;
7775
7984
  }
7776
- updateQuickReviewScopeSummary(governedMode);
7985
+ updateQuickReviewScopeSummary(scopeMode);
7777
7986
  } catch {
7778
7987
  setScopeOptions(projectSelect, [{ id: '', label: 'Project list unavailable' }], '');
7779
7988
  setQuickReviewStatus('Project list is unavailable right now.', 'warn');
7780
7989
  if (primaryButton) {
7781
7990
  primaryButton.disabled = true;
7782
7991
  }
7783
- updateQuickReviewScopeSummary(governedMode);
7992
+ updateQuickReviewScopeSummary(scopeMode);
7784
7993
  }
7785
7994
  }
7786
7995
 
@@ -7818,10 +8027,10 @@ function renderLauncherHtml(launcherToken) {
7818
8027
  setQuickReviewStatus(item.statusLabel + (item.statusMeta ? ' · ' + item.statusMeta : ''), item.statusTone === 'muted' ? '' : item.statusTone);
7819
8028
  resetReviewResolutionActions('quick-review');
7820
8029
 
7821
- const primaryLabel = getReviewPrimaryLabel(item);
8030
+ const primaryLabel = getReviewPrimaryLabel(item, 'solo');
7822
8031
  setText(
7823
8032
  'quick-review-action-summary',
7824
- getReviewActionSummary(item),
8033
+ getReviewActionSummary(item, 'solo'),
7825
8034
  );
7826
8035
  if (primaryButton) {
7827
8036
  primaryButton.textContent = primaryLabel;
@@ -7840,17 +8049,22 @@ function renderLauncherHtml(launcherToken) {
7840
8049
  ignoreButton.hidden = !canReviewIgnore(item);
7841
8050
  }
7842
8051
 
7843
- const needsScope = canReviewRegister(item);
7844
- if (!needsScope) {
8052
+ const showScopeChoice = canChooseReviewScope(item);
8053
+ if (!showScopeChoice) {
7845
8054
  if (scopeWrap) scopeWrap.hidden = true;
8055
+ setReviewRegistrationMode('quick-review', 'solo');
7846
8056
  quickReviewScopeCacheKey = null;
7847
- setText('quick-review-scope-summary', item.kind === 'runtime' ? 'Open runtime review' : 'Full review available');
8057
+ setText('quick-review-scope-summary', getPassiveReviewScopeSummary(item));
7848
8058
  return;
7849
8059
  }
7850
8060
 
7851
8061
  if (scopeWrap) scopeWrap.hidden = false;
7852
8062
  if (!workspaceSelect || !projectSelect) return;
7853
8063
  const cacheKey = item.id + ':' + String(item.workspaceId || '') + ':' + String(item.projectId || '');
8064
+ syncQuickReviewRegistrationMode(
8065
+ item,
8066
+ quickReviewScopeCacheKey === cacheKey ? getReviewRegistrationMode('quick-review') : 'solo',
8067
+ );
7854
8068
  if (quickReviewScopeCacheKey === cacheKey) {
7855
8069
  return;
7856
8070
  }
@@ -7863,35 +8077,43 @@ function renderLauncherHtml(launcherToken) {
7863
8077
  const response = await apiFetch('/api/scope/access');
7864
8078
  const payload = await response.json();
7865
8079
  scopeAccessSnapshot = payload;
7866
- const governedMode = payload && payload.operatingMode === 'governed';
7867
8080
  const workspaces = payload.ok && Array.isArray(payload.workspaces) ? payload.workspaces : [];
7868
8081
  const options = [
7869
- ...(governedMode ? [] : [{ id: '', label: 'Account scope / no workspace' }]),
8082
+ { id: '', label: 'Register solo / account scope' },
7870
8083
  ...workspaces.map((workspace) => ({ id: workspace.id, label: workspace.name || workspace.id })),
7871
8084
  ];
7872
- if (governedMode && !options.length) {
7873
- options.push({ id: '', label: 'No governed workspaces yet' });
7874
- }
7875
- const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || (options[0] && options[0].id) || '';
8085
+ const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || '';
8086
+ const selectedProject = item.projectId || payload.currentProjectId || '';
7876
8087
  setScopeOptions(workspaceSelect, options, selectedWorkspace);
7877
- await loadQuickReviewProjects(selectedWorkspace, item.projectId || payload.currentProjectId || '', governedMode);
8088
+ await loadQuickReviewProjects(selectedWorkspace, selectedProject, getReviewRegistrationMode('quick-review'));
8089
+ const reviewScopeMode = syncQuickReviewRegistrationMode(item, getReviewRegistrationMode('quick-review'));
7878
8090
  setQuickReviewStatus(
7879
8091
  payload.ok
7880
- ? (governedMode
7881
- ? 'Choose the governed workspace and project for this registration.'
7882
- : 'Account scope stays available. Choose governed scope only when needed.')
7883
- : (payload.message || 'Workspace access is unavailable right now.'),
8092
+ ? (reviewScopeMode === 'workspace'
8093
+ ? (selectedWorkspace
8094
+ ? 'Choose the governed workspace and project for this registration.'
8095
+ : workspaces.length
8096
+ ? 'Choose a workspace and project for governed registration.'
8097
+ : 'No governed workspaces are available yet. Switch back to solo or create one first.')
8098
+ : 'Solo registration is ready. Choose governed workspace only when needed.')
8099
+ : (reviewScopeMode === 'workspace'
8100
+ ? (payload.message || 'Workspace access is unavailable right now. Switch to solo registration or retry later.')
8101
+ : 'Solo registration is still available. Governed workspace access is unavailable right now.'),
7884
8102
  payload.ok ? '' : 'warn',
7885
8103
  );
7886
- updateQuickReviewScopeSummary(governedMode);
7887
8104
  } catch {
7888
8105
  setScopeOptions(workspaceSelect, [{ id: '', label: 'Workspace list unavailable' }], '');
7889
8106
  setScopeOptions(projectSelect, [{ id: '', label: 'Project list unavailable' }], '');
7890
- setQuickReviewStatus('Workspace access is unavailable right now.', 'warn');
7891
- if (primaryButton) {
7892
- primaryButton.disabled = true;
8107
+ const reviewScopeMode = syncQuickReviewRegistrationMode(item, getReviewRegistrationMode('quick-review'));
8108
+ setQuickReviewStatus(
8109
+ reviewScopeMode === 'workspace'
8110
+ ? 'Workspace access is unavailable right now. Switch to solo registration or retry later.'
8111
+ : 'Solo registration is still available. Governed workspace access is unavailable right now.',
8112
+ 'warn',
8113
+ );
8114
+ if (reviewScopeMode === 'workspace') {
8115
+ setText('quick-review-scope-summary', 'Scope unavailable');
7893
8116
  }
7894
- setText('quick-review-scope-summary', 'Scope unavailable');
7895
8117
  }
7896
8118
  }
7897
8119
 
@@ -7899,7 +8121,7 @@ function renderLauncherHtml(launcherToken) {
7899
8121
  const item = getQuickReviewItem();
7900
8122
  if (!item) return;
7901
8123
  selectedDiscoveryId = item.id;
7902
- if (item.kind === 'runtime' || item.actionLabel === 'Open' || item.actionLabel === 'Review') {
8124
+ if (shouldOpenReviewContext(item)) {
7903
8125
  await openDiscoveryContext(item);
7904
8126
  setQuickReviewPanelOpen(false);
7905
8127
  return;
@@ -7911,17 +8133,13 @@ function renderLauncherHtml(launcherToken) {
7911
8133
  const workspaceSelect = document.getElementById('quick-review-workspace');
7912
8134
  const projectSelect = document.getElementById('quick-review-project');
7913
8135
  const primaryButton = document.getElementById('quick-review-primary');
7914
- const workspaceId = workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
7915
- const projectId = projectSelect ? String(projectSelect.value || '').trim() : '';
7916
- const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
7917
- if (workspaceId && !projectId) {
8136
+ const reviewScopeMode = getReviewRegistrationMode('quick-review');
8137
+ const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
8138
+ const projectId = reviewScopeMode === 'workspace' && projectSelect ? String(projectSelect.value || '').trim() : '';
8139
+ if (reviewScopeMode === 'workspace' && (!workspaceId || !projectId)) {
7918
8140
  setQuickReviewStatus('Select a project for the chosen workspace, or switch back to account scope.', 'warn');
7919
8141
  return;
7920
8142
  }
7921
- if (!workspaceId && governedMode) {
7922
- setQuickReviewStatus('Choose the governed workspace and project before registering here.', 'warn');
7923
- return;
7924
- }
7925
8143
  if (primaryButton) primaryButton.disabled = true;
7926
8144
  const endpoint = item.kind === 'agent' ? '/api/discovery/connect-agent' : '/api/discovery/connect-model';
7927
8145
  const result = await postAction(endpoint, 'Registering with Forkit Connect...', {
@@ -7995,13 +8213,39 @@ function renderLauncherHtml(launcherToken) {
7995
8213
  }
7996
8214
  }
7997
8215
 
7998
- async function loadDiscoveryReviewProjects(workspaceId, selectedProjectId, governedMode) {
8216
+ function syncDiscoveryReviewRegistrationMode(item, mode) {
8217
+ const reviewScopeMode = setReviewRegistrationMode('discovery-review', mode);
8218
+ const workspaceSelect = document.getElementById('discovery-review-workspace');
8219
+ const projectSelect = document.getElementById('discovery-review-project');
8220
+ const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect
8221
+ ? String(workspaceSelect.value || '').trim()
8222
+ : '';
8223
+ const projectId = reviewScopeMode === 'workspace' && projectSelect
8224
+ ? String(projectSelect.value || '').trim()
8225
+ : '';
8226
+ if (item) {
8227
+ setDiscoveryReviewButtons({
8228
+ primaryLabel: getReviewPrimaryLabel(item, reviewScopeMode),
8229
+ primaryEnabled: item.inboxGroup !== 'ignored' && !(reviewScopeMode === 'workspace' && (!workspaceId || !projectId)),
8230
+ deferEnabled: canReviewDefer(item),
8231
+ ignoreEnabled: canReviewIgnore(item),
8232
+ });
8233
+ }
8234
+ return reviewScopeMode;
8235
+ }
8236
+
8237
+ async function loadDiscoveryReviewProjects(workspaceId, selectedProjectId, scopeMode) {
7999
8238
  const projectSelect = document.getElementById('discovery-review-project');
8000
8239
  const primaryButton = document.getElementById('discovery-review-primary');
8001
8240
  if (!projectSelect) return;
8002
8241
  if (!workspaceId) {
8003
- setScopeOptions(projectSelect, [{ id: '', label: governedMode ? 'Choose workspace first' : 'Account scope / no project' }], '');
8004
- if (primaryButton) primaryButton.disabled = governedMode;
8242
+ if (scopeMode === 'workspace') {
8243
+ setScopeOptions(projectSelect, [{ id: '', label: 'Choose a workspace first' }], '');
8244
+ if (primaryButton) primaryButton.disabled = true;
8245
+ } else {
8246
+ setScopeOptions(projectSelect, [{ id: '', label: 'Solo registration / no project' }], '');
8247
+ if (primaryButton) primaryButton.disabled = false;
8248
+ }
8005
8249
  return;
8006
8250
  }
8007
8251
  setScopeOptions(projectSelect, [{ id: '', label: 'Loading projects...' }], '');
@@ -8042,6 +8286,7 @@ function renderLauncherHtml(launcherToken) {
8042
8286
  setText('discovery-review-meta', 'Choose a model, agent, or runtime to review it here.');
8043
8287
  setText('discovery-review-detail', 'Registering creates or updates a Forkit Passport. Nothing is published automatically.');
8044
8288
  if (scopeWrap) scopeWrap.hidden = true;
8289
+ setReviewRegistrationMode('discovery-review', 'solo');
8045
8290
  setDiscoveryReviewStatus('Select an item to continue.', '');
8046
8291
  resetReviewResolutionActions('discovery-review');
8047
8292
  setDiscoveryReviewButtons({ primaryLabel: 'Review', primaryEnabled: false, deferEnabled: false, ignoreEnabled: false });
@@ -8049,8 +8294,7 @@ function renderLauncherHtml(launcherToken) {
8049
8294
  }
8050
8295
 
8051
8296
  const typeLabel = item.typeLabel || item.kind;
8052
- const needsScope = canReviewRegister(item);
8053
- const primaryLabel = getReviewPrimaryLabel(item);
8297
+ const showScopeChoice = canChooseReviewScope(item);
8054
8298
 
8055
8299
  setText('discovery-review-kicker', typeLabel);
8056
8300
  setText('discovery-review-title', item.name);
@@ -8059,14 +8303,15 @@ function renderLauncherHtml(launcherToken) {
8059
8303
  setDiscoveryReviewStatus(item.statusLabel + (item.statusMeta ? ' · ' + item.statusMeta : ''), item.statusTone === 'muted' ? '' : item.statusTone);
8060
8304
  resetReviewResolutionActions('discovery-review');
8061
8305
  setDiscoveryReviewButtons({
8062
- primaryLabel: getReviewPrimaryLabel(item),
8306
+ primaryLabel: getReviewPrimaryLabel(item, 'solo'),
8063
8307
  primaryEnabled: item.inboxGroup !== 'ignored',
8064
8308
  deferEnabled: canReviewDefer(item),
8065
8309
  ignoreEnabled: canReviewIgnore(item),
8066
8310
  });
8067
8311
 
8068
- if (!needsScope) {
8312
+ if (!showScopeChoice) {
8069
8313
  if (scopeWrap) scopeWrap.hidden = true;
8314
+ setReviewRegistrationMode('discovery-review', 'solo');
8070
8315
  reviewScopeCacheKey = null;
8071
8316
  return;
8072
8317
  }
@@ -8075,6 +8320,10 @@ function renderLauncherHtml(launcherToken) {
8075
8320
  if (!workspaceSelect || !projectSelect) return;
8076
8321
 
8077
8322
  const cacheKey = item.id + ':' + String(item.workspaceId || '') + ':' + String(item.projectId || '');
8323
+ syncDiscoveryReviewRegistrationMode(
8324
+ item,
8325
+ reviewScopeCacheKey === cacheKey ? getReviewRegistrationMode('discovery-review') : 'solo',
8326
+ );
8078
8327
  if (reviewScopeCacheKey === cacheKey) {
8079
8328
  return;
8080
8329
  }
@@ -8088,43 +8337,47 @@ function renderLauncherHtml(launcherToken) {
8088
8337
  const response = await apiFetch('/api/scope/access');
8089
8338
  const payload = await response.json();
8090
8339
  scopeAccessSnapshot = payload;
8091
- const governedMode = payload && payload.operatingMode === 'governed';
8092
8340
  const workspaces = payload.ok && Array.isArray(payload.workspaces) ? payload.workspaces : [];
8093
8341
  const options = [
8094
- ...(governedMode ? [] : [{ id: '', label: 'Account scope / no workspace' }]),
8342
+ { id: '', label: 'Register solo / account scope' },
8095
8343
  ...workspaces.map((workspace) => ({ id: workspace.id, label: workspace.name || workspace.id })),
8096
8344
  ];
8097
- if (governedMode && !options.length) {
8098
- options.push({ id: '', label: 'No governed workspaces yet' });
8099
- }
8100
- const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || (options[0] && options[0].id) || '';
8345
+ const selectedWorkspace = item.workspaceId || payload.currentWorkspaceId || '';
8346
+ const selectedProject = item.projectId || payload.currentProjectId || '';
8101
8347
  setScopeOptions(workspaceSelect, options, selectedWorkspace);
8102
- await loadDiscoveryReviewProjects(selectedWorkspace, item.projectId || payload.currentProjectId || '', governedMode);
8348
+ await loadDiscoveryReviewProjects(selectedWorkspace, selectedProject, getReviewRegistrationMode('discovery-review'));
8349
+ const reviewScopeMode = syncDiscoveryReviewRegistrationMode(item, getReviewRegistrationMode('discovery-review'));
8103
8350
  setDiscoveryReviewStatus(
8104
8351
  payload.ok
8105
- ? (governedMode
8106
- ? 'Choose the governed workspace and project for this registration.'
8107
- : 'Account scope stays available. Choose governed scope only when needed.')
8108
- : (payload.message || 'Workspace access is unavailable right now.'),
8352
+ ? (reviewScopeMode === 'workspace'
8353
+ ? (selectedWorkspace
8354
+ ? 'Choose the governed workspace and project for this registration.'
8355
+ : workspaces.length
8356
+ ? 'Choose a workspace and project for governed registration.'
8357
+ : 'No governed workspaces are available yet. Switch back to solo or create one first.')
8358
+ : 'Solo registration is ready. Choose governed workspace only when needed.')
8359
+ : (reviewScopeMode === 'workspace'
8360
+ ? (payload.message || 'Workspace access is unavailable right now. Switch to solo registration or retry later.')
8361
+ : 'Solo registration is still available. Governed workspace access is unavailable right now.'),
8109
8362
  payload.ok ? '' : 'warn',
8110
8363
  );
8111
8364
  } catch {
8112
8365
  setScopeOptions(workspaceSelect, [{ id: '', label: 'Workspace list unavailable' }], '');
8113
8366
  setScopeOptions(projectSelect, [{ id: '', label: 'Project list unavailable' }], '');
8114
- setDiscoveryReviewStatus('Workspace access is unavailable right now.', 'warn');
8115
- setDiscoveryReviewButtons({
8116
- primaryLabel,
8117
- primaryEnabled: false,
8118
- deferEnabled: canReviewDefer(item),
8119
- ignoreEnabled: canReviewIgnore(item),
8120
- });
8367
+ const reviewScopeMode = syncDiscoveryReviewRegistrationMode(item, getReviewRegistrationMode('discovery-review'));
8368
+ setDiscoveryReviewStatus(
8369
+ reviewScopeMode === 'workspace'
8370
+ ? 'Workspace access is unavailable right now. Switch to solo registration or retry later.'
8371
+ : 'Solo registration is still available. Governed workspace access is unavailable right now.',
8372
+ 'warn',
8373
+ );
8121
8374
  }
8122
8375
  }
8123
8376
 
8124
8377
  async function submitDiscoveryReviewPrimary() {
8125
8378
  const item = getSelectedDiscoveryItem();
8126
8379
  if (!item) return;
8127
- if (item.kind === 'runtime' || item.actionLabel === 'Open' || item.actionLabel === 'Review') {
8380
+ if (shouldOpenReviewContext(item)) {
8128
8381
  await openDiscoveryContext(item);
8129
8382
  return;
8130
8383
  }
@@ -8135,9 +8388,10 @@ function renderLauncherHtml(launcherToken) {
8135
8388
  const workspaceSelect = document.getElementById('discovery-review-workspace');
8136
8389
  const projectSelect = document.getElementById('discovery-review-project');
8137
8390
  const primaryButton = document.getElementById('discovery-review-primary');
8138
- const workspaceId = workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
8139
- const projectId = projectSelect ? String(projectSelect.value || '').trim() : '';
8140
- if (workspaceId && !projectId) {
8391
+ const reviewScopeMode = getReviewRegistrationMode('discovery-review');
8392
+ const workspaceId = reviewScopeMode === 'workspace' && workspaceSelect ? String(workspaceSelect.value || '').trim() : '';
8393
+ const projectId = reviewScopeMode === 'workspace' && projectSelect ? String(projectSelect.value || '').trim() : '';
8394
+ if (reviewScopeMode === 'workspace' && (!workspaceId || !projectId)) {
8141
8395
  setDiscoveryReviewStatus('Select a project for the chosen workspace, or switch back to account scope.', 'warn');
8142
8396
  return;
8143
8397
  }
@@ -9091,7 +9345,7 @@ function renderLauncherHtml(launcherToken) {
9091
9345
  registerButton.disabled = true;
9092
9346
  setText('scope-modal-title', 'Register ' + item.name);
9093
9347
  let governedMode = latestSummary && latestSummary.operatingMode === 'governed';
9094
- setText('scope-modal-copy', 'Checking account scope and available governed workspaces...');
9348
+ setText('scope-modal-copy', 'Checking account scope and any governed workspace options...');
9095
9349
  if (createWorkspaceButton) createWorkspaceButton.hidden = true;
9096
9350
  if (createProjectButton) createProjectButton.hidden = true;
9097
9351
  setScopeCreateButtonsEnabled(false);
@@ -9106,40 +9360,38 @@ function renderLauncherHtml(launcherToken) {
9106
9360
  setText(
9107
9361
  'scope-modal-copy',
9108
9362
  governedMode
9109
- ? 'Select the governed workspace and project that should own this Passport. You can create missing scope here.'
9110
- : 'Account scope remains available on Origin. Choose a governed workspace/project only when you want governed operations.',
9363
+ ? 'Register on your account now, or choose a governed workspace/project when you want governed ownership. You can create missing scope here.'
9364
+ : 'Solo registration is available now. Choose a governed workspace/project only when you want governed operations.',
9111
9365
  );
9112
9366
  if (createWorkspaceButton) createWorkspaceButton.hidden = !governedMode;
9113
9367
  if (createProjectButton) createProjectButton.hidden = !governedMode;
9114
9368
  setScopeCreateButtonsEnabled(governedMode);
9115
9369
  const workspaces = payload.ok && Array.isArray(payload.workspaces) ? payload.workspaces : [];
9116
9370
  const options = [
9117
- ...(governedMode ? [] : [{ id: '', label: 'Account scope / no workspace' }]),
9371
+ { id: '', label: 'Register solo / account scope' },
9118
9372
  ...workspaces.map((workspace) => ({ id: workspace.id, label: workspace.name || workspace.id })),
9119
9373
  ];
9120
- if (governedMode && !options.length) {
9121
- options.push({ id: '', label: 'No governed workspaces yet' });
9122
- registerButton.disabled = true;
9374
+ if (governedMode && workspaces.length === 0) {
9123
9375
  openScopeCreateWorkspaceFlow('No governed workspace exists yet. Create one here to continue.', 'warn');
9124
9376
  }
9125
- const selectedWorkspace = payload.currentWorkspaceId || (options[0] && options[0].id) || '';
9377
+ const selectedWorkspace = item.workspaceId || '';
9126
9378
  setScopeOptions(workspaceSelect, options, selectedWorkspace);
9127
9379
  const hasProjects = await loadScopeProjects(workspaceSelect.value, payload.currentProjectId || '');
9128
- registerButton.disabled = !payload.ok || (governedMode && (!String(workspaceSelect.value || '').trim() || !hasProjects));
9129
- if (payload.ok && (!governedMode || hasProjects)) {
9130
- setScopeStatus(governedMode ? 'Ready to register in governed scope.' : 'Ready to register.', '');
9380
+ registerButton.disabled = !payload.ok || (Boolean(String(workspaceSelect.value || '').trim()) && !hasProjects);
9381
+ if (payload.ok && (!String(workspaceSelect.value || '').trim() || hasProjects)) {
9382
+ setScopeStatus(String(workspaceSelect.value || '').trim() ? 'Ready to register in governed scope.' : 'Ready to register solo.', '');
9131
9383
  } else if (!payload.ok) {
9132
9384
  setScopeStatus(
9133
- payload.message || (governedMode ? 'Workspace list unavailable.' : 'Workspace list unavailable. Account scope is still available.'),
9385
+ payload.message || 'Workspace list unavailable. Solo registration is still available.',
9134
9386
  'warn',
9135
9387
  );
9136
9388
  }
9137
9389
  } catch {
9138
- setScopeOptions(workspaceSelect, governedMode ? [] : [{ id: '', label: 'Account scope / no workspace' }], '');
9139
- await loadScopeProjects(governedMode ? (workspaceSelect.value || '') : '', '');
9140
- registerButton.disabled = true;
9390
+ setScopeOptions(workspaceSelect, [{ id: '', label: 'Register solo / account scope' }], '');
9391
+ await loadScopeProjects('', '');
9392
+ registerButton.disabled = false;
9141
9393
  setScopeCreateButtonsEnabled(false);
9142
- setScopeStatus(governedMode ? 'Workspace list unavailable.' : 'Workspace list unavailable. Account scope is still available.', 'warn');
9394
+ setScopeStatus('Workspace list unavailable. Solo registration is still available.', 'warn');
9143
9395
  }
9144
9396
  }
9145
9397
 
@@ -9165,7 +9417,7 @@ function renderLauncherHtml(launcherToken) {
9165
9417
  }
9166
9418
  if (registerButton) registerButton.disabled = true;
9167
9419
  const endpoint = item.kind === 'agent' ? '/api/discovery/connect-agent' : '/api/discovery/connect-model';
9168
- const pendingMessage = item.kind === 'agent' ? 'Registering agent...' : 'Creating Passport draft...';
9420
+ const pendingMessage = item.kind === 'agent' ? 'Registering agent...' : 'Registering model...';
9169
9421
  setScopeStatus('Registering with Forkit Connect...', 'warn');
9170
9422
  const result = await postAction(endpoint, pendingMessage, {
9171
9423
  method: 'POST',
@@ -10073,34 +10325,62 @@ function renderLauncherHtml(launcherToken) {
10073
10325
  void submitQuickReviewIgnore();
10074
10326
  });
10075
10327
  }
10328
+ const quickReviewModeSolo = document.getElementById('quick-review-mode-solo');
10329
+ if (quickReviewModeSolo) {
10330
+ quickReviewModeSolo.addEventListener('click', () => {
10331
+ const item = getQuickReviewItem();
10332
+ if (!item || !canChooseReviewScope(item)) return;
10333
+ syncQuickReviewRegistrationMode(item, 'solo');
10334
+ setQuickReviewStatus('Solo registration is ready. Choose governed workspace only when needed.', '');
10335
+ });
10336
+ }
10337
+ const quickReviewModeWorkspace = document.getElementById('quick-review-mode-workspace');
10338
+ if (quickReviewModeWorkspace) {
10339
+ quickReviewModeWorkspace.addEventListener('click', () => {
10340
+ const item = getQuickReviewItem();
10341
+ if (!item || !canChooseReviewScope(item)) return;
10342
+ syncQuickReviewRegistrationMode(item, 'workspace');
10343
+ const selectedWorkspaceId = quickReviewWorkspaceSelect
10344
+ ? String(quickReviewWorkspaceSelect.value || '').trim()
10345
+ : '';
10346
+ const selectedProjectId = quickReviewProjectSelect
10347
+ ? String(quickReviewProjectSelect.value || '').trim()
10348
+ : '';
10349
+ void loadQuickReviewProjects(selectedWorkspaceId, selectedProjectId, 'workspace');
10350
+ setQuickReviewStatus(
10351
+ selectedWorkspaceId
10352
+ ? 'Choose the governed project for this registration.'
10353
+ : 'Choose a workspace and project for governed registration.',
10354
+ '',
10355
+ );
10356
+ });
10357
+ }
10076
10358
  const quickReviewWorkspaceSelect = document.getElementById('quick-review-workspace');
10077
10359
  if (quickReviewWorkspaceSelect) {
10078
10360
  quickReviewWorkspaceSelect.addEventListener('change', () => {
10361
+ const item = getQuickReviewItem();
10079
10362
  const selectedWorkspaceId = String(quickReviewWorkspaceSelect.value || '').trim();
10080
- const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
10081
- quickReviewScopeCacheKey = null;
10082
- void loadQuickReviewProjects(selectedWorkspaceId, '', governedMode);
10083
- updateQuickReviewScopeSummary(governedMode);
10363
+ const reviewScopeMode = getReviewRegistrationMode('quick-review');
10364
+ void loadQuickReviewProjects(selectedWorkspaceId, '', reviewScopeMode);
10084
10365
  setQuickReviewStatus(
10085
- selectedWorkspaceId
10086
- ? 'Choose the governed project for this registration.'
10087
- : 'Account scope stays available. Choose governed scope only when needed.',
10366
+ reviewScopeMode === 'workspace'
10367
+ ? (selectedWorkspaceId
10368
+ ? 'Choose the governed project for this registration.'
10369
+ : 'Choose a workspace and project for governed registration.')
10370
+ : 'Solo registration stays available. Choose governed scope only when needed.',
10088
10371
  '',
10089
10372
  );
10373
+ if (item) {
10374
+ syncQuickReviewRegistrationMode(item, reviewScopeMode);
10375
+ }
10090
10376
  });
10091
10377
  }
10092
10378
  const quickReviewProjectSelect = document.getElementById('quick-review-project');
10093
10379
  if (quickReviewProjectSelect) {
10094
10380
  quickReviewProjectSelect.addEventListener('change', () => {
10095
- const primaryButton = document.getElementById('quick-review-primary');
10096
- const selectedWorkspaceId = quickReviewWorkspaceSelect
10097
- ? String(quickReviewWorkspaceSelect.value || '').trim()
10098
- : '';
10099
- const selectedProjectId = String(quickReviewProjectSelect.value || '').trim();
10100
- const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
10101
- updateQuickReviewScopeSummary(governedMode);
10102
- if (primaryButton) {
10103
- primaryButton.disabled = Boolean(selectedWorkspaceId && !selectedProjectId && governedMode);
10381
+ const item = getQuickReviewItem();
10382
+ if (item) {
10383
+ syncQuickReviewRegistrationMode(item, getReviewRegistrationMode('quick-review'));
10104
10384
  }
10105
10385
  });
10106
10386
  }
@@ -10134,20 +10414,53 @@ function renderLauncherHtml(launcherToken) {
10134
10414
  void submitDiscoveryReviewIgnore();
10135
10415
  });
10136
10416
  }
10417
+ const discoveryReviewModeSolo = document.getElementById('discovery-review-mode-solo');
10418
+ if (discoveryReviewModeSolo) {
10419
+ discoveryReviewModeSolo.addEventListener('click', () => {
10420
+ const selectedItem = getSelectedDiscoveryItem();
10421
+ if (!selectedItem || !canChooseReviewScope(selectedItem)) return;
10422
+ syncDiscoveryReviewRegistrationMode(selectedItem, 'solo');
10423
+ setDiscoveryReviewStatus('Solo registration is ready. Choose governed workspace only when needed.', '');
10424
+ });
10425
+ }
10426
+ const discoveryReviewModeWorkspace = document.getElementById('discovery-review-mode-workspace');
10427
+ if (discoveryReviewModeWorkspace) {
10428
+ discoveryReviewModeWorkspace.addEventListener('click', () => {
10429
+ const selectedItem = getSelectedDiscoveryItem();
10430
+ if (!selectedItem || !canChooseReviewScope(selectedItem)) return;
10431
+ syncDiscoveryReviewRegistrationMode(selectedItem, 'workspace');
10432
+ const selectedWorkspaceId = discoveryReviewWorkspaceSelect
10433
+ ? String(discoveryReviewWorkspaceSelect.value || '').trim()
10434
+ : '';
10435
+ const selectedProjectId = discoveryReviewProjectSelect
10436
+ ? String(discoveryReviewProjectSelect.value || '').trim()
10437
+ : '';
10438
+ void loadDiscoveryReviewProjects(selectedWorkspaceId, selectedProjectId, 'workspace');
10439
+ setDiscoveryReviewStatus(
10440
+ selectedWorkspaceId
10441
+ ? 'Choose the governed project for this registration.'
10442
+ : 'Choose a workspace and project for governed registration.',
10443
+ '',
10444
+ );
10445
+ });
10446
+ }
10137
10447
  const discoveryReviewWorkspaceSelect = document.getElementById('discovery-review-workspace');
10138
10448
  if (discoveryReviewWorkspaceSelect) {
10139
10449
  discoveryReviewWorkspaceSelect.addEventListener('change', () => {
10140
10450
  const selectedItem = getSelectedDiscoveryItem();
10141
10451
  const selectedWorkspaceId = String(discoveryReviewWorkspaceSelect.value || '').trim();
10142
- const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
10143
- void loadDiscoveryReviewProjects(selectedWorkspaceId, '', governedMode);
10452
+ const reviewScopeMode = getReviewRegistrationMode('discovery-review');
10453
+ void loadDiscoveryReviewProjects(selectedWorkspaceId, '', reviewScopeMode);
10144
10454
  if (selectedItem && canReviewRegister(selectedItem)) {
10145
10455
  setDiscoveryReviewStatus(
10146
- selectedWorkspaceId
10147
- ? 'Choose the governed project for this registration.'
10148
- : 'Account scope stays available. Choose governed scope only when needed.',
10456
+ reviewScopeMode === 'workspace'
10457
+ ? (selectedWorkspaceId
10458
+ ? 'Choose the governed project for this registration.'
10459
+ : 'Choose a workspace and project for governed registration.')
10460
+ : 'Solo registration stays available. Choose governed scope only when needed.',
10149
10461
  '',
10150
10462
  );
10463
+ syncDiscoveryReviewRegistrationMode(selectedItem, reviewScopeMode);
10151
10464
  }
10152
10465
  });
10153
10466
  }
@@ -10155,14 +10468,8 @@ function renderLauncherHtml(launcherToken) {
10155
10468
  if (discoveryReviewProjectSelect) {
10156
10469
  discoveryReviewProjectSelect.addEventListener('change', () => {
10157
10470
  const selectedItem = getSelectedDiscoveryItem();
10158
- const primaryButton = document.getElementById('discovery-review-primary');
10159
- const selectedWorkspaceId = discoveryReviewWorkspaceSelect
10160
- ? String(discoveryReviewWorkspaceSelect.value || '').trim()
10161
- : '';
10162
- const selectedProjectId = String(discoveryReviewProjectSelect.value || '').trim();
10163
- const governedMode = scopeAccessSnapshot && scopeAccessSnapshot.operatingMode === 'governed';
10164
- if (primaryButton && selectedItem && canReviewRegister(selectedItem)) {
10165
- primaryButton.disabled = Boolean(selectedWorkspaceId && !selectedProjectId && governedMode);
10471
+ if (selectedItem && canReviewRegister(selectedItem)) {
10472
+ syncDiscoveryReviewRegistrationMode(selectedItem, getReviewRegistrationMode('discovery-review'));
10166
10473
  }
10167
10474
  });
10168
10475
  }
@@ -10806,16 +11113,19 @@ function createLauncherApp(options) {
10806
11113
  else {
10807
11114
  await options.service.bindWorkspaceProject(null, null);
10808
11115
  }
10809
- const result = await options.service.connectDetectedModel(selector);
11116
+ const result = await options.service.connectDetectedModel(selector, {
11117
+ destination: 'passport',
11118
+ visibility: 'public',
11119
+ });
10810
11120
  const message = result.action === 'already_bound'
10811
11121
  ? 'Model is already connected to a Passport.'
10812
11122
  : result.action === 'already_pending'
10813
- ? 'Model already has a pending Passport draft.'
11123
+ ? 'Registration is already in progress for this model.'
10814
11124
  : result.action === 'passport_registered'
10815
- ? 'Passport registered from detected model.'
11125
+ ? 'Passport registered successfully.'
10816
11126
  : result.action === 'draft_created'
10817
- ? 'Passport draft created from detected model.'
10818
- : 'Passport draft queued locally from detected model.';
11127
+ ? 'Registration started privately for review before publishing.'
11128
+ : 'Registration was saved locally and will continue when Forkit Connect can sync again.';
10819
11129
  response.json({
10820
11130
  ok: true,
10821
11131
  message,
@@ -10885,7 +11195,7 @@ function createLauncherApp(options) {
10885
11195
  : passportGaid
10886
11196
  ? 'Agent is already registered.'
10887
11197
  : draftId
10888
- ? 'Agent registration draft created.'
11198
+ ? 'Agent registration started privately for review.'
10889
11199
  : 'Agent connected locally. Registration is still available.';
10890
11200
  response.json({
10891
11201
  ok: true,
@@ -742,6 +742,7 @@ export declare class ConnectV1Service {
742
742
  connectDetectedModel(selector: string, options?: {
743
743
  visibility?: 'private' | 'public';
744
744
  destination?: 'draft' | 'passport';
745
+ allowPrivateFallback?: boolean;
745
746
  }): Promise<ConnectSelectionResult>;
746
747
  private resolveRuntimePassportSelection;
747
748
  connectRuntimeSuggestion(selector: string): Promise<ConnectSelectionResult>;
@@ -7834,10 +7834,13 @@ class ConnectV1Service {
7834
7834
  const soloDraftAllowed = draftBindingStatus.allowed && draftBindingStatus.reasonCode === 'solo_passport_draft_allowed';
7835
7835
  const localScopedDraftAllowed = draftBindingStatus.allowed && draftBindingStatus.reasonCode === 'local_workspace_project_draft_allowed';
7836
7836
  const model = this.resolveModelSelection(selector, state);
7837
- const requestedDestination = options?.destination === 'passport' ? 'passport' : 'draft';
7838
- const requestedVisibility = options?.visibility === 'public' && requestedDestination === 'passport'
7839
- ? 'public'
7840
- : 'private';
7837
+ const requestedDestination = options?.destination === 'draft' ? 'draft' : 'passport';
7838
+ const requestedVisibility = options?.visibility === 'private'
7839
+ ? 'private'
7840
+ : requestedDestination === 'passport'
7841
+ ? 'public'
7842
+ : 'private';
7843
+ const allowPrivateFallback = options?.allowPrivateFallback !== false;
7841
7844
  this.clearModelReviewDeferral(model);
7842
7845
  this.updateDetectedModelRegistrationHint(model, {
7843
7846
  trackingStatus: null,
@@ -7992,10 +7995,17 @@ class ConnectV1Service {
7992
7995
  this.updateDetectedModelRegistrationHint(model, {
7993
7996
  trackingStatus: 'private_draft_required',
7994
7997
  errorCode: backendCode,
7995
- errorMessage: 'This registration must start as a private draft before it can be published.',
7998
+ errorMessage: 'Forkit needs one private review step before this passport can finish publishing.',
7996
7999
  errorStatus: result.status,
7997
- guidance: 'Open the review flow and continue through the private draft path first.',
8000
+ guidance: 'Forkit is continuing this registration privately first. Finish the review step there before publishing.',
7998
8001
  });
8002
+ if (allowPrivateFallback && requestedDestination === 'passport' && requestedVisibility === 'public') {
8003
+ return this.connectDetectedModel(selector, {
8004
+ destination: 'draft',
8005
+ visibility: 'private',
8006
+ allowPrivateFallback: false,
8007
+ });
8008
+ }
7999
8009
  }
8000
8010
  this.observeBackendCommunicationState({
8001
8011
  passportGaid: bindingWithRuntime?.gaid ?? null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forkit-connect",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Forkit Connect Local Engine - The Global AI Governance Fabric",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",