@useorgx/wizard 0.1.21 → 0.1.22

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
@@ -3,7 +3,9 @@
3
3
  // src/cli.ts
4
4
  import * as clack from "@clack/prompts";
5
5
  import { spawnSync as spawnSync3 } from "child_process";
6
+ import { readFileSync as readFileSync3 } from "fs";
6
7
  import { hostname } from "os";
8
+ import { resolve } from "path";
7
9
  import { Command } from "commander";
8
10
  import pc3 from "picocolors";
9
11
 
@@ -791,7 +793,7 @@ function parsePairingPollResult(value) {
791
793
  };
792
794
  }
793
795
  function sleep(ms) {
794
- return new Promise((resolve) => setTimeout(resolve, ms));
796
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
795
797
  }
796
798
  async function startBrowserPairing(options, fetchImpl) {
797
799
  const data = await fetchJson({
@@ -904,12 +906,12 @@ h1{font-size:1.5rem;color:#b91c1c}p{color:#555;margin-top:.5rem}</style>
904
906
  <p>Return to your terminal and try again.</p>
905
907
  </div></body></html>`;
906
908
  function tryListen(port, hostname2) {
907
- return new Promise((resolve, reject) => {
909
+ return new Promise((resolve2, reject) => {
908
910
  const server = createServer();
909
911
  server.once("error", reject);
910
912
  server.listen(port, hostname2, () => {
911
913
  server.removeListener("error", reject);
912
- resolve(server);
914
+ resolve2(server);
913
915
  });
914
916
  });
915
917
  }
@@ -938,7 +940,7 @@ async function startLocalAuthServer(options) {
938
940
  const successHtml = options.successHtml ?? DEFAULT_SUCCESS_HTML;
939
941
  const errorHtml = options.errorHtml ?? DEFAULT_ERROR_HTML;
940
942
  const { server, port } = await bindServer(options.preferredPort, hostname2);
941
- const result = new Promise((resolve, reject) => {
943
+ const result = new Promise((resolve2, reject) => {
942
944
  const timer = setTimeout(() => {
943
945
  server.close();
944
946
  reject(new Error("Timed out waiting for browser authorization."));
@@ -981,7 +983,7 @@ async function startLocalAuthServer(options) {
981
983
  res.writeHead(200, { "Content-Type": "text/html" }).end(successHtml);
982
984
  clearTimeout(timer);
983
985
  server.close();
984
- resolve({ code, state });
986
+ resolve2({ code, state });
985
987
  });
986
988
  });
987
989
  return { port, result };
@@ -4435,7 +4437,7 @@ function formatCommandFailure(command, args, result) {
4435
4437
  return `${command} ${args.join(" ")} failed${result.exitCode >= 0 ? ` with exit code ${result.exitCode}` : ""}${detail ? `: ${detail}` : "."}`;
4436
4438
  }
4437
4439
  async function defaultCommandRunner(command, args) {
4438
- return await new Promise((resolve) => {
4440
+ return await new Promise((resolve2) => {
4439
4441
  const child = spawn(command, [...args], {
4440
4442
  env: process.env,
4441
4443
  stdio: ["ignore", "pipe", "pipe"]
@@ -4450,7 +4452,7 @@ async function defaultCommandRunner(command, args) {
4450
4452
  });
4451
4453
  child.on("error", (error) => {
4452
4454
  const errorCode = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
4453
- resolve({
4455
+ resolve2({
4454
4456
  exitCode: -1,
4455
4457
  stdout,
4456
4458
  stderr,
@@ -4458,7 +4460,7 @@ async function defaultCommandRunner(command, args) {
4458
4460
  });
4459
4461
  });
4460
4462
  child.on("close", (code) => {
4461
- resolve({
4463
+ resolve2({
4462
4464
  exitCode: code ?? -1,
4463
4465
  stdout,
4464
4466
  stderr
@@ -5925,6 +5927,503 @@ async function fetchOnboardingState(auth) {
5925
5927
  }
5926
5928
  }
5927
5929
 
5930
+ // src/lib/self-audit.ts
5931
+ import { createHash as createHash3 } from "crypto";
5932
+ var SELF_AUDIT_SCHEMA_VERSION = "2026-04-27";
5933
+ var AUDIT_DIMENSIONS = [
5934
+ "queryability",
5935
+ "proof_density",
5936
+ "loop_closure",
5937
+ "context_debt",
5938
+ "autonomy_readiness",
5939
+ "roi_visibility"
5940
+ ];
5941
+ function clampScore(value) {
5942
+ return Math.max(0, Math.min(100, Math.round(value)));
5943
+ }
5944
+ function ratio(numerator, denominator, fallback = 0) {
5945
+ if (denominator <= 0) return fallback;
5946
+ return numerator / denominator;
5947
+ }
5948
+ function includesAny(value, patterns) {
5949
+ return patterns.some((pattern) => pattern.test(value));
5950
+ }
5951
+ function classifyLine(line) {
5952
+ const normalized = line.trim();
5953
+ if (!normalized) return null;
5954
+ if (/^(decision|decided|we decided|d:)\b/i.test(normalized)) return "decision";
5955
+ if (/^(commitment|committed|promise|promised|todo:|we will)\b/i.test(normalized)) return "commitment";
5956
+ if (/^(artifact|receipt|proof|shipped|implemented|commit|pr:)\b/i.test(normalized)) return "artifact";
5957
+ if (/^(open loop|gap|blocker|risk|missing|needs|unresolved)\b/i.test(normalized)) return "open_loop";
5958
+ if (/^(next action|follow[- ]?up|next step|action:)\b/i.test(normalized)) return "next_action";
5959
+ if (/^(outcome|result|impact|metric|adoption)\b/i.test(normalized)) return "outcome";
5960
+ if (/^(roi|economics|token|tokens|cost|saved|time saved|api bill)\b/i.test(normalized)) return "economics";
5961
+ return null;
5962
+ }
5963
+ function extractFounderLoopItems(imports) {
5964
+ const items = [];
5965
+ for (const source of imports) {
5966
+ const lines = source.text.split(/\r?\n/);
5967
+ lines.forEach((line, index) => {
5968
+ const type = classifyLine(line);
5969
+ if (!type) return;
5970
+ const lineNumber = index + 1;
5971
+ items.push({
5972
+ evidenceRef: `${source.sourceId}:L${lineNumber}`,
5973
+ lineNumber,
5974
+ sourceId: source.sourceId,
5975
+ sourceLabel: source.sourceLabel,
5976
+ text: line.trim(),
5977
+ type
5978
+ });
5979
+ });
5980
+ }
5981
+ return items;
5982
+ }
5983
+ function buildSelfAuditSignals(imports, items, options = {}) {
5984
+ const allText = imports.map((source) => source.text).join("\n");
5985
+ const lower = allText.toLowerCase();
5986
+ const decisions = items.filter((item) => item.type === "decision");
5987
+ const artifacts = items.filter((item) => item.type === "artifact");
5988
+ const commitments = items.filter((item) => item.type === "commitment");
5989
+ const nextActions = items.filter((item) => item.type === "next_action");
5990
+ const outcomes = items.filter((item) => item.type === "outcome");
5991
+ const economics = items.filter((item) => item.type === "economics");
5992
+ const proofMentions = (lower.match(/\b(proof|verified|verification|receipt|quality score|artifact)\b/g) ?? []).length;
5993
+ const ownerMentions = (lower.match(/\b(owner|dri|responsible|agent:|founder)\b/g) ?? []).length;
5994
+ const artifactNextActionMentions = artifacts.filter(
5995
+ (item) => includesAny(item.text.toLowerCase(), [/\bnext action\b/, /\bfollow[- ]?up\b/, /\brollback\b/])
5996
+ ).length;
5997
+ const writebackMentions = (lower.match(/\b(approve|approved|writeback|rollback|create task|follow-up task)\b/g) ?? []).length;
5998
+ const repeatedContextPrompts = (lower.match(/\b(recap|catch you up|context again|restate|reread|remind me)\b/g) ?? []).length;
5999
+ return {
6000
+ approvedWritebackTargets: Math.min(3, writebackMentions),
6001
+ artifactsWithNextActions: Math.min(artifacts.length, nextActions.length + artifactNextActionMentions),
6002
+ artifactsWithOwners: Math.min(artifacts.length, ownerMentions),
6003
+ completedWorkItems: artifacts.length,
6004
+ completedWorkWithProof: Math.min(artifacts.length, proofMentions),
6005
+ connectedSources: Math.max(options.connectedSources?.length ?? 0, imports.length),
6006
+ decisionsWithEvidence: decisions.length,
6007
+ economicSignals: economics.length + (lower.includes("token") || lower.includes("cost") || lower.includes("saved") ? 1 : 0),
6008
+ missingSources: options.missingSources?.length ?? 0,
6009
+ openLoops: items.filter((item) => item.type === "open_loop").length,
6010
+ outcomeLinkedItems: outcomes.length,
6011
+ repeatedContextPrompts,
6012
+ totalArtifacts: artifacts.length,
6013
+ totalContextItems: Math.max(items.length, allText.split(/\s+/).filter(Boolean).length),
6014
+ totalDecisions: decisions.length,
6015
+ unresolvedCommitments: Math.max(0, commitments.length - nextActions.length - outcomes.length)
6016
+ };
6017
+ }
6018
+ function scoreSelfAudit(signals) {
6019
+ const queryability = clampScore(
6020
+ 30 + ratio(signals.decisionsWithEvidence, Math.max(1, signals.totalDecisions), 0) * 25 + Math.min(20, signals.connectedSources * 5) + Math.min(30, (signals.totalArtifacts + signals.outcomeLinkedItems + signals.approvedWritebackTargets) * 5)
6021
+ );
6022
+ const proofDensity = clampScore(
6023
+ 30 + ratio(signals.completedWorkWithProof, Math.max(1, signals.completedWorkItems), 0) * 35 + ratio(signals.artifactsWithOwners, Math.max(1, signals.totalArtifacts), 0) * 20 + ratio(signals.artifactsWithNextActions, Math.max(1, signals.totalArtifacts), 0) * 15
6024
+ );
6025
+ const loopClosure = clampScore(
6026
+ 40 + Math.min(25, signals.outcomeLinkedItems * 25) + Math.min(35, signals.approvedWritebackTargets * 20) + (signals.openLoops === 0 ? 15 : Math.max(0, 15 - signals.openLoops * 3))
6027
+ );
6028
+ const contextDebt = clampScore(
6029
+ 100 - Math.min(35, signals.repeatedContextPrompts * 10) - Math.min(35, signals.openLoops * 6) - Math.min(20, signals.missingSources * 4) - Math.min(10, signals.unresolvedCommitments * 3)
6030
+ );
6031
+ const autonomyReadiness = clampScore(
6032
+ 35 + Math.min(30, signals.approvedWritebackTargets * 15) + Math.min(20, signals.completedWorkWithProof * 5) + (signals.openLoops <= 1 ? 15 : 5)
6033
+ );
6034
+ const roiVisibility = clampScore(
6035
+ 30 + Math.min(40, signals.economicSignals * 18) + Math.min(25, signals.outcomeLinkedItems * 25) + Math.min(10, signals.completedWorkWithProof * 3)
6036
+ );
6037
+ return {
6038
+ autonomy_readiness: autonomyReadiness,
6039
+ context_debt: contextDebt,
6040
+ loop_closure: loopClosure,
6041
+ proof_density: proofDensity,
6042
+ queryability,
6043
+ roi_visibility: roiVisibility
6044
+ };
6045
+ }
6046
+ function buildFindings(scores, signals) {
6047
+ const findings = [];
6048
+ for (const dimension of AUDIT_DIMENSIONS) {
6049
+ const score = scores[dimension];
6050
+ if (score >= 95) {
6051
+ findings.push({
6052
+ dimension,
6053
+ evidence: `Score ${score}/100 meets the Phase 2 target.`,
6054
+ recommendation: "Keep this dimension gated by evidence so the score stays earned.",
6055
+ severity: "info",
6056
+ title: `${dimension.replace(/_/g, " ")} is at the 95+ target`
6057
+ });
6058
+ continue;
6059
+ }
6060
+ const recommendationByDimension = {
6061
+ autonomy_readiness: "Keep writeback approval-gated and add rollback references to every generated action.",
6062
+ context_debt: "Reduce repeated context prompts and close unresolved open loops with task or decision artifacts.",
6063
+ loop_closure: "Add outcome references and approved follow-up writebacks so planning changes after execution.",
6064
+ proof_density: "Attach owners, next actions, and verification proof to every completed work artifact.",
6065
+ queryability: "Add cited decisions, artifacts, connected sources, and retrieval scope to the audit output.",
6066
+ roi_visibility: "Add token/time/cost evidence plus an outcome review so ROI is not a narrative claim."
6067
+ };
6068
+ findings.push({
6069
+ dimension,
6070
+ evidence: `Score ${score}/100. Signals: ${JSON.stringify({
6071
+ approvedWritebackTargets: signals.approvedWritebackTargets,
6072
+ completedWorkWithProof: signals.completedWorkWithProof,
6073
+ economicSignals: signals.economicSignals,
6074
+ openLoops: signals.openLoops,
6075
+ outcomeLinkedItems: signals.outcomeLinkedItems,
6076
+ repeatedContextPrompts: signals.repeatedContextPrompts
6077
+ })}`,
6078
+ recommendation: recommendationByDimension[dimension],
6079
+ severity: score < 60 ? "critical" : "warning",
6080
+ title: `${dimension.replace(/_/g, " ")} needs evidence before it can be called 95+`
6081
+ });
6082
+ }
6083
+ return findings;
6084
+ }
6085
+ function buildSelfCritique(scores) {
6086
+ return AUDIT_DIMENSIONS.map((dimension) => {
6087
+ const score = scores[dimension];
6088
+ return {
6089
+ dimension,
6090
+ gap: score >= 95 ? "No score gap. Preserve evidence and regression-test this dimension." : `Needs ${95 - score} more points of verified product evidence before claiming 95+.`,
6091
+ passed: score >= 95,
6092
+ score,
6093
+ target: 95
6094
+ };
6095
+ });
6096
+ }
6097
+ function hashPlanPayload(payload) {
6098
+ return createHash3("sha256").update(JSON.stringify(payload)).digest("hex");
6099
+ }
6100
+ function buildSelfAuditPlan(input) {
6101
+ if (input.imports.length === 0) {
6102
+ throw new Error("At least one AI-session import is required to run the Founder Loop audit.");
6103
+ }
6104
+ const items = extractFounderLoopItems(input.imports);
6105
+ const connectedSources = input.connectedSources ?? input.imports.map((source) => source.sourceLabel);
6106
+ const missingSources = input.missingSources ?? [];
6107
+ const signals = buildSelfAuditSignals(input.imports, items, {
6108
+ connectedSources,
6109
+ missingSources
6110
+ });
6111
+ const scores = scoreSelfAudit(signals);
6112
+ const evidenceRefs = items.slice(0, 12).map((item) => item.evidenceRef);
6113
+ const decisions = items.filter((item) => item.type === "decision");
6114
+ const nextAction = items.find((item) => item.type === "next_action");
6115
+ const basePlan = {
6116
+ artifact_type: "ai_native_self_audit_plan",
6117
+ audit_scope: {
6118
+ connected_sources: connectedSources,
6119
+ loop: "founder",
6120
+ missing_sources: missingSources,
6121
+ time_window_days: input.timeWindowDays ?? 30
6122
+ },
6123
+ extracted_items: items,
6124
+ findings: buildFindings(scores, signals),
6125
+ generated_at: input.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
6126
+ recommended_follow_up: {
6127
+ rollback: "Delete or close the generated OrgX follow-up task if the founder rejects the audit recommendation.",
6128
+ summary: nextAction?.text ?? "Review the audit findings, approve one follow-up action, and attach proof after execution.",
6129
+ title: "Review AI-native self-audit findings and approve first follow-up"
6130
+ },
6131
+ recommended_initiative: {
6132
+ summary: "Generated by @useorgx/wizard audit to close the first Founder Loop from AI-session context, proof artifacts, approved writeback, and outcome review.",
6133
+ title: `Close Founder Loop: ${input.workspace.name} AI-native operating loop`,
6134
+ workstreams: [
6135
+ {
6136
+ purpose: "Capture AI-session context, decisions, commitments, and open loops.",
6137
+ tasks: [
6138
+ {
6139
+ proof_requirement: "AI-session import with cited evidence references.",
6140
+ title: "Import founder AI-session context"
6141
+ }
6142
+ ],
6143
+ title: "Founder Context Ingest"
6144
+ },
6145
+ {
6146
+ purpose: "Turn completed work into artifacts with owners, proof, and next actions.",
6147
+ tasks: [
6148
+ {
6149
+ proof_requirement: "Artifact metadata includes owner, evidence refs, and retrieval scope.",
6150
+ title: "Attach proof artifacts to completed work"
6151
+ }
6152
+ ],
6153
+ title: "Proof Chain"
6154
+ },
6155
+ {
6156
+ purpose: "Write one approved follow-up action into OrgX with rollback context.",
6157
+ tasks: [
6158
+ {
6159
+ proof_requirement: "Approved OrgX task with rollback and evidence references.",
6160
+ title: "Approve first OrgX follow-up writeback"
6161
+ }
6162
+ ],
6163
+ title: "Safe Writeback"
6164
+ },
6165
+ {
6166
+ purpose: "Record outcome and economics so the next plan learns from execution.",
6167
+ tasks: [
6168
+ {
6169
+ proof_requirement: "Founder review with time/token/value estimate and attribution confidence.",
6170
+ title: "Record outcome and economics review"
6171
+ }
6172
+ ],
6173
+ title: "Outcome Review"
6174
+ }
6175
+ ]
6176
+ },
6177
+ safe_writeback_plan: [
6178
+ {
6179
+ action: "create_follow_up_task",
6180
+ approval: "required",
6181
+ rollback: "Delete or close the generated task and preserve the audit artifact as a rejected recommendation.",
6182
+ target: "orgx"
6183
+ }
6184
+ ],
6185
+ schema_version: SELF_AUDIT_SCHEMA_VERSION,
6186
+ scores,
6187
+ self_critique: buildSelfCritique(scores),
6188
+ signals,
6189
+ workspace: input.workspace
6190
+ };
6191
+ const invariant = {
6192
+ decision_refs: decisions.map((item) => item.evidenceRef),
6193
+ evidence_refs: evidenceRefs,
6194
+ goal_ref: `workspace:${input.workspace.id}:ai-native-self-audit`,
6195
+ next_action_ref: nextAction?.evidenceRef ?? "manual-next-action:review-audit",
6196
+ owner_ref: "founder:dri",
6197
+ proof_requirement: "verification",
6198
+ retrieval_scope: "Retrieve the imported AI-session context, extracted Founder Loop items, audit scores, findings, writeback plan, and outcome review."
6199
+ };
6200
+ const artifactHash = hashPlanPayload({ ...basePlan, artifact_invariant: invariant });
6201
+ return {
6202
+ ...basePlan,
6203
+ artifact_hash: artifactHash,
6204
+ artifact_invariant: invariant
6205
+ };
6206
+ }
6207
+ function renderSelfAuditMarkdown(plan) {
6208
+ const lines = [
6209
+ "# AI-Native Founder Loop Self-Audit",
6210
+ "",
6211
+ `Generated: ${plan.generated_at}`,
6212
+ `Workspace: ${plan.workspace.name} (${plan.workspace.id})`,
6213
+ `Artifact hash: ${plan.artifact_hash}`,
6214
+ "",
6215
+ "## Scores",
6216
+ "",
6217
+ "| Dimension | Score | Target | Status |",
6218
+ "| --- | ---: | ---: | --- |",
6219
+ ...AUDIT_DIMENSIONS.map((dimension) => {
6220
+ const score = plan.scores[dimension];
6221
+ return `| ${dimension.replace(/_/g, " ")} | ${score} | 95 | ${score >= 95 ? "pass" : "gap"} |`;
6222
+ }),
6223
+ "",
6224
+ "## Self-Critique",
6225
+ "",
6226
+ ...plan.self_critique.map((item) => `- ${item.dimension}: ${item.gap}`),
6227
+ "",
6228
+ "## Findings",
6229
+ "",
6230
+ ...plan.findings.map((finding) => [
6231
+ `### ${finding.title}`,
6232
+ "",
6233
+ `- Severity: ${finding.severity}`,
6234
+ `- Evidence: ${finding.evidence}`,
6235
+ `- Recommendation: ${finding.recommendation}`,
6236
+ ""
6237
+ ].join("\n")),
6238
+ "## Extracted Founder Loop Items",
6239
+ "",
6240
+ ...plan.extracted_items.map((item) => `- ${item.type}: ${item.text} (${item.evidenceRef})`),
6241
+ "",
6242
+ "## Recommended Initiative",
6243
+ "",
6244
+ `Title: ${plan.recommended_initiative.title}`,
6245
+ "",
6246
+ plan.recommended_initiative.summary,
6247
+ "",
6248
+ "## Approved Follow-Up Candidate",
6249
+ "",
6250
+ `Title: ${plan.recommended_follow_up.title}`,
6251
+ "",
6252
+ plan.recommended_follow_up.summary,
6253
+ "",
6254
+ `Rollback: ${plan.recommended_follow_up.rollback}`,
6255
+ "",
6256
+ "## Artifact Invariant",
6257
+ "",
6258
+ "```json",
6259
+ JSON.stringify(plan.artifact_invariant, null, 2),
6260
+ "```",
6261
+ ""
6262
+ ];
6263
+ return lines.join("\n");
6264
+ }
6265
+ function parseEntityRef(payload) {
6266
+ const entity = isRecord(payload) && isRecord(payload.data) ? payload.data : payload;
6267
+ if (!isRecord(entity)) {
6268
+ throw new Error("OrgX returned an unexpected entity payload.");
6269
+ }
6270
+ const id = typeof entity.id === "string" ? entity.id : "";
6271
+ const title = typeof entity.title === "string" ? entity.title : typeof entity.name === "string" ? entity.name : "";
6272
+ if (!id || !title) {
6273
+ throw new Error("OrgX returned an incomplete entity payload.");
6274
+ }
6275
+ return { id, title };
6276
+ }
6277
+ async function parseResponseBody5(response) {
6278
+ const text2 = await response.text();
6279
+ if (!text2) return null;
6280
+ try {
6281
+ return JSON.parse(text2);
6282
+ } catch {
6283
+ return text2;
6284
+ }
6285
+ }
6286
+ function formatHttpError4(status, body) {
6287
+ if (typeof body === "string" && body.trim().length > 0) {
6288
+ return `HTTP ${status}: ${body}`;
6289
+ }
6290
+ if (isRecord(body) && typeof body.error === "string" && body.error.trim().length > 0) {
6291
+ return `HTTP ${status}: ${body.error}`;
6292
+ }
6293
+ if (isRecord(body) && isRecord(body.error) && typeof body.error.message === "string") {
6294
+ return `HTTP ${status}: ${body.error.message}`;
6295
+ }
6296
+ return `HTTP ${status}`;
6297
+ }
6298
+ async function createOrgxEntity(body, options) {
6299
+ if (options.dryRun) {
6300
+ return {
6301
+ id: `dry-run-${String(body.type ?? "entity")}`,
6302
+ title: String(body.title ?? body.name ?? "Dry-run entity")
6303
+ };
6304
+ }
6305
+ const auth = await resolveOrgxAuth(options);
6306
+ if (!auth) {
6307
+ throw new Error("No OrgX API key configured. Run `wizard auth login` before using writeback flags.");
6308
+ }
6309
+ const response = await fetch(buildOrgxApiUrl("/entities", auth.baseUrl), {
6310
+ body: JSON.stringify(body),
6311
+ headers: {
6312
+ Authorization: `Bearer ${auth.apiKey}`,
6313
+ "Content-Type": "application/json"
6314
+ },
6315
+ method: "POST",
6316
+ signal: AbortSignal.timeout(15e3)
6317
+ });
6318
+ const responseBody = await parseResponseBody5(response);
6319
+ if (!response.ok) {
6320
+ throw new Error(`Failed to create ${String(body.type ?? "entity")}. ${formatHttpError4(response.status, responseBody)}`);
6321
+ }
6322
+ return parseEntityRef(responseBody);
6323
+ }
6324
+ async function createAuditArtifact(options) {
6325
+ const { initiativeId, markdown, plan } = options;
6326
+ return createOrgxEntity(
6327
+ {
6328
+ artifact_type: "shared.project_handbook",
6329
+ description: "AI-native Founder Loop self-audit generated by @useorgx/wizard audit.",
6330
+ entity_id: initiativeId,
6331
+ entity_type: "initiative",
6332
+ external_url: `orgx-wizard://audit/${plan.artifact_hash}`,
6333
+ initiative_id: initiativeId,
6334
+ metadata: {
6335
+ ...plan.artifact_invariant,
6336
+ artifact_hash: plan.artifact_hash,
6337
+ atomic_unit_type: "ai_native_self_audit",
6338
+ completion_state: "generated",
6339
+ schema_validated: true,
6340
+ scores: plan.scores
6341
+ },
6342
+ name: `AI-Native Self-Audit: ${plan.workspace.name}`,
6343
+ preview_markdown: markdown.slice(0, 8e3),
6344
+ status: "in_review",
6345
+ type: "artifact",
6346
+ workspace_id: plan.workspace.id
6347
+ },
6348
+ options
6349
+ );
6350
+ }
6351
+ async function createInitiativeFromAuditPlan(options) {
6352
+ const { plan } = options;
6353
+ return createOrgxEntity(
6354
+ {
6355
+ metadata: {
6356
+ artifact_hash: plan.artifact_hash,
6357
+ audit_score_snapshot: plan.scores,
6358
+ source: "ai_native_self_audit",
6359
+ source_artifact_type: "ai_native_self_audit_plan"
6360
+ },
6361
+ status: "active",
6362
+ summary: plan.recommended_initiative.summary,
6363
+ title: plan.recommended_initiative.title,
6364
+ type: "initiative",
6365
+ workspace_id: plan.workspace.id
6366
+ },
6367
+ options
6368
+ );
6369
+ }
6370
+ async function createAuditFollowUpTask(options) {
6371
+ const { initiativeId, milestoneId, plan, workstreamId } = options;
6372
+ const resolvedWorkstreamId = workstreamId?.trim() || (await createOrgxEntity(
6373
+ {
6374
+ initiative_id: initiativeId,
6375
+ metadata: {
6376
+ artifact_hash: plan.artifact_hash,
6377
+ source: "ai_native_self_audit"
6378
+ },
6379
+ status: "active",
6380
+ summary: "Follow-up workstream created by @useorgx/wizard audit so the approved action has execution context.",
6381
+ title: "AI-native self-audit follow-up",
6382
+ type: "workstream",
6383
+ workspace_id: plan.workspace.id
6384
+ },
6385
+ options
6386
+ )).id;
6387
+ const resolvedMilestoneId = milestoneId?.trim() || (await createOrgxEntity(
6388
+ {
6389
+ initiative_id: initiativeId,
6390
+ metadata: {
6391
+ artifact_hash: plan.artifact_hash,
6392
+ source: "ai_native_self_audit"
6393
+ },
6394
+ status: "planned",
6395
+ summary: "Milestone created by @useorgx/wizard audit so the approved follow-up task has proof-chain hierarchy.",
6396
+ title: "AI-native self-audit follow-up",
6397
+ type: "milestone",
6398
+ workspace_id: plan.workspace.id,
6399
+ workstream_id: resolvedWorkstreamId
6400
+ },
6401
+ options
6402
+ )).id;
6403
+ return createOrgxEntity(
6404
+ {
6405
+ description: `${plan.recommended_follow_up.summary}
6406
+
6407
+ Rollback: ${plan.recommended_follow_up.rollback}`,
6408
+ initiative_id: initiativeId,
6409
+ milestone_id: resolvedMilestoneId,
6410
+ metadata: {
6411
+ ...plan.artifact_invariant,
6412
+ artifact_hash: plan.artifact_hash,
6413
+ source: "ai_native_self_audit",
6414
+ source_action: "approved_follow_up_writeback"
6415
+ },
6416
+ priority: "high",
6417
+ status: "todo",
6418
+ title: plan.recommended_follow_up.title,
6419
+ type: "task",
6420
+ workstream_id: resolvedWorkstreamId,
6421
+ workspace_id: plan.workspace.id
6422
+ },
6423
+ options
6424
+ );
6425
+ }
6426
+
5928
6427
  // src/spinner.ts
