@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/README.md +8 -1
- package/dist/cli.js +690 -645
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
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/
|
|
4749
|
-
var
|
|
4750
|
-
var
|
|
4751
|
-
var
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
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
|
|
4790
|
-
|
|
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
|
-
|
|
4798
|
-
|
|
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
|
|
4803
|
-
const
|
|
4804
|
-
|
|
4805
|
-
|
|
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
|
-
|
|
4810
|
-
|
|
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
|
-
|
|
4826
|
-
|
|
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
|
|
4847
|
-
const
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
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
|
|
4856
|
-
return {
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
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
|
|
4873
|
-
return {
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
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
|
|
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
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
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
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
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
|
|
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
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
workspace: promoted.workspace
|
|
5167
|
+
created: true,
|
|
5168
|
+
initiative,
|
|
5169
|
+
liveUrl
|
|
5348
5170
|
};
|
|
5349
5171
|
}
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
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
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
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
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
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
|
|
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
|
-
|
|
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 ||
|
|
14494
|
-
let firstValueInitiative = providedInitiativeId
|
|
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()}
|
|
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.
|
|
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("
|
|
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
|
|
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
|
|
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, {
|