@useorgx/wizard 0.1.46 → 0.1.48

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
@@ -508,6 +508,31 @@ async function clearWizardAuth(authPath = ORGX_WIZARD_AUTH_PATH, options = {}) {
508
508
  return secretRemoved || fileRemoved;
509
509
  }
510
510
 
511
+ // src/lib/network.ts
512
+ var DEFAULT_REQUEST_TIMEOUT_MS = 12e3;
513
+ function isTimeoutError(error) {
514
+ if (!(error instanceof Error)) return false;
515
+ if (error.name === "TimeoutError" || error.name === "AbortError") return true;
516
+ const message = error.message.toLowerCase();
517
+ return message.includes("aborted due to timeout") || message.includes("operation was aborted");
518
+ }
519
+ async function fetchWithRetry(url, init, options = {}) {
520
+ const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
521
+ const retries = options.retries ?? 1;
522
+ let lastError;
523
+ for (let attempt = 0; attempt <= retries; attempt++) {
524
+ try {
525
+ return await fetch(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });
526
+ } catch (error) {
527
+ lastError = error;
528
+ if (!isTimeoutError(error) || attempt === retries) {
529
+ throw error;
530
+ }
531
+ }
532
+ }
533
+ throw lastError;
534
+ }
535
+
511
536
  // src/lib/auth.ts