5929
6428
  import ora from "ora";
5930
6429
  import pc2 from "picocolors";
@@ -6025,6 +6524,145 @@ function printPluginMutationReport(report) {
6025
6524
  );
6026
6525
  }
6027
6526
  }
6527
+ function formatScoreLine(scores) {
6528
+ return Object.entries(scores).map(([dimension, score]) => `${dimension}=${score}`).join(" ");
6529
+ }
6530
+ function readAuditInput(options, interactive) {
6531
+ if (options.input?.trim()) {
6532
+ return readFileSync3(resolve(options.input.trim()), "utf8");
6533
+ }
6534
+ if (!process.stdin.isTTY) {
6535
+ return readFileSync3(0, "utf8");
6536
+ }
6537
+ if (!interactive) {
6538
+ throw new Error("Audit input is required. Pass --input <file> or pipe text into wizard audit.");
6539
+ }
6540
+ return textPrompt({
6541
+ message: "Paste a short AI-session summary, decision log, or founder context excerpt",
6542
+ placeholder: "Decision: Founder Loop first. Artifact: proof ledger attached. Next action: ...",
6543
+ validate: (value) => value?.trim().length ? void 0 : "Audit context is required."
6544
+ }).then((value) => {
6545
+ if (clack.isCancel(value) || typeof value !== "string") {
6546
+ clack.cancel("Audit cancelled.");
6547
+ return "";
6548
+ }
6549
+ return value;
6550
+ });
6551
+ }
6552
+ function requireWriteApproval(options, interactive) {
6553
+ const wantsWrite = Boolean(options.createInitiative || options.attachToInitiative || options.writeFollowUp);
6554
+ if (!wantsWrite || options.yes || options.dryRun) return true;
6555
+ if (!interactive) {
6556
+ throw new Error("Write flags require --yes in non-interactive mode.");
6557
+ }
6558
+ return clack.confirm({
6559
+ message: "Approve OrgX writes for this audit run?"
6560
+ }).then((value) => {
6561
+ if (clack.isCancel(value) || value !== true) {
6562
+ clack.cancel("Audit writeback cancelled.");
6563
+ return false;
6564
+ }
6565
+ return true;
6566
+ });
6567
+ }
6568
+ async function resolveAuditWorkspace(options) {
6569
+ const explicitId = options.workspaceId?.trim();
6570
+ const explicitName = options.workspaceName?.trim();
6571
+ if (explicitId || explicitName) {
6572
+ return {
6573
+ id: explicitId || "manual-workspace",
6574
+ name: explicitName || explicitId || "Manual workspace"
6575
+ };
6576
+ }
6577
+ try {
6578
+ const workspace = await getCurrentWorkspace();
6579
+ if (workspace) {
6580
+ return {
6581
+ id: workspace.id,
6582
+ name: workspace.name
6583
+ };
6584
+ }
6585
+ } catch {
6586
+ }
6587
+ return {
6588
+ id: "local-workspace",
6589
+ name: "Local workspace"
6590
+ };
6591
+ }
6592
+ async function runAuditCommand(options) {
6593
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
6594
+ const text2 = (await readAuditInput(options, interactive)).trim();
6595
+ if (!text2) return;
6596
+ const workspace = await resolveAuditWorkspace(options);
6597
+ const plan = buildSelfAuditPlan({
6598
+ connectedSources: [
6599
+ options.sourceLabel?.trim() || "Manual AI-session import",
6600
+ ...workspace.id === "local-workspace" ? [] : ["OrgX workspace"]
6601
+ ],
6602
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
6603
+ imports: [
6604
+ {
6605
+ sourceId: "wizard-audit-input",
6606
+ sourceLabel: options.sourceLabel?.trim() || "Wizard audit input",
6607
+ text: text2
6608
+ }
6609
+ ],
6610
+ missingSources: workspace.id === "local-workspace" ? ["OrgX workspace auth", "automatic AI-session import"] : ["automatic AI-session import"],
6611
+ workspace
6612
+ });
6613
+ const markdown = renderSelfAuditMarkdown(plan);
6614
+ const outputDir = resolve(options.outputDir?.trim() || ".orgx/audits");
6615
+ const timestamp = plan.generated_at.replace(/[:.]/g, "-");
6616
+ const jsonPath = resolve(outputDir, `ai-native-self-audit-${timestamp}.json`);
6617
+ const markdownPath = resolve(outputDir, `ai-native-self-audit-${timestamp}.md`);
6618
+ writeJsonFile(jsonPath, plan);
6619
+ writeTextFile(markdownPath, markdown);
6620
+ if (options.json) {
6621
+ console.log(JSON.stringify({ jsonPath, markdownPath, scores: plan.scores }, null, 2));
6622
+ } else {
6623
+ console.log(` ${ICON.ok} ${pc3.green("audit generated")} ${pc3.dim(markdownPath)}`);
6624
+ console.log(` ${ICON.ok} ${pc3.green("scores ")} ${pc3.dim(formatScoreLine(plan.scores))}`);
6625
+ const belowTarget = plan.self_critique.filter((item) => !item.passed);
6626
+ if (belowTarget.length === 0) {
6627
+ console.log(` ${ICON.ok} ${pc3.green("score gate ")} ${pc3.dim("all dimensions at 95+")}`);
6628
+ } else {
6629
+ console.log(` ${ICON.warn} ${pc3.yellow("score gate ")} ${pc3.dim(`${belowTarget.length} dimension${belowTarget.length === 1 ? "" : "s"} below 95`)}`);
6630
+ }
6631
+ }
6632
+ const approved = await requireWriteApproval(options, interactive);
6633
+ if (!approved) return;
6634
+ let targetInitiativeId = options.attachToInitiative?.trim() || "";
6635
+ if (options.createInitiative) {
6636
+ const initiative = await createInitiativeFromAuditPlan({
6637
+ dryRun: Boolean(options.dryRun),
6638
+ plan
6639
+ });
6640
+ targetInitiativeId = initiative.id;
6641
+ console.log(` ${ICON.ok} ${pc3.green("initiative ")} ${pc3.bold(initiative.title)} ${pc3.dim(initiative.id)}`);
6642
+ }
6643
+ if (targetInitiativeId && (options.attachToInitiative || options.createInitiative)) {
6644
+ const artifact = await createAuditArtifact({
6645
+ dryRun: Boolean(options.dryRun),
6646
+ initiativeId: targetInitiativeId,
6647
+ markdown,
6648
+ plan
6649
+ });
6650
+ console.log(` ${ICON.ok} ${pc3.green("artifact ")} ${pc3.bold(artifact.title)} ${pc3.dim(artifact.id)}`);
6651
+ }
6652
+ if (options.writeFollowUp) {
6653
+ if (!targetInitiativeId) {
6654
+ throw new Error("--write-follow-up requires --attach-to-initiative <id> or --create-initiative.");
6655
+ }
6656
+ const followUp = await createAuditFollowUpTask({
6657
+ dryRun: Boolean(options.dryRun),
6658
+ initiativeId: targetInitiativeId,
6659
+ ...options.milestoneId?.trim() ? { milestoneId: options.milestoneId.trim() } : {},
6660
+ plan,
6661
+ ...options.workstreamId?.trim() ? { workstreamId: options.workstreamId.trim() } : {}
6662
+ });
6663
+ console.log(` ${ICON.ok} ${pc3.green("follow-up ")} ${pc3.bold(followUp.title)} ${pc3.dim(followUp.id)}`);
6664
+ }
6665
+ }
6028
6666
  async function checkPluginStatusesCompact() {
6029
6667
  const spinner = createOrgxSpinner("Checking OrgX companion plugin status");
6030
6668
  spinner.start();
@@ -6323,14 +6961,14 @@ async function readSingleKey() {
6323
6961
  const stdin = process.stdin;
6324
6962
  if (!stdin.isTTY) return null;
6325
6963
  const previousRawMode = stdin.isRaw === true;
6326
- return await new Promise((resolve) => {
6964
+ return await new Promise((resolve2) => {
6327
6965
  const cleanup = (result) => {
6328
6966
  stdin.off("data", onData);
6329
6967
  if (stdin.isTTY) {
6330
6968
  stdin.setRawMode(previousRawMode);
6331
6969
  }
6332
6970
  stdin.pause();
6333
- resolve(result);
6971
+ resolve2(result);
6334
6972
  };
6335
6973
  const onData = (chunk) => {
6336
6974
  const text2 = chunk.toString("utf8");
@@ -6942,7 +7580,7 @@ function printDoctorReport(report, assessment) {
6942
7580
  async function main() {
6943
7581
  const program = new Command();
6944
7582
  program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
6945
- const pkgVersion = true ? "0.1.21" : void 0;
7583
+ const pkgVersion = true ? "0.1.22" : void 0;
6946
7584
  program.version(pkgVersion ?? "unknown", "-V, --version");
6947
7585
  program.hook("preAction", () => {
6948
7586
  console.log(renderBanner(pkgVersion));
@@ -7604,6 +8242,16 @@ async function main() {
7604
8242
  jsonOutput: Boolean(options.json)
7605
8243
  });
7606
8244
  });
8245
+ program.command("audit").description("Run the AI-native Founder Loop self-audit from pasted or file-based AI-session context.").option("--input <path>", "AI-session transcript or summary file; stdin is used when piped").option("--source-label <label>", "label for the imported AI-session 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 audits").option("--output-dir <path>", "directory for generated audit JSON and Markdown", ".orgx/audits").option("--attach-to-initiative <id>", "attach the generated audit artifact to an existing OrgX initiative").option("--create-initiative", "create an OrgX initiative from the generated audit plan").option("--write-follow-up", "create one approval-gated OrgX follow-up task from the audit recommendation").option("--workstream-id <id>", "optional workstream id for the generated follow-up task").option("--milestone-id <id>", "optional milestone id for the generated follow-up task").option("--dry-run", "exercise OrgX write paths without sending writes").option("--yes", "approve OrgX write flags in non-interactive mode").option("--json", "emit a JSON command summary").action(async (options) => {
8246
+ await safeTrackWizardTelemetry("audit_started", {
8247
+ attach_to_initiative: Boolean(options.attachToInitiative),
8248
+ command: "audit",
8249
+ create_initiative: Boolean(options.createInitiative),
8250
+ dry_run: Boolean(options.dryRun),
8251
+ write_follow_up: Boolean(options.writeFollowUp)
8252
+ });
8253
+ await runAuditCommand(options);
8254
+ });
7607
8255
  program.command("doctor").description("Verify local OrgX surface config and optional remote setup status.").action(async () => {
7608
8256
  const spinner = createOrgxSpinner("Running OrgX health check");
7609
8257
  spinner.start();