512
537
  function normalizeHost(value) {
513
538
  return value.trim().toLowerCase().replace(/^\[|\]$/g, "");
@@ -652,14 +677,13 @@ async function parseResponseBody(response) {
652
677
  async function verifyOrgxAuth(auth) {
653
678
  const url = buildOrgxApiUrl("/client/sync", auth.baseUrl);
654
679
  try {
655
- const response = await fetch(url, {
680
+ const response = await fetchWithRetry(url, {
656
681
  method: "POST",
657
682
  headers: {
658
683
  Authorization: `Bearer ${auth.apiKey}`,
659
684
  "Content-Type": "application/json"
660
685
  },
661
- body: "{}",
662
- signal: AbortSignal.timeout(7e3)
686
+ body: "{}"
663
687
  });
664
688
  const data = await parseResponseBody(response);
665
689
  return {
@@ -1177,30 +1201,6 @@ function parseContinuityDefaults(value) {
1177
1201
  }
1178
1202
  return Object.keys(parsed).length > 0 ? parsed : void 0;
1179
1203
  }
1180
- function parseDemoInitiative(value) {
1181
- if (!value || typeof value !== "object" || Array.isArray(value)) {
1182
- return void 0;
1183
- }
1184
- const record = value;
1185
- if (!isNonEmptyString2(record.id) || !isNonEmptyString2(record.title) || !isNonEmptyString2(record.liveUrl) || !isNonEmptyString2(record.createdAt)) {
1186
- return void 0;
1187
- }
1188
- return {
1189
- createdAt: record.createdAt.trim(),
1190
- ...isNonEmptyString2(record.artifactId) ? { artifactId: record.artifactId.trim() } : {},
1191
- ...isNonEmptyString2(record.artifactName) ? { artifactName: record.artifactName.trim() } : {},
1192
- ...isNonEmptyString2(record.artifactType) ? { artifactType: record.artifactType.trim() } : {},
1193
- ...isNonEmptyString2(record.artifactUrl) ? { artifactUrl: record.artifactUrl.trim() } : {},
1194
- ...isNonEmptyString2(record.decisionId) ? { decisionId: record.decisionId.trim() } : {},
1195
- ...isNonEmptyString2(record.decisionStatus) ? { decisionStatus: record.decisionStatus.trim() } : {},
1196
- ...isNonEmptyString2(record.decisionTitle) ? { decisionTitle: record.decisionTitle.trim() } : {},
1197
- id: record.id.trim(),
1198
- liveUrl: record.liveUrl.trim(),
1199
- title: record.title.trim(),
1200
- ...isNonEmptyString2(record.workspaceId) ? { workspaceId: record.workspaceId.trim() } : {},
1201
- ...isNonEmptyString2(record.workspaceName) ? { workspaceName: record.workspaceName.trim() } : {}
1202
- };
1203
- }
1204
1204
  function parseFirstValueInitiative(value) {
1205
1205
  if (!value || typeof value !== "object" || Array.isArray(value)) {
1206
1206
  return void 0;
@@ -1421,7 +1421,6 @@ function createWizardState(now = (/* @__PURE__ */ new Date()).toISOString()) {
1421
1421
  function sanitizeWizardStateRecord(record) {
1422
1422
  const continuity = parseContinuityDefaults(record.continuity);
1423
1423
  const agentRoster = parseAgentRoster(record.agentRoster);
1424
- const demoInitiative = parseDemoInitiative(record.demoInitiative);
1425
1424
  const firstValueInitiative = parseFirstValueInitiative(record.firstValueInitiative);
1426
1425
  const onboardingTask = parseOnboardingTask(record.onboardingTask);
1427
1426
  const skillFiles = parseSkillFiles(record.skillFiles);
@@ -1434,7 +1433,6 @@ function sanitizeWizardStateRecord(record) {
1434
1433
  updatedAt: record.updatedAt.trim(),
1435
1434
  ...continuity ? { continuity } : {},
1436
1435
  ...agentRoster ? { agentRoster } : {},
1437
- ...demoInitiative ? { demoInitiative } : {},
1438
1436
  ...firstValueInitiative ? { firstValueInitiative } : {},
1439
1437
  ...onboardingTask ? { onboardingTask } : {},
1440
1438
  ...skillFiles ? { skillFiles } : {},
@@ -1457,8 +1455,6 @@ function readWizardState(statePath = ORGX_WIZARD_STATE_PATH) {
1457
1455
  if (continuity !== void 0) state.continuity = continuity;
1458
1456
  const agentRoster = parseAgentRoster(parsed.agentRoster);
1459
1457
  if (agentRoster !== void 0) state.agentRoster = agentRoster;
1460
- const demoInitiative = parseDemoInitiative(parsed.demoInitiative);
1461
- if (demoInitiative !== void 0) state.demoInitiative = demoInitiative;
1462
1458
  const firstValueInitiative = parseFirstValueInitiative(parsed.firstValueInitiative);
1463
1459
  if (firstValueInitiative !== void 0) {
1464
1460
  state.firstValueInitiative = firstValueInitiative;
@@ -1949,12 +1945,11 @@ function formatHttpError(status, body) {
1949
1945
  async function listWorkspaces(options = {}) {
1950
1946
  const auth = await requireOrgxAuth(options);
1951
1947
  const url = buildOrgxApiUrl("/entities?type=workspace&limit=100", auth.baseUrl);
1952
- const response = await fetch(url, {
1948
+ const response = await fetchWithRetry(url, {
1953
1949
  method: "GET",
1954
1950
  headers: {
1955
1951
  Authorization: `Bearer ${auth.apiKey}`
1956
- },
1957
- signal: AbortSignal.timeout(7e3)
1952
+ }
1958
1953
  });
1959
1954
  const body = await parseResponseBody2(response);
1960
1955
  if (!response.ok) {
@@ -1965,12 +1960,11 @@ async function listWorkspaces(options = {}) {
1965
1960
  async function getCurrentWorkspace(options = {}) {
1966
1961
  const auth = await requireOrgxAuth(options);
1967
1962
  const url = buildOrgxApiUrl("/v1/workspaces/current", auth.baseUrl);
1968
- const response = await fetch(url, {
1963
+ const response = await fetchWithRetry(url, {
1969
1964
  method: "GET",
1970
1965
  headers: {
1971
1966
  Authorization: `Bearer ${auth.apiKey}`
1972
- },
1973
- signal: AbortSignal.timeout(7e3)
1967
+ }
1974
1968
  });
1975
1969
  const body = await parseResponseBody2(response);
1976
1970
  if (response.ok) {
@@ -3169,6 +3163,9 @@ var CODEX_PLUGIN_SYNC_SPEC = {
3169
3163
  { localPath: ".codex-plugin", remotePath: ".codex-plugin" },
3170
3164
  { localPath: ".mcp.json", remotePath: ".mcp.json" },
3171
3165
  { localPath: "assets", remotePath: "assets" },
3166
+ // Deliver the runtime hooks (Work Graph reconcile + execution-graph emit)
3167
+ // so the WEG keystone actually installs for Codex, not just Cursor/Claude.
3168
+ { localPath: "hooks", remotePath: "hooks" },
3172
3169
  { localPath: "skills", remotePath: "skills" }
3173
3170
  ]
3174
3171
  };
@@ -4594,15 +4591,17 @@ function skippedOpenClawHealth() {
4594
4591
  details: []
4595
4592
  };
4596
4593
  }
4597
- async function runDoctor() {
4594
+ async function runDoctor(options = {}) {
4598
4595
  const surfaces = listSurfaceStatuses();
4599
4596
  const openclawSurface = surfaces.find((surface) => surface.name === "openclaw");
4600
- const auth = await checkOrgxAuth();
4601
- const hostedMcp = await checkHostedMcpHealth();
4602
- const hostedMcpTool = await checkHostedMcpToolAccess();
4603
- const npmRegistry = await checkNpmRegistryHealth();
4604
- const workspace = await checkWorkspaceConnectivity();
4605
- const openclaw = openclawSurface?.detected ? await checkOpenClawHealth(openclawSurface.path) : skippedOpenClawHealth();
4597
+ const [auth, hostedMcp, hostedMcpTool, npmRegistry, workspace, openclaw] = await Promise.all([
4598
+ checkOrgxAuth(),
4599
+ checkHostedMcpHealth(),
4600
+ checkHostedMcpToolAccess(),
4601
+ checkNpmRegistryHealth(),
4602
+ options.cachedWorkspace ? Promise.resolve(options.cachedWorkspace) : checkWorkspaceConnectivity(),
4603
+ openclawSurface?.detected ? checkOpenClawHealth(openclawSurface.path) : Promise.resolve(skippedOpenClawHealth())
4604
+ ]);
4606
4605
  return { surfaces, auth, hostedMcp, hostedMcpTool, npmRegistry, workspace, openclaw };
4607
4606
  }
4608
4607
  function assessDoctorReport(report) {
@@ -4745,513 +4744,114 @@ function persistContinuityDefaults(seed = {}, statePath) {
4745
4744
  );
4746
4745
  }
4747
4746
 
4748
- // src/lib/initiatives.ts
4749
- var FOUNDER_DEMO_INITIATIVE_TITLE = "Founder Demo Initiative";
4750
- var FOUNDER_DEMO_INITIATIVE_SUMMARY = "Starter initiative created by @useorgx/wizard to validate workspace routing, live views, and the default OrgX skill pack.";
4751
- var FOUNDER_DEMO_DECISION_TITLE = "Approve founder demo workspace";
4752
- var FOUNDER_DEMO_DECISION_SUMMARY = "Initial decision created by @useorgx/wizard so the founder preset leaves the workspace with a resolved approval trail.";
4753
- var FOUNDER_DEMO_DECISION_RESOLUTION = "Approved automatically by @useorgx/wizard after the founder preset finished creating the live demo workspace.";
4754
- var FOUNDER_DEMO_ARTIFACT_NAME = "Founder Demo Live View";
4755
- var FOUNDER_DEMO_ARTIFACT_TYPE = "document";
4756
- var FOUNDER_DEMO_ARTIFACT_DESCRIPTION = "Live founder demo generated by @useorgx/wizard after workspace bootstrap completed.";
4757
- var ONBOARDING_TASK_TITLE = "Complete OrgX onboarding";
4758
- var ONBOARDING_TASK_SUMMARY = "Starter onboarding task created by @useorgx/wizard so the first workspace has a clear follow-up after setup.";
4759
- var ONBOARDING_WORKSTREAM_TITLE = "OrgX onboarding";
4760
- var ONBOARDING_WORKSTREAM_SUMMARY = "Starter onboarding workstream created by @useorgx/wizard so the first workspace has a home for setup follow-up tasks.";
4761
- var FIRST_VALUE_INITIATIVE_TITLE = "Make OrgX useful on this machine";
4762
- var FIRST_VALUE_INITIATIVE_SUMMARY = "First initiative created by @useorgx/wizard so setup ends with a live workspace, an onboarding workstream, and a clean handoff into the user's configured AI tools.";
4763
- function parseResponseBody3(text2) {
4764
- if (!text2) {
4765
- return null;
4766
- }
4767
- try {
4768
- return JSON.parse(text2);
4769
- } catch {
4770
- return text2;
4771
- }
4772
- }
4773
- function formatHttpError2(status, body) {
4774
- if (typeof body === "string" && body.trim().length > 0) {
4775
- return `HTTP ${status}: ${body}`;
4776
- }
4777
- if (isRecord(body) && typeof body.error === "string" && body.error.trim().length > 0) {
4778
- return `HTTP ${status}: ${body.error}`;
4779
- }
4780
- return `HTTP ${status}`;
4781
- }
4782
- function extractEntity(payload) {
4783
- const entity = isRecord(payload) && isRecord(payload.data) ? payload.data : payload;
4784
- if (!isRecord(entity)) {
4785
- throw new Error("OrgX returned an unexpected entity payload.");
4786
- }
4787
- return entity;
4747
+ // src/lib/setup-workspace.ts
4748
+ var CREATE_WORKSPACE_VALUE = "__create_workspace__";
4749
+ var SKIP_WORKSPACE_VALUE = "__skip_workspace__";
4750
+ var REAUTH_WORKSPACE_VALUE = "__reauth_workspace__";
4751
+ function trimDescription(value) {
4752
+ const trimmed = value.trim();
4753
+ return trimmed.length > 0 ? trimmed : void 0;
4788
4754
  }
4789
- function parseInitiative(payload) {
4790
- const entity = extractEntity(payload);
4791
- const id = typeof entity.id === "string" ? entity.id.trim() : "";
4792
- const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
4793
- if (!id || !title) {
4794
- throw new Error("OrgX returned an incomplete initiative payload.");
4795
- }
4755
+ function cancelResult(prompts, message = "Workspace bootstrap cancelled.") {
4756
+ prompts.cancel(message);
4796
4757
  return {
4797
- id,
4798
- title,
4799
- ...typeof entity.summary === "string" && entity.summary.trim().length > 0 ? { summary: entity.summary.trim() } : {}
4758
+ message,
4759
+ status: "cancelled"
4800
4760
  };
4801
4761
  }
4802
- function parseDecision(payload) {
4803
- const entity = extractEntity(payload);
4804
- const id = typeof entity.id === "string" ? entity.id.trim() : "";
4805
- const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
4806
- if (!id || !title) {
4807
- throw new Error("OrgX returned an incomplete decision payload.");
4762
+ function buildWorkspaceLabel(workspace, currentWorkspaceId) {
4763
+ const suffixes = [];
4764
+ if (workspace.isDefault) {
4765
+ suffixes.push("default");
4808
4766
  }
4809
- return {
4810
- id,
4811
- title,
4812
- ...typeof entity.status === "string" && entity.status.trim().length > 0 ? { status: entity.status.trim() } : {},
4813
- ...typeof entity.summary === "string" && entity.summary.trim().length > 0 ? { summary: entity.summary.trim() } : {}
4814
- };
4815
- }
4816
- function parseArtifact(payload) {
4817
- const entity = extractEntity(payload);
4818
- const id = typeof entity.id === "string" ? entity.id.trim() : "";
4819
- const name = typeof entity.name === "string" ? entity.name.trim() : typeof entity.title === "string" ? entity.title.trim() : "";
4820
- const type = typeof entity.artifact_type === "string" ? entity.artifact_type.trim() : typeof entity.type === "string" ? entity.type.trim() : "";
4821
- const url = typeof entity.external_url === "string" ? entity.external_url.trim() : typeof entity.url === "string" ? entity.url.trim() : "";
4822
- if (!id || !name) {
4823
- throw new Error("OrgX returned an incomplete artifact payload.");
4767
+ if (workspace.id === currentWorkspaceId) {
4768
+ suffixes.push("current");
4824
4769
  }
4825
- return {
4826
- id,
4827
- name,
4828
- ...type ? { type } : {},
4829
- ...url ? { url } : {}
4830
- };
4831
- }
4832
- function parseTask(payload) {
4833
- const entity = extractEntity(payload);
4834
- const id = typeof entity.id === "string" ? entity.id.trim() : "";
4835
- const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
4836
- if (!id || !title) {
4837
- throw new Error("OrgX returned an incomplete task payload.");
4770
+ if (suffixes.length === 0) {
4771
+ return workspace.name;
4838
4772
  }
4839
- return {
4840
- id,
4841
- title,
4842
- ...typeof entity.status === "string" && entity.status.trim().length > 0 ? { status: entity.status.trim() } : {},
4843
- ...typeof entity.summary === "string" && entity.summary.trim().length > 0 ? { summary: entity.summary.trim() } : {}
4844
- };
4773
+ return `${workspace.name} (${suffixes.join(", ")})`;
4845
4774
  }
4846
- function parseWorkstream(payload) {
4847
- const entity = extractEntity(payload);
4848
- const id = typeof entity.id === "string" ? entity.id.trim() : "";
4849
- const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
4850
- if (!id || !title) {
4851
- throw new Error("OrgX returned an incomplete workstream payload.");
4852
- }
4853
- return { id, title };
4775
+ function buildWorkspaceSelectOptions(workspaces, currentWorkspaceId) {
4776
+ const options = workspaces.map((workspace) => ({
4777
+ value: workspace.id,
4778
+ label: buildWorkspaceLabel(workspace, currentWorkspaceId),
4779
+ ...workspace.description ? { hint: workspace.description } : {}
4780
+ }));
4781
+ options.push(
4782
+ {
4783
+ value: CREATE_WORKSPACE_VALUE,
4784
+ label: "Create a new workspace",
4785
+ hint: "Name it here and set it as the default for this machine."
4786
+ },
4787
+ {
4788
+ value: SKIP_WORKSPACE_VALUE,
4789
+ label: "Skip for now",
4790
+ hint: "Leave workspace selection unchanged and finish setup."
4791
+ }
4792
+ );
4793
+ return options;
4854
4794
  }
4855
- function toDemoInitiativeRecord(artifact, decision, initiative, liveUrl, workspace) {
4856
- return {
4857
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4858
- artifactId: artifact.id,
4859
- artifactName: artifact.name,
4860
- ...artifact.type ? { artifactType: artifact.type } : {},
4861
- ...artifact.url ? { artifactUrl: artifact.url } : {},
4862
- decisionId: decision.id,
4863
- ...decision.status ? { decisionStatus: decision.status } : {},
4864
- decisionTitle: decision.title,
4865
- id: initiative.id,
4866
- liveUrl,
4867
- title: initiative.title,
4868
- workspaceId: workspace.id,
4869
- workspaceName: workspace.name
4870
- };
4795
+ async function promptForWorkspaceName(prompts) {
4796
+ return prompts.text({
4797
+ message: "Workspace name",
4798
+ placeholder: "Founders",
4799
+ validate(value) {
4800
+ if (!value || value.trim().length === 0) {
4801
+ return "Workspace name is required.";
4802
+ }
4803
+ return void 0;
4804
+ }
4805
+ });
4871
4806
  }
4872
- function toOnboardingTaskRecord(task, workspace, options = {}) {
4873
- return {
4874
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4875
- id: task.id,
4876
- ...options.initiativeId ? { initiativeId: options.initiativeId } : {},
4877
- ...task.status ? { status: task.status } : {},
4878
- title: task.title,
4879
- ...options.workstreamId ? { workstreamId: options.workstreamId } : {},
4880
- workspaceId: workspace.id,
4881
- workspaceName: workspace.name
4882
- };
4807
+ async function promptForWorkspaceDescription(prompts) {
4808
+ return prompts.text({
4809
+ message: "Workspace description",
4810
+ placeholder: "Optional"
4811
+ });
4883
4812
  }
4884
- function toFirstValueInitiativeRecord(initiative, liveUrl, workspace) {
4813
+ async function createAndSelectWorkspace(client, prompts) {
4814
+ const name = await promptForWorkspaceName(prompts);
4815
+ if (prompts.isCancel(name)) {
4816
+ return cancelResult(prompts);
4817
+ }
4818
+ if (typeof name !== "string") {
4819
+ return cancelResult(prompts);
4820
+ }
4821
+ const description = await promptForWorkspaceDescription(prompts);
4822
+ if (prompts.isCancel(description)) {
4823
+ return cancelResult(prompts);
4824
+ }
4825
+ if (typeof description !== "string") {
4826
+ return cancelResult(prompts);
4827
+ }
4828
+ const trimmedDescription = trimDescription(description);
4829
+ const createWorkspaceInput = trimmedDescription ? { name, description: trimmedDescription } : { name };
4830
+ const created = await client.createWorkspace(createWorkspaceInput);
4831
+ if (created.isDefault) {
4832
+ return {
4833
+ created: true,
4834
+ defaultChanged: false,
4835
+ message: `Created "${created.name}" and it is already the default OrgX workspace.`,
4836
+ status: "updated",
4837
+ workspace: created
4838
+ };
4839
+ }
4840
+ const promoted = await client.setDefaultWorkspace({ id: created.id });
4885
4841
  return {
4886
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4887
- id: initiative.id,
4888
- liveUrl,
4889
- ...initiative.summary ? { summary: initiative.summary } : {},
4890
- title: initiative.title,
4891
- workspaceId: workspace.id,
4892
- workspaceName: workspace.name
4842
+ created: true,
4843
+ defaultChanged: promoted.changed,
4844
+ message: `Created "${promoted.workspace.name}" and set it as the default OrgX workspace.`,
4845
+ status: "updated",
4846
+ workspace: promoted.workspace
4893
4847
  };
4894
4848
  }
4895
- async function requireOrgxAuth2(options = {}) {
4896
- const auth = await resolveOrgxAuth(options);
4897
- if (!auth) {
4898
- throw new Error(
4899
- "No OrgX API key configured. Run `wizard auth login` or `wizard auth set-key <oxk_...>` first."
4900
- );
4901
- }
4902
- return auth;
4903
- }
4904
- async function createEntity(type, body, parse2, options = {}) {
4905
- const auth = await requireOrgxAuth2(options);
4906
- const response = await fetch(buildOrgxApiUrl("/entities", auth.baseUrl), {
4907
- method: "POST",
4908
- headers: {
4909
- Authorization: `Bearer ${auth.apiKey}`,
4910
- "Content-Type": "application/json"
4911
- },
4912
- body: JSON.stringify({
4913
- type,
4914
- ...body
4915
- }),
4916
- signal: AbortSignal.timeout(7e3)
4917
- });
4918
- const responseBody = parseResponseBody3(await response.text());
4919
- if (!response.ok) {
4920
- throw new Error(`Failed to create ${type}. ${formatHttpError2(response.status, responseBody)}`);
4921
- }
4922
- return parse2(responseBody);
4923
- }
4924
- async function updateEntity(type, id, body, parse2, options = {}) {
4925
- const auth = await requireOrgxAuth2(options);
4926
- const response = await fetch(buildOrgxApiUrl("/entities", auth.baseUrl), {
4927
- method: "PATCH",
4928
- headers: {
4929
- Authorization: `Bearer ${auth.apiKey}`,
4930
- "Content-Type": "application/json"
4931
- },
4932
- body: JSON.stringify({
4933
- type,
4934
- id,
4935
- ...body
4936
- }),
4937
- signal: AbortSignal.timeout(7e3)
4938
- });
4939
- const responseBody = parseResponseBody3(await response.text());
4940
- if (!response.ok) {
4941
- throw new Error(`Failed to update ${type}. ${formatHttpError2(response.status, responseBody)}`);
4942
- }
4943
- return parse2(responseBody);
4944
- }
4945
- function buildLiveUrl(baseUrl, initiativeId) {
4946
- const parsed = new URL(normalizeOrgxBaseUrl(baseUrl));
4947
- parsed.pathname = `/live/${initiativeId}`;
4948
- parsed.search = "";
4949
- parsed.hash = "";
4950
- return parsed.toString();
4951
- }
4952
- async function createFounderDemoDecision(initiative, workspaceId, options = {}) {
4953
- return createEntity(
4954
- "decision",
4955
- {
4956
- initiative_id: initiative.id,
4957
- summary: FOUNDER_DEMO_DECISION_SUMMARY,
4958
- title: FOUNDER_DEMO_DECISION_TITLE,
4959
- workspace_id: workspaceId
4960
- },
4961
- parseDecision,
4962
- options
4963
- );
4964
- }
4965
- async function approveFounderDemoDecision(decisionId, options = {}) {
4966
- return updateEntity(
4967
- "decision",
4968
- decisionId,
4969
- {
4970
- resolution_summary: FOUNDER_DEMO_DECISION_RESOLUTION,
4971
- status: "approved"
4972
- },
4973
- parseDecision,
4974
- options
4975
- );
4976
- }
4977
- async function createFounderDemoArtifact(initiative, liveUrl, workspaceId, options = {}) {
4978
- return createEntity(
4979
- "artifact",
4980
- {
4981
- artifact_type: FOUNDER_DEMO_ARTIFACT_TYPE,
4982
- description: FOUNDER_DEMO_ARTIFACT_DESCRIPTION,
4983
- entity_id: initiative.id,
4984
- entity_type: "initiative",
4985
- external_url: liveUrl,
4986
- initiative_id: initiative.id,
4987
- name: FOUNDER_DEMO_ARTIFACT_NAME,
4988
- workspace_id: workspaceId
4989
- },
4990
- parseArtifact,
4991
- options
4992
- );
4993
- }
4994
- async function createInitiative(input, options = {}) {
4995
- const title = input.title.trim();
4996
- if (!title) {
4997
- throw new Error("Initiative title is required.");
4998
- }
4999
- return createEntity(
5000
- "initiative",
5001
- {
5002
- title,
5003
- status: "active",
5004
- ...input.summary?.trim() ? { summary: input.summary.trim() } : {},
5005
- ...input.workspaceId?.trim() ? { workspace_id: input.workspaceId.trim() } : {}
5006
- },
5007
- parseInitiative,
5008
- options
5009
- );
5010
- }
5011
- async function ensureFounderDemoInitiative(workspace, options = {}) {
5012
- const existingRecord = readWizardState(options.statePath)?.demoInitiative;
5013
- const matchingRecord = existingRecord?.workspaceId === workspace.id ? existingRecord : void 0;
5014
- const auth = await requireOrgxAuth2(options);
5015
- const initiative = matchingRecord ? {
5016
- id: matchingRecord.id,
5017
- title: matchingRecord.title
5018
- } : await createInitiative(
5019
- {
5020
- title: FOUNDER_DEMO_INITIATIVE_TITLE,
5021
- summary: FOUNDER_DEMO_INITIATIVE_SUMMARY,
5022
- workspaceId: workspace.id
5023
- },
5024
- options
5025
- );
5026
- const liveUrl = matchingRecord?.liveUrl || buildLiveUrl(auth.baseUrl, initiative.id);
5027
- const decision = matchingRecord?.decisionId ? matchingRecord.decisionStatus === "approved" && matchingRecord.decisionTitle ? {
5028
- id: matchingRecord.decisionId,
5029
- status: matchingRecord.decisionStatus,
5030
- title: matchingRecord.decisionTitle
5031
- } : await approveFounderDemoDecision(matchingRecord.decisionId, options) : await approveFounderDemoDecision(
5032
- (await createFounderDemoDecision(initiative, workspace.id, options)).id,
5033
- options
5034
- );
5035
- const artifact = matchingRecord?.artifactId && matchingRecord.artifactName ? {
5036
- id: matchingRecord.artifactId,
5037
- name: matchingRecord.artifactName,
5038
- ...matchingRecord.artifactType ? { type: matchingRecord.artifactType } : {},
5039
- ...matchingRecord.artifactUrl ? { url: matchingRecord.artifactUrl } : {}
5040
- } : await createFounderDemoArtifact(initiative, liveUrl, workspace.id, options);
5041
- const record = toDemoInitiativeRecord(artifact, decision, initiative, liveUrl, workspace);
5042
- updateWizardState(
5043
- (current) => ({
5044
- ...current,
5045
- demoInitiative: record
5046
- }),
5047
- options.statePath
5048
- );
5049
- return {
5050
- artifact,
5051
- created: !matchingRecord,
5052
- decision,
5053
- initiative,
5054
- liveUrl
5055
- };
5056
- }
5057
- async function ensureFirstValueInitiative(workspace, options = {}) {
5058
- const existingRecord = readWizardState(options.statePath)?.firstValueInitiative;
5059
- const matchingRecord = existingRecord?.workspaceId === workspace.id ? existingRecord : void 0;
5060
- const auth = await requireOrgxAuth2(options);
5061
- if (matchingRecord) {
5062
- return {
5063
- created: false,
5064
- initiative: {
5065
- id: matchingRecord.id,
5066
- title: matchingRecord.title,
5067
- ...matchingRecord.summary ? { summary: matchingRecord.summary } : {}
5068
- },
5069
- liveUrl: matchingRecord.liveUrl || buildLiveUrl(auth.baseUrl, matchingRecord.id)
5070
- };
5071
- }
5072
- const initiative = await createInitiative(
5073
- {
5074
- title: options.title?.trim() || FIRST_VALUE_INITIATIVE_TITLE,
5075
- summary: options.summary?.trim() || FIRST_VALUE_INITIATIVE_SUMMARY,
5076
- workspaceId: workspace.id
5077
- },
5078
- options
5079
- );
5080
- const liveUrl = buildLiveUrl(auth.baseUrl, initiative.id);
5081
- updateWizardState(
5082
- (current) => ({
5083
- ...current,
5084
- firstValueInitiative: toFirstValueInitiativeRecord(initiative, liveUrl, workspace)
5085
- }),
5086
- options.statePath
5087
- );
5088
- return {
5089
- created: true,
5090
- initiative,
5091
- liveUrl
5092
- };
5093
- }
5094
- async function ensureOnboardingTask(workspace, options = {}) {
5095
- const existingRecord = readWizardState(options.statePath)?.onboardingTask;
5096
- if (existingRecord?.workspaceId === workspace.id) {
5097
- return {
5098
- id: existingRecord.id,
5099
- title: existingRecord.title,
5100
- ...existingRecord.status ? { status: existingRecord.status } : {}
5101
- };
5102
- }
5103
- const initiativeId = options.initiativeId?.trim();
5104
- if (!initiativeId) {
5105
- throw new Error(
5106
- "Starter onboarding task requires an initiative context. Re-run setup with the founder preset or create an initiative before requesting onboarding tasks."
5107
- );
5108
- }
5109
- const workstream = await createEntity(
5110
- "workstream",
5111
- {
5112
- initiative_id: initiativeId,
5113
- status: "active",
5114
- summary: ONBOARDING_WORKSTREAM_SUMMARY,
5115
- title: ONBOARDING_WORKSTREAM_TITLE,
5116
- workspace_id: workspace.id
5117
- },
5118
- parseWorkstream,
5119
- options
5120
- );
5121
- const task = await createEntity(
5122
- "task",
5123
- {
5124
- initiative_id: initiativeId,
5125
- status: "todo",
5126
- summary: ONBOARDING_TASK_SUMMARY,
5127
- title: ONBOARDING_TASK_TITLE,
5128
- workstream_id: workstream.id,
5129
- workspace_id: workspace.id
5130
- },
5131
- parseTask,
5132
- options
5133
- );
5134
- updateWizardState(
5135
- (current) => ({
5136
- ...current,
5137
- onboardingTask: toOnboardingTaskRecord(task, workspace, {
5138
- initiativeId,
5139
- workstreamId: workstream.id
5140
- })
5141
- }),
5142
- options.statePath
5143
- );
5144
- return task;
5145
- }
5146
-
5147
- // src/lib/setup-workspace.ts
5148
- var CREATE_WORKSPACE_VALUE = "__create_workspace__";
5149
- var SKIP_WORKSPACE_VALUE = "__skip_workspace__";
5150
- var REAUTH_WORKSPACE_VALUE = "__reauth_workspace__";
5151
- function trimDescription(value) {
5152
- const trimmed = value.trim();
5153
- return trimmed.length > 0 ? trimmed : void 0;
5154
- }
5155
- function cancelResult(prompts, message = "Workspace bootstrap cancelled.") {
5156
- prompts.cancel(message);
5157
- return {
5158
- message,
5159
- status: "cancelled"
5160
- };
5161
- }
5162
- function buildWorkspaceLabel(workspace, currentWorkspaceId) {
5163
- const suffixes = [];
5164
- if (workspace.isDefault) {
5165
- suffixes.push("default");
5166
- }
5167
- if (workspace.id === currentWorkspaceId) {
5168
- suffixes.push("current");
5169
- }
5170
- if (suffixes.length === 0) {
5171
- return workspace.name;
5172
- }
5173
- return `${workspace.name} (${suffixes.join(", ")})`;
5174
- }
5175
- function buildWorkspaceSelectOptions(workspaces, currentWorkspaceId) {
5176
- const options = workspaces.map((workspace) => ({
5177
- value: workspace.id,
5178
- label: buildWorkspaceLabel(workspace, currentWorkspaceId),
5179
- ...workspace.description ? { hint: workspace.description } : {}
5180
- }));
5181
- options.push(
5182
- {
5183
- value: CREATE_WORKSPACE_VALUE,
5184
- label: "Create a new workspace",
5185
- hint: "Name it here and set it as the default for this machine."
5186
- },
5187
- {
5188
- value: SKIP_WORKSPACE_VALUE,
5189
- label: "Skip for now",
5190
- hint: "Leave workspace selection unchanged and finish setup."
5191
- }
5192
- );
5193
- return options;
5194
- }
5195
- async function promptForWorkspaceName(prompts) {
5196
- return prompts.text({
5197
- message: "Workspace name",
5198
- placeholder: "Founders",
5199
- validate(value) {
5200
- if (!value || value.trim().length === 0) {
5201
- return "Workspace name is required.";
5202
- }
5203
- return void 0;
5204
- }
5205
- });
5206
- }
5207
- async function promptForWorkspaceDescription(prompts) {
5208
- return prompts.text({
5209
- message: "Workspace description",
5210
- placeholder: "Optional"
5211
- });
5212
- }
5213
- async function createAndSelectWorkspace(client, prompts) {
5214
- const name = await promptForWorkspaceName(prompts);
5215
- if (prompts.isCancel(name)) {
5216
- return cancelResult(prompts);
5217
- }
5218
- if (typeof name !== "string") {
5219
- return cancelResult(prompts);
5220
- }
5221
- const description = await promptForWorkspaceDescription(prompts);
5222
- if (prompts.isCancel(description)) {
5223
- return cancelResult(prompts);
5224
- }
5225
- if (typeof description !== "string") {
5226
- return cancelResult(prompts);
5227
- }
5228
- const trimmedDescription = trimDescription(description);
5229
- const createWorkspaceInput = trimmedDescription ? { name, description: trimmedDescription } : { name };
5230
- const created = await client.createWorkspace(createWorkspaceInput);
5231
- if (created.isDefault) {
5232
- return {
5233
- created: true,
5234
- defaultChanged: false,
5235
- message: `Created "${created.name}" and it is already the default OrgX workspace.`,
5236
- status: "updated",
5237
- workspace: created
5238
- };
5239
- }
5240
- const promoted = await client.setDefaultWorkspace({ id: created.id });
5241
- return {
5242
- created: true,
5243
- defaultChanged: promoted.changed,
5244
- message: `Created "${promoted.workspace.name}" and set it as the default OrgX workspace.`,
5245
- status: "updated",
5246
- workspace: promoted.workspace
5247
- };
5248
- }
5249
- async function runWorkspaceSetup(client, prompts, options) {
5250
- if (!options.interactive) {
5251
- return {
5252
- message: "Interactive workspace bootstrap skipped because this shell is not attached to a TTY.",
5253
- status: "skipped"
5254
- };
4849
+ async function runWorkspaceSetup(client, prompts, options) {
4850
+ if (!options.interactive) {
4851
+ return {
4852
+ message: "Interactive workspace bootstrap skipped because this shell is not attached to a TTY.",
4853
+ status: "skipped"
4854
+ };
5255
4855
  }
5256
4856
  const workspaces = await client.listWorkspaces();
5257
4857
  const currentWorkspace = workspaces.length > 0 ? await client.getCurrentWorkspace().catch(() => workspaces.find((workspace) => workspace.isDefault) ?? null) : null;
@@ -5327,69 +4927,299 @@ async function runWorkspaceSetup(client, prompts, options) {
5327
4927
  if (selected === CREATE_WORKSPACE_VALUE) {
5328
4928
  return createAndSelectWorkspace(client, prompts);
5329
4929
  }
5330
- const chosenWorkspace = workspaces.find((workspace) => workspace.id === selected);
5331
- if (!chosenWorkspace) {
5332
- throw new Error(`Selected workspace ${selected} is no longer available.`);
4930
+ const chosenWorkspace = workspaces.find((workspace) => workspace.id === selected);
4931
+ if (!chosenWorkspace) {
4932
+ throw new Error(`Selected workspace ${selected} is no longer available.`);
4933
+ }
4934
+ if (chosenWorkspace.isDefault) {
4935
+ return {
4936
+ defaultChanged: false,
4937
+ message: `"${chosenWorkspace.name}" is already the default OrgX workspace.`,
4938
+ status: "unchanged",
4939
+ workspace: chosenWorkspace
4940
+ };
4941
+ }
4942
+ const promoted = await client.setDefaultWorkspace({ id: chosenWorkspace.id });
4943
+ return {
4944
+ defaultChanged: promoted.changed,
4945
+ message: `Set "${promoted.workspace.name}" as the default OrgX workspace.`,
4946
+ status: promoted.changed ? "updated" : "unchanged",
4947
+ workspace: promoted.workspace
4948
+ };
4949
+ }
4950
+
4951
+ // src/lib/founder-preset.ts
4952
+ async function runFounderPreset(prompts, options) {
4953
+ const surfaceResults = await setupDetectedSurfaces();
4954
+ const pluginTargets = options.pluginTargets ?? (await listOrgxPluginStatuses()).filter((status) => status.installed).map((status) => status.target);
4955
+ const skillReport = await installOrgxSkills({
4956
+ pluginTargets,
4957
+ skillNames: [...DEFAULT_ORGX_SKILL_PACKS]
4958
+ });
4959
+ let workspaceSetup;
4960
+ let workspace = await getCurrentWorkspace().catch(() => null);
4961
+ if (workspace || options.interactive) {
4962
+ workspaceSetup = await runWorkspaceSetup(
4963
+ {
4964
+ createWorkspace,
4965
+ getCurrentWorkspace,
4966
+ listWorkspaces,
4967
+ setDefaultWorkspace
4968
+ },
4969
+ prompts,
4970
+ options
4971
+ );
4972
+ if (workspaceSetup.status === "cancelled") {
4973
+ return workspaceSetup;
4974
+ }
4975
+ workspace = workspaceSetup.workspace ?? workspace ?? await getCurrentWorkspace().catch(() => null);
4976
+ }
4977
+ const continuity = persistContinuityDefaults({
4978
+ statuses: listSurfaceStatuses(),
4979
+ workspace
4980
+ });
4981
+ return {
4982
+ continuity,
4983
+ skillReport,
4984
+ surfaceResults,
4985
+ workspace,
4986
+ ...workspaceSetup ? { workspaceSetup } : {}
4987
+ };
4988
+ }
4989
+
4990
+ // src/lib/initiatives.ts
4991
+ var ONBOARDING_TASK_TITLE = "Complete OrgX onboarding";
4992
+ var ONBOARDING_TASK_SUMMARY = "Starter onboarding task created by @useorgx/wizard so the first workspace has a clear follow-up after setup.";
4993
+ var ONBOARDING_WORKSTREAM_TITLE = "OrgX onboarding";
4994
+ var ONBOARDING_WORKSTREAM_SUMMARY = "Starter onboarding workstream created by @useorgx/wizard so the first workspace has a home for setup follow-up tasks.";
4995
+ var FIRST_VALUE_INITIATIVE_TITLE = "Make OrgX useful on this machine";
4996
+ var FIRST_VALUE_INITIATIVE_SUMMARY = "First initiative created by @useorgx/wizard so setup ends with a live workspace, an onboarding workstream, and a clean handoff into the user's configured AI tools.";
4997
+ function parseResponseBody3(text2) {
4998
+ if (!text2) {
4999
+ return null;
5000
+ }
5001
+ try {
5002
+ return JSON.parse(text2);
5003
+ } catch {
5004
+ return text2;
5005
+ }
5006
+ }
5007
+ function formatHttpError2(status, body) {
5008
+ if (typeof body === "string" && body.trim().length > 0) {
5009
+ return `HTTP ${status}: ${body}`;
5010
+ }
5011
+ if (isRecord(body) && typeof body.error === "string" && body.error.trim().length > 0) {
5012
+ return `HTTP ${status}: ${body.error}`;
5013
+ }
5014
+ return `HTTP ${status}`;
5015
+ }
5016
+ function extractEntity(payload) {
5017
+ const entity = isRecord(payload) && isRecord(payload.data) ? payload.data : payload;
5018
+ if (!isRecord(entity)) {
5019
+ throw new Error("OrgX returned an unexpected entity payload.");
5020
+ }
5021
+ return entity;
5022
+ }
5023
+ function parseInitiative(payload) {
5024
+ const entity = extractEntity(payload);
5025
+ const id = typeof entity.id === "string" ? entity.id.trim() : "";
5026
+ const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
5027
+ if (!id || !title) {
5028
+ throw new Error("OrgX returned an incomplete initiative payload.");
5029
+ }
5030
+ return {
5031
+ id,
5032
+ title,
5033
+ ...typeof entity.summary === "string" && entity.summary.trim().length > 0 ? { summary: entity.summary.trim() } : {}
5034
+ };
5035
+ }
5036
+ function parseTask(payload) {
5037
+ const entity = extractEntity(payload);
5038
+ const id = typeof entity.id === "string" ? entity.id.trim() : "";
5039
+ const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
5040
+ if (!id || !title) {
5041
+ throw new Error("OrgX returned an incomplete task payload.");
5042
+ }
5043
+ return {
5044
+ id,
5045
+ title,
5046
+ ...typeof entity.status === "string" && entity.status.trim().length > 0 ? { status: entity.status.trim() } : {},
5047
+ ...typeof entity.summary === "string" && entity.summary.trim().length > 0 ? { summary: entity.summary.trim() } : {}
5048
+ };
5049
+ }
5050
+ function parseWorkstream(payload) {
5051
+ const entity = extractEntity(payload);
5052
+ const id = typeof entity.id === "string" ? entity.id.trim() : "";
5053
+ const title = typeof entity.title === "string" ? entity.title.trim() : typeof entity.name === "string" ? entity.name.trim() : "";
5054
+ if (!id || !title) {
5055
+ throw new Error("OrgX returned an incomplete workstream payload.");
5056
+ }
5057
+ return { id, title };
5058
+ }
5059
+ function toOnboardingTaskRecord(task, workspace, options = {}) {
5060
+ return {
5061
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5062
+ id: task.id,
5063
+ ...options.initiativeId ? { initiativeId: options.initiativeId } : {},
5064
+ ...task.status ? { status: task.status } : {},
5065
+ title: task.title,
5066
+ ...options.workstreamId ? { workstreamId: options.workstreamId } : {},
5067
+ workspaceId: workspace.id,
5068
+ workspaceName: workspace.name
5069
+ };
5070
+ }
5071
+ function toFirstValueInitiativeRecord(initiative, liveUrl, workspace) {
5072
+ return {
5073
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5074
+ id: initiative.id,
5075
+ liveUrl,
5076
+ ...initiative.summary ? { summary: initiative.summary } : {},
5077
+ title: initiative.title,
5078
+ workspaceId: workspace.id,
5079
+ workspaceName: workspace.name
5080
+ };
5081
+ }
5082
+ async function requireOrgxAuth2(options = {}) {
5083
+ const auth = await resolveOrgxAuth(options);
5084
+ if (!auth) {
5085
+ throw new Error(
5086
+ "No OrgX API key configured. Run `wizard auth login` or `wizard auth set-key <oxk_...>` first."
5087
+ );
5088
+ }
5089
+ return auth;
5090
+ }
5091
+ async function createEntity(type, body, parse2, options = {}) {
5092
+ const auth = await requireOrgxAuth2(options);
5093
+ const response = await fetch(buildOrgxApiUrl("/entities", auth.baseUrl), {
5094
+ method: "POST",
5095
+ headers: {
5096
+ Authorization: `Bearer ${auth.apiKey}`,
5097
+ "Content-Type": "application/json"
5098
+ },
5099
+ body: JSON.stringify({
5100
+ type,
5101
+ ...body
5102
+ }),
5103
+ signal: AbortSignal.timeout(7e3)
5104
+ });
5105
+ const responseBody = parseResponseBody3(await response.text());
5106
+ if (!response.ok) {
5107
+ throw new Error(`Failed to create ${type}. ${formatHttpError2(response.status, responseBody)}`);
5108
+ }
5109
+ return parse2(responseBody);
5110
+ }
5111
+ function buildLiveUrl(baseUrl, initiativeId) {
5112
+ const parsed = new URL(normalizeOrgxBaseUrl(baseUrl));
5113
+ parsed.pathname = `/live/${initiativeId}`;
5114
+ parsed.search = "";
5115
+ parsed.hash = "";
5116
+ return parsed.toString();
5117
+ }
5118
+ async function createInitiative(input, options = {}) {
5119
+ const title = input.title.trim();
5120
+ if (!title) {
5121
+ throw new Error("Initiative title is required.");
5333
5122
  }
5334
- if (chosenWorkspace.isDefault) {
5123
+ return createEntity(
5124
+ "initiative",
5125
+ {
5126
+ title,
5127
+ status: "active",
5128
+ ...input.summary?.trim() ? { summary: input.summary.trim() } : {},
5129
+ ...input.workspaceId?.trim() ? { workspace_id: input.workspaceId.trim() } : {}
5130
+ },
5131
+ parseInitiative,
5132
+ options
5133
+ );
5134
+ }
5135
+ async function ensureFirstValueInitiative(workspace, options = {}) {
5136
+ const existingRecord = readWizardState(options.statePath)?.firstValueInitiative;
5137
+ const matchingRecord = existingRecord?.workspaceId === workspace.id ? existingRecord : void 0;
5138
+ const auth = await requireOrgxAuth2(options);
5139
+ if (matchingRecord) {
5335
5140
  return {
5336
- defaultChanged: false,
5337
- message: `"${chosenWorkspace.name}" is already the default OrgX workspace.`,
5338
- status: "unchanged",
5339
- workspace: chosenWorkspace
5141
+ created: false,
5142
+ initiative: {
5143
+ id: matchingRecord.id,
5144
+ title: matchingRecord.title,
5145
+ ...matchingRecord.summary ? { summary: matchingRecord.summary } : {}
5146
+ },
5147
+ liveUrl: matchingRecord.liveUrl || buildLiveUrl(auth.baseUrl, matchingRecord.id)
5340
5148
  };
5341
5149
  }
5342
- const promoted = await client.setDefaultWorkspace({ id: chosenWorkspace.id });
5150
+ const initiative = await createInitiative(
5151
+ {
5152
+ title: options.title?.trim() || FIRST_VALUE_INITIATIVE_TITLE,
5153
+ summary: options.summary?.trim() || FIRST_VALUE_INITIATIVE_SUMMARY,
5154
+ workspaceId: workspace.id
5155
+ },
5156
+ options
5157
+ );
5158
+ const liveUrl = buildLiveUrl(auth.baseUrl, initiative.id);
5159
+ updateWizardState(
5160
+ (current) => ({
5161
+ ...current,
5162
+ firstValueInitiative: toFirstValueInitiativeRecord(initiative, liveUrl, workspace)
5163
+ }),
5164
+ options.statePath
5165
+ );
5343
5166
  return {
5344
- defaultChanged: promoted.changed,
5345
- message: `Set "${promoted.workspace.name}" as the default OrgX workspace.`,
5346
- status: promoted.changed ? "updated" : "unchanged",
5347
- workspace: promoted.workspace
5167
+ created: true,
5168
+ initiative,
5169
+ liveUrl
5348
5170
  };
5349
5171
  }
5350
-
5351
- // src/lib/founder-preset.ts
5352
- async function runFounderPreset(prompts, options) {
5353
- const surfaceResults = await setupDetectedSurfaces();
5354
- const pluginTargets = options.pluginTargets ?? (await listOrgxPluginStatuses()).filter((status) => status.installed).map((status) => status.target);
5355
- const skillReport = await installOrgxSkills({
5356
- pluginTargets,
5357
- skillNames: [...DEFAULT_ORGX_SKILL_PACKS]
5358
- });
5359
- let workspaceSetup;
5360
- let workspace = await getCurrentWorkspace().catch(() => null);
5361
- if (workspace || options.interactive) {
5362
- workspaceSetup = await runWorkspaceSetup(
5363
- {
5364
- createWorkspace,
5365
- getCurrentWorkspace,
5366
- listWorkspaces,
5367
- setDefaultWorkspace
5368
- },
5369
- prompts,
5370
- options
5371
- );
5372
- if (workspaceSetup.status === "cancelled") {
5373
- return workspaceSetup;
5374
- }
5375
- workspace = workspaceSetup.workspace ?? workspace ?? await getCurrentWorkspace().catch(() => null);
5172
+ async function ensureOnboardingTask(workspace, options = {}) {
5173
+ const existingRecord = readWizardState(options.statePath)?.onboardingTask;
5174
+ if (existingRecord?.workspaceId === workspace.id) {
5175
+ return {
5176
+ id: existingRecord.id,
5177
+ title: existingRecord.title,
5178
+ ...existingRecord.status ? { status: existingRecord.status } : {}
5179
+ };
5376
5180
  }
5377
- const continuity = persistContinuityDefaults({
5378
- statuses: listSurfaceStatuses(),
5379
- workspace
5380
- });
5381
- let demoInitiative;
5382
- if (workspace) {
5383
- demoInitiative = await ensureFounderDemoInitiative(workspace);
5181
+ const initiativeId = options.initiativeId?.trim();
5182
+ if (!initiativeId) {
5183
+ throw new Error(
5184
+ "Starter onboarding task requires an initiative context. Re-run setup with the founder preset or create an initiative before requesting onboarding tasks."
5185
+ );
5384
5186
  }
5385
- return {
5386
- continuity,
5387
- ...demoInitiative ? { demoInitiative } : {},
5388
- skillReport,
5389
- surfaceResults,
5390
- workspace,
5391
- ...workspaceSetup ? { workspaceSetup } : {}
5392
- };
5187
+ const workstream = await createEntity(
5188
+ "workstream",
5189
+ {
5190
+ initiative_id: initiativeId,
5191
+ status: "active",
5192
+ summary: ONBOARDING_WORKSTREAM_SUMMARY,
5193
+ title: ONBOARDING_WORKSTREAM_TITLE,
5194
+ workspace_id: workspace.id
5195
+ },
5196
+ parseWorkstream,
5197
+ options
5198
+ );
5199
+ const task = await createEntity(
5200
+ "task",
5201
+ {
5202
+ initiative_id: initiativeId,
5203
+ status: "todo",
5204
+ summary: ONBOARDING_TASK_SUMMARY,
5205
+ title: ONBOARDING_TASK_TITLE,
5206
+ workstream_id: workstream.id,
5207
+ workspace_id: workspace.id
5208
+ },
5209
+ parseTask,
5210
+ options
5211
+ );
5212
+ updateWizardState(
5213
+ (current) => ({
5214
+ ...current,
5215
+ onboardingTask: toOnboardingTaskRecord(task, workspace, {
5216
+ initiativeId,
5217
+ workstreamId: workstream.id
5218
+ })
5219
+ }),
5220
+ options.statePath
5221
+ );
5222
+ return task;
5393
5223
  }
5394
5224
 
5395
5225
  // src/lib/local-skill-discovery.ts
@@ -5607,6 +5437,9 @@ var HOSTED_MCP_OUTAGE_TITLE = "Hosted OrgX MCP is unreachable.";
5607
5437
  function getSetupVerificationHeadline(summary) {
5608
5438
  switch (summary.status) {
5609
5439
  case "degraded":
5440
+ if (summary.transientTimeouts) {
5441
+ return "OrgX servers were slow to respond \u2014 setup applied, but the final health check timed out. Re-run `wizard doctor` in a moment to confirm.";
5442
+ }
5610
5443
  return "Hosted OrgX MCP is down; local setup can still continue.";
5611
5444
  case "error":
5612
5445
  return "Issues detected";
@@ -5616,18 +5449,50 @@ function getSetupVerificationHeadline(summary) {
5616
5449
  return "All systems ready.";
5617
5450
  }
5618
5451
  }
5619
- function summarizeSetupVerification(assessment) {
5452
+ function isTimeoutErrorString(value) {
5453
+ if (!value) return false;
5454
+ return isTimeoutError(new Error(value));
5455
+ }
5456
+ function reportErrorsAreOnlyTimeouts(report) {
5457
+ if (!report) return false;
5458
+ const authTimedOut = !report.auth.ok && !report.auth.skipped && isTimeoutErrorString(report.auth.error);
5459
+ const workspaceTimedOut = !report.workspace.ok && !report.workspace.skipped && isTimeoutErrorString(report.workspace.error);
5460
+ const reachableServicesOk = (report.hostedMcp.skipped || report.hostedMcp.ok) && (report.openclaw.skipped || report.openclaw.ok);
5461
+ return reachableServicesOk && (authTimedOut || workspaceTimedOut);
5462
+ }
5463
+ function summarizeSetupVerification(assessment, report) {
5620
5464
  const errors = assessment.issues.filter((issue) => issue.level === "error");
5621
5465
  if (errors.length === 0) {
5622
5466
  return {
5623
5467
  hostedMcpDegraded: false,
5468
+ transientTimeouts: false,
5624
5469
  status: assessment.issues.length > 0 ? "warning" : "ok"
5625
5470
  };
5626
5471
  }
5627
5472
  const hostedMcpDegraded = errors.every((issue) => issue.title === HOSTED_MCP_OUTAGE_TITLE);
5473
+ if (hostedMcpDegraded) {
5474
+ return {
5475
+ hostedMcpDegraded: true,
5476
+ transientTimeouts: false,
5477
+ status: "degraded"
5478
+ };
5479
+ }
5480
+ const authOrWorkspaceTitles = /* @__PURE__ */ new Set([
5481
+ "OrgX user auth could not be verified.",
5482
+ "Current workspace lookup failed."
5483
+ ]);
5484
+ const onlyAuthOrWorkspaceErrors = errors.every((issue) => authOrWorkspaceTitles.has(issue.title));
5485
+ if (onlyAuthOrWorkspaceErrors && reportErrorsAreOnlyTimeouts(report)) {
5486
+ return {
5487
+ hostedMcpDegraded: false,
5488
+ transientTimeouts: true,
5489
+ status: "degraded"
5490
+ };
5491
+ }
5628
5492
  return {
5629
- hostedMcpDegraded,
5630
- status: hostedMcpDegraded ? "degraded" : "error"
5493
+ hostedMcpDegraded: false,
5494
+ transientTimeouts: false,
5495
+ status: "error"
5631
5496
  };
5632
5497
  }
5633
5498
 
@@ -5669,16 +5534,6 @@ function buildAgentRosterTelemetryProperties(input, base = {}) {
5669
5534
  base
5670
5535
  );
5671
5536
  }
5672
- function buildFounderDemoTelemetryProperties(result, base = {}) {
5673
- return withBaseProperties(
5674
- {
5675
- created: result.created,
5676
- decision_status: result.decision.status ?? "unknown",
5677
- has_artifact_url: Boolean(result.artifact.url)
5678
- },
5679
- base
5680
- );
5681
- }
5682
5537
  function buildFirstValueInitiativeTelemetryProperties(result, base = {}) {
5683
5538
  return withBaseProperties(
5684
5539
  {
@@ -5701,6 +5556,7 @@ function buildDoctorTelemetryProperties(report, assessment, verification, base =
5701
5556
  hosted_mcp_degraded: verification.hostedMcpDegraded,
5702
5557
  hosted_mcp_ok: report.hostedMcp.ok,
5703
5558
  hosted_mcp_tool_ok: report.hostedMcpTool.ok,
5559
+ transient_timeouts: verification.transientTimeouts,
5704
5560
  issue_count: assessment.issues.length,
5705
5561
  openclaw_available: !report.openclaw.skipped,
5706
5562
  openclaw_ok: report.openclaw.ok,
@@ -12153,11 +12009,19 @@ function renderWorkGraphShareables(report, options) {
12153
12009
  lines.push("");
12154
12010
  const aq = report.agentic_quotient;
12155
12011
  const topQuest = aq.repair_quests[0];
12012
+ const strongestTrail = markdownPublicTrails(report)[0];
12013
+ const firstMove = topQuest ? `${topQuest.title} (+${topQuest.expected_aq_lift} AQ): ${topQuest.reason}` : "Claim the profile and turn the strongest evidence path into owner-visible work with linked proof.";
12156
12014
  lines.push("Suggested share copy:");
12157
12015
  lines.push(`- AQ ${aq.aq}. Stack ${aq.stack_score}. Durable ${aq.durability_score}. Gap ${aq.agentic_gap}. ${aq.archetype.label}. Receipts attached.`);
12158
12016
  lines.push(`- Just ran my AQ. ${topQuest ? `Next repair: ${topQuest.title} (+${topQuest.expected_aq_lift} AQ).` : "The gap is the game."}`);
12159
12017
  lines.push(`- Receipts > vibes. AQ ${aq.aq} with ${report.impact_projection.time_saved_hours_per_week}h/week recoverable.`);
12160
12018
  lines.push("");
12019
+ lines.push("First executable move:");
12020
+ lines.push(`- ${firstMove}`);
12021
+ if (strongestTrail) {
12022
+ lines.push(`- Evidence path: ${markdownPublicTitle(strongestTrail.title, "Top work loop")}`);
12023
+ }
12024
+ lines.push("");
12161
12025
  return lines;
12162
12026
  }
12163
12027
  function renderWorkGraphMarkdown(report, options = {}) {
@@ -12284,6 +12148,17 @@ function renderWorkGraphMarkdown(report, options = {}) {
12284
12148
  lines.push(report.agentic_quotient.archetype.roast);
12285
12149
  lines.push(report.agentic_quotient.archetype.truth);
12286
12150
  lines.push("");
12151
+ if (report.agentic_quotient.repair_quests[0]) {
12152
+ const quest = report.agentic_quotient.repair_quests[0];
12153
+ const primaryTrail = markdownPublicTrails(report)[0];
12154
+ lines.push("First executable move:");
12155
+ lines.push(`- ${quest.title} (+${quest.expected_aq_lift} AQ): ${quest.reason}`);
12156
+ if (primaryTrail) {
12157
+ lines.push(`- Starts from: ${markdownPublicTitle(primaryTrail.title, "Top work loop")}`);
12158
+ }
12159
+ lines.push(`- Why it matters: moves AQ ${report.agentic_quotient.aq} toward ${report.agentic_quotient.ceiling} by closing proof, source, or writeback gaps.`);
12160
+ lines.push("");
12161
+ }
12287
12162
  if (report.agentic_quotient.repair_quests.length > 0) {
12288
12163
  lines.push("Repair quests:");
12289
12164
  for (const quest of report.agentic_quotient.repair_quests) {
@@ -12907,6 +12782,7 @@ import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync3 } from
12907
12782
  import { homedir as homedir3 } from "os";
12908
12783
  import { dirname as dirname4, join as join7 } from "path";
12909
12784
  var HOOK_MARKER = "orgx-session-hook.mjs";
12785
+ var EMIT_HOOK_MARKER = "orgx-emit-execution-graph.mjs";
12910
12786
  var HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PermissionRequest", "Stop"];
12911
12787
  var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "SubagentStop", "Stop", "SessionEnd"];
12912
12788
  function defaultPaths(options = {}) {
@@ -12916,6 +12792,7 @@ function defaultPaths(options = {}) {
12916
12792
  codexConfigPath: options.codexConfigPath ?? CODEX_CONFIG_PATH ?? join7(CODEX_DIR, "config.toml"),
12917
12793
  codexHooksPath: options.codexHooksPath ?? join7(CODEX_DIR, "hooks.json"),
12918
12794
  hookScriptPath: options.hookScriptPath ?? join7(hookDir, HOOK_MARKER),
12795
+ emitHookScriptPath: options.emitHookScriptPath ?? join7(hookDir, EMIT_HOOK_MARKER),
12919
12796
  outboxPath: options.outboxPath ?? join7(hookDir, "events.jsonl")
12920
12797
  };
12921
12798
  }
@@ -13036,6 +12913,140 @@ function buildHookCommand(params) {
13036
12913
  `--outbox=${params.outboxPath}`
13037
12914
  ].join(" ");
13038
12915
  }
12916
+ function buildExecutionGraphEmitScriptContent() {
12917
+ return `#!/usr/bin/env node
12918
+ import { readFileSync } from "node:fs";
12919
+
12920
+ function parseArgs(argv) {
12921
+ const args = {};
12922
+ for (const arg of argv) {
12923
+ if (!arg.startsWith("--")) continue;
12924
+ const i = arg.indexOf("=");
12925
+ if (i < 0) args[arg.slice(2)] = "true";
12926
+ else args[arg.slice(2, i)] = arg.slice(i + 1);
12927
+ }
12928
+ return args;
12929
+ }
12930
+ function truthy(v) {
12931
+ return typeof v === "string" && ["1", "true", "yes", "on"].includes(v.toLowerCase());
12932
+ }
12933
+ function pick() {
12934
+ for (let i = 0; i < arguments.length; i++) {
12935
+ const v = arguments[i];
12936
+ if (typeof v === "string" && v.trim()) return v.trim();
12937
+ }
12938
+ return undefined;
12939
+ }
12940
+ function clamp(s, m) {
12941
+ return typeof s === "string" ? s.slice(0, m) : undefined;
12942
+ }
12943
+ async function readStdin() {
12944
+ try {
12945
+ const c = [];
12946
+ for await (const ch of process.stdin) c.push(Buffer.from(ch));
12947
+ return Buffer.concat(c).toString("utf8");
12948
+ } catch (e) {
12949
+ return "";
12950
+ }
12951
+ }
12952
+ function jsonl(raw) {
12953
+ const out = [];
12954
+ if (typeof raw !== "string") return out;
12955
+ for (const line of raw.split(String.fromCharCode(10))) {
12956
+ const t = line.trim();
12957
+ if (!t) continue;
12958
+ try { out.push(JSON.parse(t)); } catch (e) {}
12959
+ }
12960
+ return out;
12961
+ }
12962
+ function blocks(entry) {
12963
+ const m = entry && (entry.message || entry);
12964
+ const c = m && m.content;
12965
+ return Array.isArray(c) ? c : [];
12966
+ }
12967
+ function derive(entries, max) {
12968
+ const errs = new Map();
12969
+ for (const e of entries) for (const b of blocks(e)) {
12970
+ if (b && b.type === "tool_result" && b.tool_use_id) errs.set(b.tool_use_id, !!b.is_error);
12971
+ }
12972
+ const steps = [];
12973
+ for (const e of entries) for (const b of blocks(e)) {
12974
+ if (b && b.type === "tool_use") steps.push({ id: b.id, name: typeof b.name === "string" ? b.name : "tool" });
12975
+ }
12976
+ const nodes = [{ id: "session", type: "task", title: "Claude Code session", status: "completed", requires_evidence: false }];
12977
+ const capped = steps.slice(-(max - 1));
12978
+ for (let i = 0; i < capped.length; i++) {
12979
+ const s = capped[i];
12980
+ nodes.push({ id: "step-" + (i + 1), type: "step", title: clamp(s.name, 500), status: errs.get(s.id) === true ? "failed" : "completed", requires_evidence: false });
12981
+ }
12982
+ return nodes;
12983
+ }
12984
+ function authHeaders(env) {
12985
+ if (env.ORGX_CLIENT_KEY) return { Authorization: "Bearer " + env.ORGX_CLIENT_KEY };
12986
+ if (env.ORGX_API_KEY) {
12987
+ const h = { Authorization: "Bearer " + env.ORGX_API_KEY };
12988
+ if (env.ORGX_USER_ID) h["X-Orgx-User-Id"] = env.ORGX_USER_ID;
12989
+ return h;
12990
+ }
12991
+ if (env.ORGX_SERVICE_KEY && env.ORGX_USER_ID) return { Authorization: "Bearer " + env.ORGX_SERVICE_KEY, "X-Orgx-User-Id": env.ORGX_USER_ID };
12992
+ return null;
12993
+ }
12994
+ (async () => {
12995
+ try {
12996
+ const args = parseArgs(process.argv.slice(2));
12997
+ const env = process.env;
12998
+ if (!(truthy(args.enabled) || truthy(env.ORGX_EMIT_EXECUTION_GRAPH))) return;
12999
+ const initiative = pick(env.ORGX_INITIATIVE_ID, args.initiative);
13000
+ if (!initiative) return;
13001
+ const auth = authHeaders(env);
13002
+ if (!auth) return;
13003
+ const raw = await readStdin();
13004
+ let hook = {};
13005
+ try { hook = raw && raw.trim() ? JSON.parse(raw) : {}; } catch (e) { hook = {}; }
13006
+ const tp = pick(env.ORGX_TRANSCRIPT_PATH, hook.transcript_path);
13007
+ let entries = [];
13008
+ if (tp) { try { entries = jsonl(readFileSync(tp, "utf8")); } catch (e) { entries = []; } }
13009
+ let max = parseInt(env.ORGX_EMIT_MAX_NODES || "", 10);
13010
+ if (!Number.isFinite(max)) max = 40;
13011
+ const nodes = derive(entries, max);
13012
+ const sc = pick(args.source_client, env.ORGX_SOURCE_CLIENT, "claude-code");
13013
+ const event = {
13014
+ schema_version: "1.0.0",
13015
+ initiative_id: initiative,
13016
+ source_client: sc,
13017
+ summary: clamp(env.ORGX_EMIT_SUMMARY, 2000) || (sc + " session: " + (nodes.length - 1) + " step(s)"),
13018
+ nodes: nodes,
13019
+ edges: [],
13020
+ trust_events: [],
13021
+ metadata: { emitter: "orgx-wizard-runtime-hook", via: "stop-hook" },
13022
+ };
13023
+ if (env.ORGX_RUN_ID) event.run_id = env.ORGX_RUN_ID;
13024
+ else event.correlation_id = clamp(pick(hook.session_id, env.ORGX_CORRELATION_ID) || (sc + "-" + initiative), 120);
13025
+ let base = env.ORGX_BASE_URL || "https://useorgx.com";
13026
+ while (base.endsWith("/")) base = base.slice(0, -1);
13027
+ const ctrl = new AbortController();
13028
+ const timer = setTimeout(() => ctrl.abort(), parseInt(env.ORGX_EMIT_TIMEOUT_MS || "", 10) || 4000);
13029
+ try {
13030
+ await fetch(base + "/api/client/live/execution-graph", {
13031
+ method: "POST",
13032
+ headers: Object.assign({ "Content-Type": "application/json" }, auth),
13033
+ body: JSON.stringify(event),
13034
+ signal: ctrl.signal,
13035
+ });
13036
+ } catch (e) {} finally { clearTimeout(timer); }
13037
+ } catch (e) {}
13038
+ process.exit(0);
13039
+ })();
13040
+ `;
13041
+ }
13042
+ function buildEmitHookCommand(params) {
13043
+ return [
13044
+ "node",
13045
+ JSON.stringify(params.emitHookScriptPath),
13046
+ "--enabled=true",
13047
+ `--source_client=${params.sourceClient}`
13048
+ ].join(" ");
13049
+ }
13039
13050
  function mergeCodexHooks(raw, paths) {
13040
13051
  const value = parseJsonObject(raw);
13041
13052
  const hooks = isRecord(value.hooks) ? value.hooks : {};
@@ -13087,6 +13098,20 @@ function mergeClaudeHooks(raw, paths) {
13087
13098
  rule.hooks = hooks;
13088
13099
  changed = true;
13089
13100
  }
13101
+ if (event === "Stop") {
13102
+ const emitCommand = buildEmitHookCommand({
13103
+ emitHookScriptPath: paths.emitHookScriptPath,
13104
+ sourceClient: "claude-code"
13105
+ });
13106
+ const emitAlready = hooks.some(
13107
+ (entry) => isRecord(entry) && entry.type === "command" && typeof entry.command === "string" && entry.command.includes(EMIT_HOOK_MARKER)
13108
+ );
13109
+ if (!emitAlready) {
13110
+ hooks.push({ type: "command", command: emitCommand });
13111
+ rule.hooks = hooks;
13112
+ changed = true;
13113
+ }
13114
+ }
13090
13115
  hooksRoot[event] = list;
13091
13116
  }
13092
13117
  value.hooks = hooksRoot;
@@ -13127,7 +13152,8 @@ function inspectRuntimeHooks(options = {}) {
13127
13152
  installed: {
13128
13153
  claudeCode: hasOrgxHook(claudeSettingsRaw),
13129
13154
  codex: hasOrgxHook(codexHooksRaw),
13130
- hookScript: existsSync9(paths.hookScriptPath)
13155
+ hookScript: existsSync9(paths.hookScriptPath),
13156
+ emitHookScript: existsSync9(paths.emitHookScriptPath)
13131
13157
  },
13132
13158
  codex: {
13133
13159
  configExists: Boolean(codexConfigRaw),
@@ -13146,7 +13172,8 @@ function installRuntimeHooks(targets, options = {}) {
13146
13172
  claudeCode: false,
13147
13173
  codex: false,
13148
13174
  codexConfig: false,
13149
- hookScript: false
13175
+ hookScript: false,
13176
+ emitHookScript: false
13150
13177
  };
13151
13178
  mkdirSync3(dirname4(paths.hookScriptPath), { recursive: true, mode: 448 });
13152
13179
  const scriptContent = buildRuntimeHookScriptContent();
@@ -13156,6 +13183,14 @@ function installRuntimeHooks(targets, options = {}) {
13156
13183
  writeTextFile(paths.hookScriptPath, scriptContent, { mode: 448 });
13157
13184
  changed.hookScript = true;
13158
13185
  }
13186
+ mkdirSync3(dirname4(paths.emitHookScriptPath), { recursive: true, mode: 448 });
13187
+ const emitScriptContent = buildExecutionGraphEmitScriptContent();
13188
+ if (readTextIfExists(paths.emitHookScriptPath) !== emitScriptContent) {
13189
+ const backup = backupExisting(paths.emitHookScriptPath, now);
13190
+ if (backup) backups.push(backup);
13191
+ writeTextFile(paths.emitHookScriptPath, emitScriptContent, { mode: 448 });
13192
+ changed.emitHookScript = true;
13193
+ }
13159
13194
  if (targets.includes("codex")) {
13160
13195
  const rawConfig = readTextIfExists(paths.codexConfigPath);
13161
13196
  const nextConfig = ensureCodexHooksFeature(rawConfig);
@@ -13283,6 +13318,15 @@ function printMutationResults(results) {
13283
13318
  }
13284
13319
  function printSurfaceSummary(results) {
13285
13320
  const summarized = summarizeMutationResults(results);
13321
+ if (summarized.length === 0) {
13322
+ console.log(
13323
+ ` ${ICON.skip} ${pc3.dim("No supported AI tools detected on this machine.")}`
13324
+ );
13325
+ console.log(
13326
+ ` ${pc3.dim("\u2192")} ${pc3.dim("Install Claude, Cursor, Codex, VS Code, Windsurf, or Zed, then re-run setup.")}`
13327
+ );
13328
+ return;
13329
+ }
13286
13330
  const updated = summarized.filter((r) => r.state === "updated");
13287
13331
  if (updated.length === 0) {
13288
13332
  console.log(
@@ -13830,6 +13874,11 @@ async function runWorkGraphCommand(options, defaults = {}) {
13830
13874
  console.log(` ${ICON.ok} ${pc3.green("score ")} ${pc3.dim(formatWorkGraphScoreLine(report.opportunity_score))}`);
13831
13875
  console.log(` ${ICON.ok} ${pc3.green("AQ ")} ${pc3.dim(`${report.agentic_quotient.aq}/100 \xB7 Stack ${report.agentic_quotient.stack_score}/100 \xB7 Durable ${report.agentic_quotient.durability_score}/100 \xB7 Gap ${report.agentic_quotient.agentic_gap}`)}`);
13832
13876
  console.log(` ${ICON.ok} ${pc3.green("archetype ")} ${pc3.dim(report.agentic_quotient.archetype.label)}`);
13877
+ const topQuest = report.agentic_quotient.repair_quests[0];
13878
+ if (topQuest) {
13879
+ console.log(` ${ICON.ok} ${pc3.green("first lift ")} ${pc3.bold(`+${topQuest.expected_aq_lift} AQ`)} ${pc3.dim(topQuest.title)}`);
13880
+ console.log(` ${ICON.skip} ${pc3.bold("why now ")} ${topQuest.reason}`);
13881
+ }
13833
13882
  console.log(` ${ICON.ok} ${pc3.green("audit quality ")} ${pc3.dim(`${report.execution_quality.overall}/100 \xB7 coverage ${report.source_coverage.coverage_score ?? 0}/100`)}`);
13834
13883
  console.log(` ${ICON.ok} ${pc3.green("page quality ")} ${pc3.dim(`${report.page_quality.overall}/100 \xB7 clarity ${report.page_quality.clarity}/100 \xB7 trust ${report.page_quality.trust}/100`)}`);
13835
13884
  console.log(` ${ICON.ok} ${pc3.green("impact ")} ${pc3.dim(`${report.impact_projection.time_saved_hours_per_week}h/week \xB7 +${report.impact_projection.acceleration_percent}% acceleration \xB7 ~$${report.impact_projection.estimated_monthly_value_usd.toLocaleString("en-US")}/month`)}`);
@@ -14050,20 +14099,6 @@ function printFounderPresetResult(result) {
14050
14099
  console.log("");
14051
14100
  printWorkspaceSetupResult(result.workspaceSetup);
14052
14101
  }
14053
- if (result.demoInitiative) {
14054
- console.log("");
14055
- console.log(pc3.bold("demo initiative"));
14056
- console.log(
14057
- ` ${result.demoInitiative.created ? pc3.green("created") : pc3.yellow("unchanged")} ${result.demoInitiative.initiative.title}`
14058
- );
14059
- console.log(` live: ${result.demoInitiative.liveUrl}`);
14060
- console.log(
14061
- ` decision: ${result.demoInitiative.decision.title} ${pc3.dim(`(${result.demoInitiative.decision.status ?? "pending"})`)}`
14062
- );
14063
- console.log(
14064
- ` artifact: ${result.demoInitiative.artifact.name}${result.demoInitiative.artifact.url ? ` ${pc3.dim(result.demoInitiative.artifact.url)}` : ""}`
14065
- );
14066
- }
14067
14102
  }
14068
14103
  function normalizePromptResult(value) {
14069
14104
  return value;
@@ -14488,10 +14523,9 @@ async function maybeConfigureOptionalWorkspaceAddOns(input) {
14488
14523
  }
14489
14524
  const existingState = readWizardState();
14490
14525
  const providedInitiativeId = input.initiativeId?.trim();
14491
- const storedDemoInitiative = existingState?.demoInitiative?.workspaceId === input.workspace.id ? existingState.demoInitiative : void 0;
14492
14526
  const storedFirstValueInitiative = existingState?.firstValueInitiative?.workspaceId === input.workspace.id ? existingState.firstValueInitiative : void 0;
14493
- let effectiveInitiativeId = providedInitiativeId || storedDemoInitiative?.id || storedFirstValueInitiative?.id;
14494
- let firstValueInitiative = providedInitiativeId || storedDemoInitiative ? null : firstValueRecordToResult(storedFirstValueInitiative);
14527
+ let effectiveInitiativeId = providedInitiativeId || storedFirstValueInitiative?.id;
14528
+ let firstValueInitiative = providedInitiativeId ? null : firstValueRecordToResult(storedFirstValueInitiative);
14495
14529
  const firstInitiativeSkipped = hasSetupPromptSkip(
14496
14530
  input.workspace.id,
14497
14531
  "first_initiative"
@@ -14845,7 +14879,7 @@ function printAuthStatus(status) {
14845
14879
  }
14846
14880
  }
14847
14881
  function printDoctorReport(report, assessment) {
14848
- const verification = summarizeSetupVerification(assessment);
14882
+ const verification = summarizeSetupVerification(assessment, report);
14849
14883
  console.log(pc3.dim(" surfaces"));
14850
14884
  printSurfaceTable(report.surfaces);
14851
14885
  console.log("");
@@ -14886,13 +14920,17 @@ function printDoctorReport(report, assessment) {
14886
14920
  console.log("");
14887
14921
  const configuredCount = report.surfaces.filter((s) => s.configured).length;
14888
14922
  if (assessment.issues.length === 0) {
14889
- console.log(` ${ICON.ok} ${pc3.green("All systems ready.")}`);
14890
14923
  if (!report.auth.configured) {
14924
+ console.log(` ${ICON.warn} ${pc3.yellow("Not set up yet \u2014 pair this terminal to finish.")}`);
14891
14925
  console.log(`
14892
- ${pc3.dim("\u2192")} ${pc3.cyan(`${getCmd()} auth login`)} ${pc3.dim("to connect your account")}`);
14926
+ ${pc3.dim("\u2192")} ${pc3.cyan(`${getCmd()} setup`)} ${pc3.dim("configures your AI tools and pairs your account")}`);
14893
14927
  } else {
14928
+ console.log(` ${ICON.ok} ${pc3.green("All systems ready.")}`);
14894
14929
  console.log(` ${pc3.dim("\u2192")} ${pc3.dim(`OrgX is active across ${configuredCount} editor${configuredCount !== 1 ? "s" : ""}`)}`);
14895
14930
  }
14931
+ } else if (verification.transientTimeouts) {
14932
+ console.log(` ${ICON.warn} ${pc3.yellow(getSetupVerificationHeadline(verification))}`);
14933
+ console.log(` ${pc3.dim("\u2192")} ${pc3.cyan(`${getCmd()} doctor`)} ${pc3.dim("re-runs the health checks")}`);
14896
14934
  } else {
14897
14935
  const headlineText = getSetupVerificationHeadline(verification);
14898
14936
  const headline = verification.status === "error" ? `${ICON.err} ${pc3.red(headlineText)}` : `${ICON.warn} ${pc3.yellow(headlineText)}`;
@@ -14909,7 +14947,7 @@ function printDoctorReport(report, assessment) {
14909
14947
  async function main() {
14910
14948
  const program = new Command();
14911
14949
  program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
14912
- const pkgVersion = true ? "0.1.46" : void 0;
14950
+ const pkgVersion = true ? "0.1.48" : void 0;
14913
14951
  program.version(pkgVersion ?? "unknown", "-V, --version");
14914
14952
  program.hook("preAction", (_thisCommand, actionCommand) => {
14915
14953
  if (Boolean(actionCommand.optsWithGlobals().json)) return;
@@ -14988,22 +15026,12 @@ async function main() {
14988
15026
  })
14989
15027
  );
14990
15028
  }
14991
- if (presetResult.demoInitiative) {
14992
- await safeTrackWizardTelemetry(
14993
- "founder_demo_ready",
14994
- buildFounderDemoTelemetryProperties(presetResult.demoInitiative, {
14995
- command: "setup",
14996
- preset: "founder"
14997
- })
14998
- );
14999
- }
15000
15029
  const addOnResult = await maybeConfigureOptionalWorkspaceAddOns({
15001
15030
  ...setupContext ? { context: setupContext } : {},
15002
15031
  interactive,
15003
15032
  profile: setupProfile,
15004
15033
  telemetry: { command: "setup", preset: "founder" },
15005
- workspace: presetResult.workspace,
15006
- ...presetResult.demoInitiative ? { initiativeId: presetResult.demoInitiative.initiative.id } : {}
15034
+ workspace: presetResult.workspace
15007
15035
  });
15008
15036
  if (addOnResult === "cancelled") {
15009
15037
  return;
@@ -15015,7 +15043,7 @@ async function main() {
15015
15043
  console.log("");
15016
15044
  const doctor2 = await runDoctor();
15017
15045
  const assessment2 = assessDoctorReport(doctor2);
15018
- const verification2 = summarizeSetupVerification(assessment2);
15046
+ const verification2 = summarizeSetupVerification(assessment2, doctor2);
15019
15047
  await safeTrackWizardTelemetry(
15020
15048
  "setup_verified",
15021
15049
  buildDoctorTelemetryProperties(doctor2, assessment2, verification2, {
@@ -15042,6 +15070,7 @@ async function main() {
15042
15070
  });
15043
15071
  const wasAlreadyPaired = await resolveOrgxAuth() !== null;
15044
15072
  let resolvedAuth = await resolveOrgxAuth();
15073
+ let cachedWorkspaceCheck;
15045
15074
  if (!resolvedAuth) {
15046
15075
  console.log("");
15047
15076
  if (interactive) {
@@ -15125,6 +15154,20 @@ async function main() {
15125
15154
  })
15126
15155
  );
15127
15156
  const resolvedWorkspace = workspaceSetup.workspace ?? await getCurrentWorkspace().catch(() => null);
15157
+ if (resolvedWorkspace && resolvedAuth) {
15158
+ cachedWorkspaceCheck = {
15159
+ configured: true,
15160
+ ok: true,
15161
+ skipped: false,
15162
+ source: resolvedAuth.source,
15163
+ baseUrl: resolvedAuth.baseUrl,
15164
+ workspace: resolvedWorkspace,
15165
+ details: [
15166
+ `workspace id: ${resolvedWorkspace.id}`,
15167
+ ...resolvedWorkspace.isDefault ? ["workspace is marked as default"] : []
15168
+ ]
15169
+ };
15170
+ }
15128
15171
  if (resolvedWorkspace) {
15129
15172
  persistContinuityDefaults({ workspace: resolvedWorkspace });
15130
15173
  }
@@ -15179,9 +15222,11 @@ async function main() {
15179
15222
  return;
15180
15223
  }
15181
15224
  }
15182
- const doctor = await runDoctor();
15225
+ const doctor = await runDoctor(
15226
+ cachedWorkspaceCheck ? { cachedWorkspace: cachedWorkspaceCheck } : {}
15227
+ );
15183
15228
  const assessment = assessDoctorReport(doctor);
15184
- const verification = summarizeSetupVerification(assessment);
15229
+ const verification = summarizeSetupVerification(assessment, doctor);
15185
15230
  await safeTrackWizardTelemetry(
15186
15231
  "setup_verified",
15187
15232
  buildDoctorTelemetryProperties(doctor, assessment, verification, {
@@ -15619,7 +15664,7 @@ async function main() {
15619
15664
  });
15620
15665
  await runAuditCommand(options);
15621
15666
  });
15622
- const workGraph = program.command("work-graph").description("Build a redacted OrgX Profile from AI-client session search, Slack, MCP, or manual context.");
15667
+ const workGraph = program.command("work-graph").description("Run AQ from real AI-work receipts and surface the first repair that raises execution capacity.");
15623
15668
  workGraph.command("extraction-schema").description("Print the packaged AI-client audit skill used to search sessions, messages, tools, domains, and logs.").option("--output <path>", "write the schema prompt to a file").option("--json", "emit the protocol as JSON instead of Markdown").action(async (options) => {
15624
15669
  await safeTrackWizardTelemetry("work_graph_extraction_schema_started", {
15625
15670
  command: "work-graph extraction-schema",
@@ -15630,14 +15675,14 @@ async function main() {
15630
15675
  workGraph.command("runtime-event").description("Write a redacted Codex/Claude runtime packet into the Work Graph collector directory.").requiredOption("--source <source>", "agent source writing the packet: codex or claude").option("--summary <text>", "public-safe summary of the decision, artifact, blocker, outcome, or tool event").option("--message <text>", "alias for --summary").option("--event-kind <kind>", "event kind hint: decision, artifact, blocker, outcome, tool_call_error", "artifact").option("--role <role>", "source role: user, assistant, tool, or meta", "assistant").option("--tool-name <name>", "tool name when the packet represents a tool call").option("--cwd <path>", "workspace root that owns the collector directory").option("--output-dir <path>", "collector root relative to cwd", ".orgx/work-graph/runtime-events").option("--json", "emit a JSON summary").action((options) => {
15631
15676
  runWorkGraphRuntimeEventCommand(options);
15632
15677
  });
15633
- workGraph.command("preview").description("Preview the OrgX Profile evidence findings without writing to OrgX.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, github, slack, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "15").option("--session-days <days>", "lookback window for local AI-session imports", "60").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only previews").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--json", "emit a JSON command summary").action(async (options) => {
15678
+ workGraph.command("preview").description("Preview AQ, evidence paths, and the first repair without writing to OrgX.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, github, slack, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "15").option("--session-days <days>", "lookback window for local AI-session imports", "60").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only previews").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--json", "emit a JSON command summary").action(async (options) => {
15634
15679
  await safeTrackWizardTelemetry("work_graph_preview_started", {
15635
15680
  command: "work-graph preview",
15636
15681
  from: options.from ?? "manual"
15637
15682
  });
15638
15683
  await runWorkGraphCommand(options);
15639
15684
  });
15640
- workGraph.command("profile").description("Build a local OrgX Profile with evidence findings, domain coverage, source confidence, and repair recommendations.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, github, slack, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "25").option("--session-days <days>", "lookback window for local AI-session imports", "60").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only profiles").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--publish", "publish the generated OrgX Profile to OrgX and return a shareable URL").option("--public-share", "create a public redacted /work-graph/<token> share when publishing").option("--attach-artifact", "attach the report as an OrgX artifact when an initiative/entity is provided").option("--attach-to-initiative <id>", "attach the report to an existing OrgX initiative").option("--entity-type <type>", "entity type for artifact attachment: project, initiative, milestone, task, decision").option("--entity-id <id>", "entity id for artifact attachment").option("--artifact-url <url>", "override the artifact URL stored in OrgX").option("--yes", "approve publish/write prompts in non-interactive mode").option("--json", "emit a JSON command summary").action(async (options) => {
15685
+ workGraph.command("profile").description("Build an AQ profile from real receipts, publish it, and return the first executable repair.").option("--input <path>", "source transcript or summary file; stdin is used when piped").option("--extraction <path>", "structured AI-client extraction JSON; repeat or comma-separate for multiple clients", collectPathOption, []).option("--from <sources>", "auto-import recent local AI sessions: claude, codex, opencode, goose, cursor, github, slack, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "25").option("--session-days <days>", "lookback window for local AI-session imports", "60").option("--codex-sessions-dir <path>", "override Codex sessions directory for import").option("--claude-projects-dir <path>", "override Claude projects directory for import").option("--source-label <label>", "label for the imported manual source").option("--workspace-id <id>", "workspace id override; defaults to the current OrgX workspace when authenticated").option("--workspace-name <name>", "workspace name override for local-only profiles").option("--output-dir <path>", "directory for generated Work Graph JSON and Markdown", ".orgx/work-graph").option("--publish", "publish the generated OrgX Profile to OrgX and return a shareable URL").option("--public-share", "create a public redacted /work-graph/<token> share when publishing").option("--attach-artifact", "attach the report as an OrgX artifact when an initiative/entity is provided").option("--attach-to-initiative <id>", "attach the report to an existing OrgX initiative").option("--entity-type <type>", "entity type for artifact attachment: project, initiative, milestone, task, decision").option("--entity-id <id>", "entity id for artifact attachment").option("--artifact-url <url>", "override the artifact URL stored in OrgX").option("--yes", "approve publish/write prompts in non-interactive mode").option("--json", "emit a JSON command summary").action(async (options) => {
15641
15686
  await safeTrackWizardTelemetry("work_graph_profile_started", {
15642
15687
  command: "work-graph profile",
15643
15688
  from: options.from ?? "manual"
@@ -15698,7 +15743,7 @@ async function main() {
15698
15743
  const report = await runDoctor();
15699
15744
  spinner.stop();
15700
15745
  const assessment = assessDoctorReport(report);
15701
- const verification = summarizeSetupVerification(assessment);
15746
+ const verification = summarizeSetupVerification(assessment, report);
15702
15747
  await safeTrackWizardTelemetry(
15703
15748
  "doctor_ran",
15704
15749
  buildDoctorTelemetryProperties(report, assessment, verification, {