@useorgx/wizard 0.1.21 → 0.1.23
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 +877 -13
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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 readFileSync4 } 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
|
|
|
@@ -79,6 +81,8 @@ var CURSOR_DIR = join(HOME, ".cursor");
|
|
|
79
81
|
var CODEX_DIR = join(HOME, ".codex");
|
|
80
82
|
var OPENCLAW_DIR = join(HOME, ".openclaw");
|
|
81
83
|
var AGENTS_DIR = join(HOME, ".agents");
|
|
84
|
+
var CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, "projects");
|
|
85
|
+
var CODEX_SESSIONS_DIR = join(CODEX_DIR, "sessions");
|
|
82
86
|
var CLAUDE_SKILLS_DIR = join(CLAUDE_DIR, "skills");
|
|
83
87
|
var CLAUDE_ORGX_SKILL_DIR = join(CLAUDE_SKILLS_DIR, "orgx");
|
|
84
88
|
var CLAUDE_ORGX_SKILL_PATH = join(CLAUDE_ORGX_SKILL_DIR, "SKILL.md");
|
|
@@ -791,7 +795,7 @@ function parsePairingPollResult(value) {
|
|
|
791
795
|
};
|
|
792
796
|
}
|
|
793
797
|
function sleep(ms) {
|
|
794
|
-
return new Promise((
|
|
798
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
795
799
|
}
|
|
796
800
|
async function startBrowserPairing(options, fetchImpl) {
|
|
797
801
|
const data = await fetchJson({
|
|
@@ -904,12 +908,12 @@ h1{font-size:1.5rem;color:#b91c1c}p{color:#555;margin-top:.5rem}</style>
|
|
|
904
908
|
<p>Return to your terminal and try again.</p>
|
|
905
909
|
</div></body></html>`;
|
|
906
910
|
function tryListen(port, hostname2) {
|
|
907
|
-
return new Promise((
|
|
911
|
+
return new Promise((resolve2, reject) => {
|
|
908
912
|
const server = createServer();
|
|
909
913
|
server.once("error", reject);
|
|
910
914
|
server.listen(port, hostname2, () => {
|
|
911
915
|
server.removeListener("error", reject);
|
|
912
|
-
|
|
916
|
+
resolve2(server);
|
|
913
917
|
});
|
|
914
918
|
});
|
|
915
919
|
}
|
|
@@ -938,7 +942,7 @@ async function startLocalAuthServer(options) {
|
|
|
938
942
|
const successHtml = options.successHtml ?? DEFAULT_SUCCESS_HTML;
|
|
939
943
|
const errorHtml = options.errorHtml ?? DEFAULT_ERROR_HTML;
|
|
940
944
|
const { server, port } = await bindServer(options.preferredPort, hostname2);
|
|
941
|
-
const result = new Promise((
|
|
945
|
+
const result = new Promise((resolve2, reject) => {
|
|
942
946
|
const timer = setTimeout(() => {
|
|
943
947
|
server.close();
|
|
944
948
|
reject(new Error("Timed out waiting for browser authorization."));
|
|
@@ -981,7 +985,7 @@ async function startLocalAuthServer(options) {
|
|
|
981
985
|
res.writeHead(200, { "Content-Type": "text/html" }).end(successHtml);
|
|
982
986
|
clearTimeout(timer);
|
|
983
987
|
server.close();
|
|
984
|
-
|
|
988
|
+
resolve2({ code, state });
|
|
985
989
|
});
|
|
986
990
|
});
|
|
987
991
|
return { port, result };
|
|
@@ -4100,8 +4104,8 @@ function encodeRepoPath2(value) {
|
|
|
4100
4104
|
return value.split("/").filter((segment) => segment.length > 0).map((segment) => encodeURIComponent(segment)).join("/");
|
|
4101
4105
|
}
|
|
4102
4106
|
function isLikelyRepoFilePath(path) {
|
|
4103
|
-
const
|
|
4104
|
-
return
|
|
4107
|
+
const basename3 = path.split("/").pop() ?? path;
|
|
4108
|
+
return basename3.includes(".") && !/^\.[^./]+$/.test(basename3);
|
|
4105
4109
|
}
|
|
4106
4110
|
function buildContentsUrl2(spec, path) {
|
|
4107
4111
|
const encodedPath = encodeRepoPath2(path);
|
|
@@ -4435,7 +4439,7 @@ function formatCommandFailure(command, args, result) {
|
|
|
4435
4439
|
return `${command} ${args.join(" ")} failed${result.exitCode >= 0 ? ` with exit code ${result.exitCode}` : ""}${detail ? `: ${detail}` : "."}`;
|
|
4436
4440
|
}
|
|
4437
4441
|
async function defaultCommandRunner(command, args) {
|
|
4438
|
-
return await new Promise((
|
|
4442
|
+
return await new Promise((resolve2) => {
|
|
4439
4443
|
const child = spawn(command, [...args], {
|
|
4440
4444
|
env: process.env,
|
|
4441
4445
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -4450,7 +4454,7 @@ async function defaultCommandRunner(command, args) {
|
|
|
4450
4454
|
});
|
|
4451
4455
|
child.on("error", (error) => {
|
|
4452
4456
|
const errorCode = typeof error === "object" && error && "code" in error ? String(error.code) : void 0;
|
|
4453
|
-
|
|
4457
|
+
resolve2({
|
|
4454
4458
|
exitCode: -1,
|
|
4455
4459
|
stdout,
|
|
4456
4460
|
stderr,
|
|
@@ -4458,7 +4462,7 @@ async function defaultCommandRunner(command, args) {
|
|
|
4458
4462
|
});
|
|
4459
4463
|
});
|
|
4460
4464
|
child.on("close", (code) => {
|
|
4461
|
-
|
|
4465
|
+
resolve2({
|
|
4462
4466
|
exitCode: code ?? -1,
|
|
4463
4467
|
stdout,
|
|
4464
4468
|
stderr
|
|
@@ -5925,6 +5929,674 @@ async function fetchOnboardingState(auth) {
|
|
|
5925
5929
|
}
|
|
5926
5930
|
}
|
|
5927
5931
|
|
|
5932
|
+
// src/lib/ai-session-import.ts
|
|
5933
|
+
import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
|
|
5934
|
+
import { basename as basename2, join as join4, relative as relative2 } from "path";
|
|
5935
|
+
var AI_SESSION_SOURCES = ["codex", "claude"];
|
|
5936
|
+
var DEFAULT_LIMIT_PER_SOURCE = 3;
|
|
5937
|
+
var DEFAULT_SINCE_DAYS = 30;
|
|
5938
|
+
var DEFAULT_MAX_BYTES_PER_FILE = 1e6;
|
|
5939
|
+
var AUDIT_RELEVANT_LINE_PATTERN = /\b(decision|decided|artifact|receipt|proof|commitment|committed|next action|follow[- ]?up|outcome|result|impact|roi|economics|token|cost|saved|open loop|gap|blocker|risk|owner|dri|writeback|rollback|quality score)\b/i;
|
|
5940
|
+
function parseAiSessionSources(value) {
|
|
5941
|
+
if (!value?.trim()) return [];
|
|
5942
|
+
const requested = value.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean);
|
|
5943
|
+
const expanded = requested.includes("all") ? [...AI_SESSION_SOURCES] : requested;
|
|
5944
|
+
const deduped = [...new Set(expanded)];
|
|
5945
|
+
const invalid = deduped.filter((source) => !AI_SESSION_SOURCES.includes(source));
|
|
5946
|
+
if (invalid.length > 0) {
|
|
5947
|
+
throw new Error(`Unsupported AI-session source: ${invalid.join(", ")}. Use codex, claude, or all.`);
|
|
5948
|
+
}
|
|
5949
|
+
return deduped;
|
|
5950
|
+
}
|
|
5951
|
+
function parseJsonLine(line) {
|
|
5952
|
+
try {
|
|
5953
|
+
return JSON.parse(line);
|
|
5954
|
+
} catch {
|
|
5955
|
+
return null;
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5958
|
+
function asText(value) {
|
|
5959
|
+
if (typeof value === "string") return value;
|
|
5960
|
+
if (Array.isArray(value)) {
|
|
5961
|
+
return value.map((item) => {
|
|
5962
|
+
if (typeof item === "string") return item;
|
|
5963
|
+
if (!isRecord(item)) return "";
|
|
5964
|
+
if (typeof item.text === "string") return item.text;
|
|
5965
|
+
if (typeof item.content === "string") return item.content;
|
|
5966
|
+
return "";
|
|
5967
|
+
}).filter(Boolean).join("\n");
|
|
5968
|
+
}
|
|
5969
|
+
if (isRecord(value) && typeof value.text === "string") return value.text;
|
|
5970
|
+
return "";
|
|
5971
|
+
}
|
|
5972
|
+
function extractCodexMessageText(record) {
|
|
5973
|
+
if (!isRecord(record) || record.type !== "response_item" || !isRecord(record.payload)) {
|
|
5974
|
+
return "";
|
|
5975
|
+
}
|
|
5976
|
+
const payload = record.payload;
|
|
5977
|
+
if (payload.type !== "message" || payload.role !== "user" && payload.role !== "assistant") {
|
|
5978
|
+
return "";
|
|
5979
|
+
}
|
|
5980
|
+
return asText(payload.content);
|
|
5981
|
+
}
|
|
5982
|
+
function extractClaudeMessageText(record) {
|
|
5983
|
+
if (!isRecord(record) || record.isMeta === true || !isRecord(record.message)) {
|
|
5984
|
+
return "";
|
|
5985
|
+
}
|
|
5986
|
+
const message = record.message;
|
|
5987
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
5988
|
+
return "";
|
|
5989
|
+
}
|
|
5990
|
+
const text2 = asText(message.content);
|
|
5991
|
+
if (/^<local-command-caveat>/i.test(text2.trim())) return "";
|
|
5992
|
+
return text2;
|
|
5993
|
+
}
|
|
5994
|
+
function keepAuditRelevantLines(text2) {
|
|
5995
|
+
return text2.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && AUDIT_RELEVANT_LINE_PATTERN.test(line));
|
|
5996
|
+
}
|
|
5997
|
+
function collectJsonlFiles(root, source) {
|
|
5998
|
+
if (!existsSync5(root)) return [];
|
|
5999
|
+
const files = [];
|
|
6000
|
+
const stack = [root];
|
|
6001
|
+
while (stack.length > 0) {
|
|
6002
|
+
const current = stack.pop();
|
|
6003
|
+
if (!current) continue;
|
|
6004
|
+
let entries;
|
|
6005
|
+
try {
|
|
6006
|
+
entries = readdirSync3(current);
|
|
6007
|
+
} catch {
|
|
6008
|
+
continue;
|
|
6009
|
+
}
|
|
6010
|
+
for (const entry of entries) {
|
|
6011
|
+
const path = join4(current, entry);
|
|
6012
|
+
let stats;
|
|
6013
|
+
try {
|
|
6014
|
+
stats = statSync3(path);
|
|
6015
|
+
} catch {
|
|
6016
|
+
continue;
|
|
6017
|
+
}
|
|
6018
|
+
if (stats.isDirectory()) {
|
|
6019
|
+
stack.push(path);
|
|
6020
|
+
continue;
|
|
6021
|
+
}
|
|
6022
|
+
if (stats.isFile() && path.endsWith(".jsonl")) {
|
|
6023
|
+
files.push({ mtimeMs: stats.mtimeMs, path, source });
|
|
6024
|
+
}
|
|
6025
|
+
}
|
|
6026
|
+
}
|
|
6027
|
+
return files;
|
|
6028
|
+
}
|
|
6029
|
+
function readSessionImport(candidate, root, options) {
|
|
6030
|
+
let stats;
|
|
6031
|
+
try {
|
|
6032
|
+
stats = statSync3(candidate.path);
|
|
6033
|
+
} catch {
|
|
6034
|
+
return null;
|
|
6035
|
+
}
|
|
6036
|
+
if (stats.size > options.maxBytesPerFile) return null;
|
|
6037
|
+
const extractor = candidate.source === "codex" ? extractCodexMessageText : extractClaudeMessageText;
|
|
6038
|
+
const lines = readFileSync3(candidate.path, "utf8").split(/\r?\n/);
|
|
6039
|
+
const relevantLines = [];
|
|
6040
|
+
for (const line of lines) {
|
|
6041
|
+
const record = parseJsonLine(line);
|
|
6042
|
+
const text2 = extractor(record);
|
|
6043
|
+
if (!text2) continue;
|
|
6044
|
+
relevantLines.push(...keepAuditRelevantLines(text2));
|
|
6045
|
+
}
|
|
6046
|
+
const deduped = [...new Set(relevantLines)].slice(0, 80);
|
|
6047
|
+
if (deduped.length === 0) return null;
|
|
6048
|
+
const relativePath = relative2(root, candidate.path);
|
|
6049
|
+
return {
|
|
6050
|
+
sourceId: `${candidate.source}:${basename2(candidate.path, ".jsonl")}`,
|
|
6051
|
+
sourceLabel: `${candidate.source === "codex" ? "Codex" : "Claude"} session ${relativePath}`,
|
|
6052
|
+
text: deduped.join("\n")
|
|
6053
|
+
};
|
|
6054
|
+
}
|
|
6055
|
+
function loadAiSessionImports(options) {
|
|
6056
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
6057
|
+
const sinceMs = now.getTime() - (options.sinceDays ?? DEFAULT_SINCE_DAYS) * 24 * 60 * 60 * 1e3;
|
|
6058
|
+
const limitPerSource = Math.max(1, options.limitPerSource ?? DEFAULT_LIMIT_PER_SOURCE);
|
|
6059
|
+
const maxBytesPerFile = Math.max(1, options.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE);
|
|
6060
|
+
const roots = {
|
|
6061
|
+
claude: options.claudeProjectsDir ?? CLAUDE_PROJECTS_DIR,
|
|
6062
|
+
codex: options.codexSessionsDir ?? CODEX_SESSIONS_DIR
|
|
6063
|
+
};
|
|
6064
|
+
const imports = [];
|
|
6065
|
+
const connectedSources = [];
|
|
6066
|
+
const missingSources = [];
|
|
6067
|
+
let scannedFiles = 0;
|
|
6068
|
+
let skippedFiles = 0;
|
|
6069
|
+
for (const source of options.sources) {
|
|
6070
|
+
const root = roots[source];
|
|
6071
|
+
const candidates = collectJsonlFiles(root, source).filter((file) => file.mtimeMs >= sinceMs).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
6072
|
+
if (candidates.length === 0) {
|
|
6073
|
+
missingSources.push(`${source} session store`);
|
|
6074
|
+
continue;
|
|
6075
|
+
}
|
|
6076
|
+
let importedForSource = 0;
|
|
6077
|
+
for (const candidate of candidates) {
|
|
6078
|
+
if (importedForSource >= limitPerSource) break;
|
|
6079
|
+
scannedFiles += 1;
|
|
6080
|
+
const imported = readSessionImport(candidate, root, { maxBytesPerFile });
|
|
6081
|
+
if (!imported) {
|
|
6082
|
+
skippedFiles += 1;
|
|
6083
|
+
continue;
|
|
6084
|
+
}
|
|
6085
|
+
imports.push(imported);
|
|
6086
|
+
importedForSource += 1;
|
|
6087
|
+
}
|
|
6088
|
+
if (importedForSource > 0) {
|
|
6089
|
+
connectedSources.push(`${source === "codex" ? "Codex" : "Claude"} local sessions`);
|
|
6090
|
+
} else {
|
|
6091
|
+
missingSources.push(`${source} audit-relevant session lines`);
|
|
6092
|
+
}
|
|
6093
|
+
}
|
|
6094
|
+
return {
|
|
6095
|
+
connectedSources,
|
|
6096
|
+
imports,
|
|
6097
|
+
missingSources,
|
|
6098
|
+
scannedFiles,
|
|
6099
|
+
skippedFiles
|
|
6100
|
+
};
|
|
6101
|
+
}
|
|
6102
|
+
|
|
6103
|
+
// src/lib/self-audit.ts
|
|
6104
|
+
import { createHash as createHash3 } from "crypto";
|
|
6105
|
+
var SELF_AUDIT_SCHEMA_VERSION = "2026-04-27";
|
|
6106
|
+
var AUDIT_DIMENSIONS = [
|
|
6107
|
+
"queryability",
|
|
6108
|
+
"proof_density",
|
|
6109
|
+
"loop_closure",
|
|
6110
|
+
"context_debt",
|
|
6111
|
+
"autonomy_readiness",
|
|
6112
|
+
"roi_visibility"
|
|
6113
|
+
];
|
|
6114
|
+
function clampScore(value) {
|
|
6115
|
+
return Math.max(0, Math.min(100, Math.round(value)));
|
|
6116
|
+
}
|
|
6117
|
+
function ratio(numerator, denominator, fallback = 0) {
|
|
6118
|
+
if (denominator <= 0) return fallback;
|
|
6119
|
+
return numerator / denominator;
|
|
6120
|
+
}
|
|
6121
|
+
function includesAny(value, patterns) {
|
|
6122
|
+
return patterns.some((pattern) => pattern.test(value));
|
|
6123
|
+
}
|
|
6124
|
+
function classifyLine(line) {
|
|
6125
|
+
const normalized = line.trim();
|
|
6126
|
+
if (!normalized) return null;
|
|
6127
|
+
if (/^(decision|decided|we decided|d:)\b/i.test(normalized)) return "decision";
|
|
6128
|
+
if (/^(commitment|committed|promise|promised|todo:|we will)\b/i.test(normalized)) return "commitment";
|
|
6129
|
+
if (/^(artifact|receipt|proof|shipped|implemented|commit|pr:)\b/i.test(normalized)) return "artifact";
|
|
6130
|
+
if (/^(open loop|gap|blocker|risk|missing|needs|unresolved)\b/i.test(normalized)) return "open_loop";
|
|
6131
|
+
if (/^(next action|follow[- ]?up|next step|action:)\b/i.test(normalized)) return "next_action";
|
|
6132
|
+
if (/^(outcome|result|impact|metric|adoption)\b/i.test(normalized)) return "outcome";
|
|
6133
|
+
if (/^(roi|economics|token|tokens|cost|saved|time saved|api bill)\b/i.test(normalized)) return "economics";
|
|
6134
|
+
return null;
|
|
6135
|
+
}
|
|
6136
|
+
function extractFounderLoopItems(imports) {
|
|
6137
|
+
const items = [];
|
|
6138
|
+
for (const source of imports) {
|
|
6139
|
+
const lines = source.text.split(/\r?\n/);
|
|
6140
|
+
lines.forEach((line, index) => {
|
|
6141
|
+
const type = classifyLine(line);
|
|
6142
|
+
if (!type) return;
|
|
6143
|
+
const lineNumber = index + 1;
|
|
6144
|
+
items.push({
|
|
6145
|
+
evidenceRef: `${source.sourceId}:L${lineNumber}`,
|
|
6146
|
+
lineNumber,
|
|
6147
|
+
sourceId: source.sourceId,
|
|
6148
|
+
sourceLabel: source.sourceLabel,
|
|
6149
|
+
text: line.trim(),
|
|
6150
|
+
type
|
|
6151
|
+
});
|
|
6152
|
+
});
|
|
6153
|
+
}
|
|
6154
|
+
return items;
|
|
6155
|
+
}
|
|
6156
|
+
function buildSelfAuditSignals(imports, items, options = {}) {
|
|
6157
|
+
const allText = imports.map((source) => source.text).join("\n");
|
|
6158
|
+
const lower = allText.toLowerCase();
|
|
6159
|
+
const decisions = items.filter((item) => item.type === "decision");
|
|
6160
|
+
const artifacts = items.filter((item) => item.type === "artifact");
|
|
6161
|
+
const commitments = items.filter((item) => item.type === "commitment");
|
|
6162
|
+
const nextActions = items.filter((item) => item.type === "next_action");
|
|
6163
|
+
const outcomes = items.filter((item) => item.type === "outcome");
|
|
6164
|
+
const economics = items.filter((item) => item.type === "economics");
|
|
6165
|
+
const proofMentions = (lower.match(/\b(proof|verified|verification|receipt|quality score|artifact)\b/g) ?? []).length;
|
|
6166
|
+
const ownerMentions = (lower.match(/\b(owner|dri|responsible|agent:|founder)\b/g) ?? []).length;
|
|
6167
|
+
const artifactNextActionMentions = artifacts.filter(
|
|
6168
|
+
(item) => includesAny(item.text.toLowerCase(), [/\bnext action\b/, /\bfollow[- ]?up\b/, /\brollback\b/])
|
|
6169
|
+
).length;
|
|
6170
|
+
const writebackMentions = (lower.match(/\b(approve|approved|writeback|rollback|create task|follow-up task)\b/g) ?? []).length;
|
|
6171
|
+
const repeatedContextPrompts = (lower.match(/\b(recap|catch you up|context again|restate|reread|remind me)\b/g) ?? []).length;
|
|
6172
|
+
return {
|
|
6173
|
+
approvedWritebackTargets: Math.min(3, writebackMentions),
|
|
6174
|
+
artifactsWithNextActions: Math.min(artifacts.length, nextActions.length + artifactNextActionMentions),
|
|
6175
|
+
artifactsWithOwners: Math.min(artifacts.length, ownerMentions),
|
|
6176
|
+
completedWorkItems: artifacts.length,
|
|
6177
|
+
completedWorkWithProof: Math.min(artifacts.length, proofMentions),
|
|
6178
|
+
connectedSources: Math.max(options.connectedSources?.length ?? 0, imports.length),
|
|
6179
|
+
decisionsWithEvidence: decisions.length,
|
|
6180
|
+
economicSignals: economics.length + (lower.includes("token") || lower.includes("cost") || lower.includes("saved") ? 1 : 0),
|
|
6181
|
+
missingSources: options.missingSources?.length ?? 0,
|
|
6182
|
+
openLoops: items.filter((item) => item.type === "open_loop").length,
|
|
6183
|
+
outcomeLinkedItems: outcomes.length,
|
|
6184
|
+
repeatedContextPrompts,
|
|
6185
|
+
totalArtifacts: artifacts.length,
|
|
6186
|
+
totalContextItems: Math.max(items.length, allText.split(/\s+/).filter(Boolean).length),
|
|
6187
|
+
totalDecisions: decisions.length,
|
|
6188
|
+
unresolvedCommitments: Math.max(0, commitments.length - nextActions.length - outcomes.length)
|
|
6189
|
+
};
|
|
6190
|
+
}
|
|
6191
|
+
function scoreSelfAudit(signals) {
|
|
6192
|
+
const queryability = clampScore(
|
|
6193
|
+
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)
|
|
6194
|
+
);
|
|
6195
|
+
const proofDensity = clampScore(
|
|
6196
|
+
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
|
|
6197
|
+
);
|
|
6198
|
+
const loopClosure = clampScore(
|
|
6199
|
+
40 + Math.min(25, signals.outcomeLinkedItems * 25) + Math.min(35, signals.approvedWritebackTargets * 20) + (signals.openLoops === 0 ? 15 : Math.max(0, 15 - signals.openLoops * 3))
|
|
6200
|
+
);
|
|
6201
|
+
const contextDebt = clampScore(
|
|
6202
|
+
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)
|
|
6203
|
+
);
|
|
6204
|
+
const autonomyReadiness = clampScore(
|
|
6205
|
+
35 + Math.min(30, signals.approvedWritebackTargets * 15) + Math.min(20, signals.completedWorkWithProof * 5) + (signals.openLoops <= 1 ? 15 : 5)
|
|
6206
|
+
);
|
|
6207
|
+
const roiVisibility = clampScore(
|
|
6208
|
+
30 + Math.min(40, signals.economicSignals * 18) + Math.min(25, signals.outcomeLinkedItems * 25) + Math.min(10, signals.completedWorkWithProof * 3)
|
|
6209
|
+
);
|
|
6210
|
+
return {
|
|
6211
|
+
autonomy_readiness: autonomyReadiness,
|
|
6212
|
+
context_debt: contextDebt,
|
|
6213
|
+
loop_closure: loopClosure,
|
|
6214
|
+
proof_density: proofDensity,
|
|
6215
|
+
queryability,
|
|
6216
|
+
roi_visibility: roiVisibility
|
|
6217
|
+
};
|
|
6218
|
+
}
|
|
6219
|
+
function buildFindings(scores, signals) {
|
|
6220
|
+
const findings = [];
|
|
6221
|
+
for (const dimension of AUDIT_DIMENSIONS) {
|
|
6222
|
+
const score = scores[dimension];
|
|
6223
|
+
if (score >= 95) {
|
|
6224
|
+
findings.push({
|
|
6225
|
+
dimension,
|
|
6226
|
+
evidence: `Score ${score}/100 meets the Phase 2 target.`,
|
|
6227
|
+
recommendation: "Keep this dimension gated by evidence so the score stays earned.",
|
|
6228
|
+
severity: "info",
|
|
6229
|
+
title: `${dimension.replace(/_/g, " ")} is at the 95+ target`
|
|
6230
|
+
});
|
|
6231
|
+
continue;
|
|
6232
|
+
}
|
|
6233
|
+
const recommendationByDimension = {
|
|
6234
|
+
autonomy_readiness: "Keep writeback approval-gated and add rollback references to every generated action.",
|
|
6235
|
+
context_debt: "Reduce repeated context prompts and close unresolved open loops with task or decision artifacts.",
|
|
6236
|
+
loop_closure: "Add outcome references and approved follow-up writebacks so planning changes after execution.",
|
|
6237
|
+
proof_density: "Attach owners, next actions, and verification proof to every completed work artifact.",
|
|
6238
|
+
queryability: "Add cited decisions, artifacts, connected sources, and retrieval scope to the audit output.",
|
|
6239
|
+
roi_visibility: "Add token/time/cost evidence plus an outcome review so ROI is not a narrative claim."
|
|
6240
|
+
};
|
|
6241
|
+
findings.push({
|
|
6242
|
+
dimension,
|
|
6243
|
+
evidence: `Score ${score}/100. Signals: ${JSON.stringify({
|
|
6244
|
+
approvedWritebackTargets: signals.approvedWritebackTargets,
|
|
6245
|
+
completedWorkWithProof: signals.completedWorkWithProof,
|
|
6246
|
+
economicSignals: signals.economicSignals,
|
|
6247
|
+
openLoops: signals.openLoops,
|
|
6248
|
+
outcomeLinkedItems: signals.outcomeLinkedItems,
|
|
6249
|
+
repeatedContextPrompts: signals.repeatedContextPrompts
|
|
6250
|
+
})}`,
|
|
6251
|
+
recommendation: recommendationByDimension[dimension],
|
|
6252
|
+
severity: score < 60 ? "critical" : "warning",
|
|
6253
|
+
title: `${dimension.replace(/_/g, " ")} needs evidence before it can be called 95+`
|
|
6254
|
+
});
|
|
6255
|
+
}
|
|
6256
|
+
return findings;
|
|
6257
|
+
}
|
|
6258
|
+
function buildSelfCritique(scores) {
|
|
6259
|
+
return AUDIT_DIMENSIONS.map((dimension) => {
|
|
6260
|
+
const score = scores[dimension];
|
|
6261
|
+
return {
|
|
6262
|
+
dimension,
|
|
6263
|
+
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+.`,
|
|
6264
|
+
passed: score >= 95,
|
|
6265
|
+
score,
|
|
6266
|
+
target: 95
|
|
6267
|
+
};
|
|
6268
|
+
});
|
|
6269
|
+
}
|
|
6270
|
+
function hashPlanPayload(payload) {
|
|
6271
|
+
return createHash3("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
6272
|
+
}
|
|
6273
|
+
function buildSelfAuditPlan(input) {
|
|
6274
|
+
if (input.imports.length === 0) {
|
|
6275
|
+
throw new Error("At least one AI-session import is required to run the Founder Loop audit.");
|
|
6276
|
+
}
|
|
6277
|
+
const items = extractFounderLoopItems(input.imports);
|
|
6278
|
+
const connectedSources = input.connectedSources ?? input.imports.map((source) => source.sourceLabel);
|
|
6279
|
+
const missingSources = input.missingSources ?? [];
|
|
6280
|
+
const signals = buildSelfAuditSignals(input.imports, items, {
|
|
6281
|
+
connectedSources,
|
|
6282
|
+
missingSources
|
|
6283
|
+
});
|
|
6284
|
+
const scores = scoreSelfAudit(signals);
|
|
6285
|
+
const evidenceRefs = items.slice(0, 12).map((item) => item.evidenceRef);
|
|
6286
|
+
const decisions = items.filter((item) => item.type === "decision");
|
|
6287
|
+
const nextAction = items.find((item) => item.type === "next_action");
|
|
6288
|
+
const basePlan = {
|
|
6289
|
+
artifact_type: "ai_native_self_audit_plan",
|
|
6290
|
+
audit_scope: {
|
|
6291
|
+
connected_sources: connectedSources,
|
|
6292
|
+
loop: "founder",
|
|
6293
|
+
missing_sources: missingSources,
|
|
6294
|
+
time_window_days: input.timeWindowDays ?? 30
|
|
6295
|
+
},
|
|
6296
|
+
extracted_items: items,
|
|
6297
|
+
findings: buildFindings(scores, signals),
|
|
6298
|
+
generated_at: input.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
6299
|
+
recommended_follow_up: {
|
|
6300
|
+
rollback: "Delete or close the generated OrgX follow-up task if the founder rejects the audit recommendation.",
|
|
6301
|
+
summary: nextAction?.text ?? "Review the audit findings, approve one follow-up action, and attach proof after execution.",
|
|
6302
|
+
title: "Review AI-native self-audit findings and approve first follow-up"
|
|
6303
|
+
},
|
|
6304
|
+
recommended_initiative: {
|
|
6305
|
+
summary: "Generated by @useorgx/wizard audit to close the first Founder Loop from AI-session context, proof artifacts, approved writeback, and outcome review.",
|
|
6306
|
+
title: `Close Founder Loop: ${input.workspace.name} AI-native operating loop`,
|
|
6307
|
+
workstreams: [
|
|
6308
|
+
{
|
|
6309
|
+
purpose: "Capture AI-session context, decisions, commitments, and open loops.",
|
|
6310
|
+
tasks: [
|
|
6311
|
+
{
|
|
6312
|
+
proof_requirement: "AI-session import with cited evidence references.",
|
|
6313
|
+
title: "Import founder AI-session context"
|
|
6314
|
+
}
|
|
6315
|
+
],
|
|
6316
|
+
title: "Founder Context Ingest"
|
|
6317
|
+
},
|
|
6318
|
+
{
|
|
6319
|
+
purpose: "Turn completed work into artifacts with owners, proof, and next actions.",
|
|
6320
|
+
tasks: [
|
|
6321
|
+
{
|
|
6322
|
+
proof_requirement: "Artifact metadata includes owner, evidence refs, and retrieval scope.",
|
|
6323
|
+
title: "Attach proof artifacts to completed work"
|
|
6324
|
+
}
|
|
6325
|
+
],
|
|
6326
|
+
title: "Proof Chain"
|
|
6327
|
+
},
|
|
6328
|
+
{
|
|
6329
|
+
purpose: "Write one approved follow-up action into OrgX with rollback context.",
|
|
6330
|
+
tasks: [
|
|
6331
|
+
{
|
|
6332
|
+
proof_requirement: "Approved OrgX task with rollback and evidence references.",
|
|
6333
|
+
title: "Approve first OrgX follow-up writeback"
|
|
6334
|
+
}
|
|
6335
|
+
],
|
|
6336
|
+
title: "Safe Writeback"
|
|
6337
|
+
},
|
|
6338
|
+
{
|
|
6339
|
+
purpose: "Record outcome and economics so the next plan learns from execution.",
|
|
6340
|
+
tasks: [
|
|
6341
|
+
{
|
|
6342
|
+
proof_requirement: "Founder review with time/token/value estimate and attribution confidence.",
|
|
6343
|
+
title: "Record outcome and economics review"
|
|
6344
|
+
}
|
|
6345
|
+
],
|
|
6346
|
+
title: "Outcome Review"
|
|
6347
|
+
}
|
|
6348
|
+
]
|
|
6349
|
+
},
|
|
6350
|
+
safe_writeback_plan: [
|
|
6351
|
+
{
|
|
6352
|
+
action: "create_follow_up_task",
|
|
6353
|
+
approval: "required",
|
|
6354
|
+
rollback: "Delete or close the generated task and preserve the audit artifact as a rejected recommendation.",
|
|
6355
|
+
target: "orgx"
|
|
6356
|
+
}
|
|
6357
|
+
],
|
|
6358
|
+
schema_version: SELF_AUDIT_SCHEMA_VERSION,
|
|
6359
|
+
scores,
|
|
6360
|
+
self_critique: buildSelfCritique(scores),
|
|
6361
|
+
signals,
|
|
6362
|
+
workspace: input.workspace
|
|
6363
|
+
};
|
|
6364
|
+
const invariant = {
|
|
6365
|
+
decision_refs: decisions.map((item) => item.evidenceRef),
|
|
6366
|
+
evidence_refs: evidenceRefs,
|
|
6367
|
+
goal_ref: `workspace:${input.workspace.id}:ai-native-self-audit`,
|
|
6368
|
+
next_action_ref: nextAction?.evidenceRef ?? "manual-next-action:review-audit",
|
|
6369
|
+
owner_ref: "founder:dri",
|
|
6370
|
+
proof_requirement: "verification",
|
|
6371
|
+
retrieval_scope: "Retrieve the imported AI-session context, extracted Founder Loop items, audit scores, findings, writeback plan, and outcome review."
|
|
6372
|
+
};
|
|
6373
|
+
const artifactHash = hashPlanPayload({ ...basePlan, artifact_invariant: invariant });
|
|
6374
|
+
return {
|
|
6375
|
+
...basePlan,
|
|
6376
|
+
artifact_hash: artifactHash,
|
|
6377
|
+
artifact_invariant: invariant
|
|
6378
|
+
};
|
|
6379
|
+
}
|
|
6380
|
+
function renderSelfAuditMarkdown(plan) {
|
|
6381
|
+
const lines = [
|
|
6382
|
+
"# AI-Native Founder Loop Self-Audit",
|
|
6383
|
+
"",
|
|
6384
|
+
`Generated: ${plan.generated_at}`,
|
|
6385
|
+
`Workspace: ${plan.workspace.name} (${plan.workspace.id})`,
|
|
6386
|
+
`Artifact hash: ${plan.artifact_hash}`,
|
|
6387
|
+
"",
|
|
6388
|
+
"## Scores",
|
|
6389
|
+
"",
|
|
6390
|
+
"| Dimension | Score | Target | Status |",
|
|
6391
|
+
"| --- | ---: | ---: | --- |",
|
|
6392
|
+
...AUDIT_DIMENSIONS.map((dimension) => {
|
|
6393
|
+
const score = plan.scores[dimension];
|
|
6394
|
+
return `| ${dimension.replace(/_/g, " ")} | ${score} | 95 | ${score >= 95 ? "pass" : "gap"} |`;
|
|
6395
|
+
}),
|
|
6396
|
+
"",
|
|
6397
|
+
"## Self-Critique",
|
|
6398
|
+
"",
|
|
6399
|
+
...plan.self_critique.map((item) => `- ${item.dimension}: ${item.gap}`),
|
|
6400
|
+
"",
|
|
6401
|
+
"## Findings",
|
|
6402
|
+
"",
|
|
6403
|
+
...plan.findings.map((finding) => [
|
|
6404
|
+
`### ${finding.title}`,
|
|
6405
|
+
"",
|
|
6406
|
+
`- Severity: ${finding.severity}`,
|
|
6407
|
+
`- Evidence: ${finding.evidence}`,
|
|
6408
|
+
`- Recommendation: ${finding.recommendation}`,
|
|
6409
|
+
""
|
|
6410
|
+
].join("\n")),
|
|
6411
|
+
"## Extracted Founder Loop Items",
|
|
6412
|
+
"",
|
|
6413
|
+
...plan.extracted_items.map((item) => `- ${item.type}: ${item.text} (${item.evidenceRef})`),
|
|
6414
|
+
"",
|
|
6415
|
+
"## Recommended Initiative",
|
|
6416
|
+
"",
|
|
6417
|
+
`Title: ${plan.recommended_initiative.title}`,
|
|
6418
|
+
"",
|
|
6419
|
+
plan.recommended_initiative.summary,
|
|
6420
|
+
"",
|
|
6421
|
+
"## Approved Follow-Up Candidate",
|
|
6422
|
+
"",
|
|
6423
|
+
`Title: ${plan.recommended_follow_up.title}`,
|
|
6424
|
+
"",
|
|
6425
|
+
plan.recommended_follow_up.summary,
|
|
6426
|
+
"",
|
|
6427
|
+
`Rollback: ${plan.recommended_follow_up.rollback}`,
|
|
6428
|
+
"",
|
|
6429
|
+
"## Artifact Invariant",
|
|
6430
|
+
"",
|
|
6431
|
+
"```json",
|
|
6432
|
+
JSON.stringify(plan.artifact_invariant, null, 2),
|
|
6433
|
+
"```",
|
|
6434
|
+
""
|
|
6435
|
+
];
|
|
6436
|
+
return lines.join("\n");
|
|
6437
|
+
}
|
|
6438
|
+
function parseEntityRef(payload) {
|
|
6439
|
+
const entity = isRecord(payload) && isRecord(payload.data) ? payload.data : payload;
|
|
6440
|
+
if (!isRecord(entity)) {
|
|
6441
|
+
throw new Error("OrgX returned an unexpected entity payload.");
|
|
6442
|
+
}
|
|
6443
|
+
const id = typeof entity.id === "string" ? entity.id : "";
|
|
6444
|
+
const title = typeof entity.title === "string" ? entity.title : typeof entity.name === "string" ? entity.name : "";
|
|
6445
|
+
if (!id || !title) {
|
|
6446
|
+
throw new Error("OrgX returned an incomplete entity payload.");
|
|
6447
|
+
}
|
|
6448
|
+
return { id, title };
|
|
6449
|
+
}
|
|
6450
|
+
async function parseResponseBody5(response) {
|
|
6451
|
+
const text2 = await response.text();
|
|
6452
|
+
if (!text2) return null;
|
|
6453
|
+
try {
|
|
6454
|
+
return JSON.parse(text2);
|
|
6455
|
+
} catch {
|
|
6456
|
+
return text2;
|
|
6457
|
+
}
|
|
6458
|
+
}
|
|
6459
|
+
function formatHttpError4(status, body) {
|
|
6460
|
+
if (typeof body === "string" && body.trim().length > 0) {
|
|
6461
|
+
return `HTTP ${status}: ${body}`;
|
|
6462
|
+
}
|
|
6463
|
+
if (isRecord(body) && typeof body.error === "string" && body.error.trim().length > 0) {
|
|
6464
|
+
return `HTTP ${status}: ${body.error}`;
|
|
6465
|
+
}
|
|
6466
|
+
if (isRecord(body) && isRecord(body.error) && typeof body.error.message === "string") {
|
|
6467
|
+
return `HTTP ${status}: ${body.error.message}`;
|
|
6468
|
+
}
|
|
6469
|
+
return `HTTP ${status}`;
|
|
6470
|
+
}
|
|
6471
|
+
async function createOrgxEntity(body, options) {
|
|
6472
|
+
if (options.dryRun) {
|
|
6473
|
+
return {
|
|
6474
|
+
id: `dry-run-${String(body.type ?? "entity")}`,
|
|
6475
|
+
title: String(body.title ?? body.name ?? "Dry-run entity")
|
|
6476
|
+
};
|
|
6477
|
+
}
|
|
6478
|
+
const auth = await resolveOrgxAuth(options);
|
|
6479
|
+
if (!auth) {
|
|
6480
|
+
throw new Error("No OrgX API key configured. Run `wizard auth login` before using writeback flags.");
|
|
6481
|
+
}
|
|
6482
|
+
const response = await fetch(buildOrgxApiUrl("/entities", auth.baseUrl), {
|
|
6483
|
+
body: JSON.stringify(body),
|
|
6484
|
+
headers: {
|
|
6485
|
+
Authorization: `Bearer ${auth.apiKey}`,
|
|
6486
|
+
"Content-Type": "application/json"
|
|
6487
|
+
},
|
|
6488
|
+
method: "POST",
|
|
6489
|
+
signal: AbortSignal.timeout(15e3)
|
|
6490
|
+
});
|
|
6491
|
+
const responseBody = await parseResponseBody5(response);
|
|
6492
|
+
if (!response.ok) {
|
|
6493
|
+
throw new Error(`Failed to create ${String(body.type ?? "entity")}. ${formatHttpError4(response.status, responseBody)}`);
|
|
6494
|
+
}
|
|
6495
|
+
return parseEntityRef(responseBody);
|
|
6496
|
+
}
|
|
6497
|
+
async function createAuditArtifact(options) {
|
|
6498
|
+
const { initiativeId, markdown, plan } = options;
|
|
6499
|
+
return createOrgxEntity(
|
|
6500
|
+
{
|
|
6501
|
+
artifact_type: "shared.project_handbook",
|
|
6502
|
+
description: "AI-native Founder Loop self-audit generated by @useorgx/wizard audit.",
|
|
6503
|
+
entity_id: initiativeId,
|
|
6504
|
+
entity_type: "initiative",
|
|
6505
|
+
external_url: `orgx-wizard://audit/${plan.artifact_hash}`,
|
|
6506
|
+
initiative_id: initiativeId,
|
|
6507
|
+
metadata: {
|
|
6508
|
+
...plan.artifact_invariant,
|
|
6509
|
+
artifact_hash: plan.artifact_hash,
|
|
6510
|
+
atomic_unit_type: "ai_native_self_audit",
|
|
6511
|
+
completion_state: "generated",
|
|
6512
|
+
schema_validated: true,
|
|
6513
|
+
scores: plan.scores
|
|
6514
|
+
},
|
|
6515
|
+
name: `AI-Native Self-Audit: ${plan.workspace.name}`,
|
|
6516
|
+
preview_markdown: markdown.slice(0, 8e3),
|
|
6517
|
+
status: "in_review",
|
|
6518
|
+
type: "artifact",
|
|
6519
|
+
workspace_id: plan.workspace.id
|
|
6520
|
+
},
|
|
6521
|
+
options
|
|
6522
|
+
);
|
|
6523
|
+
}
|
|
6524
|
+
async function createInitiativeFromAuditPlan(options) {
|
|
6525
|
+
const { plan } = options;
|
|
6526
|
+
return createOrgxEntity(
|
|
6527
|
+
{
|
|
6528
|
+
metadata: {
|
|
6529
|
+
artifact_hash: plan.artifact_hash,
|
|
6530
|
+
audit_score_snapshot: plan.scores,
|
|
6531
|
+
source: "ai_native_self_audit",
|
|
6532
|
+
source_artifact_type: "ai_native_self_audit_plan"
|
|
6533
|
+
},
|
|
6534
|
+
status: "active",
|
|
6535
|
+
summary: plan.recommended_initiative.summary,
|
|
6536
|
+
title: plan.recommended_initiative.title,
|
|
6537
|
+
type: "initiative",
|
|
6538
|
+
workspace_id: plan.workspace.id
|
|
6539
|
+
},
|
|
6540
|
+
options
|
|
6541
|
+
);
|
|
6542
|
+
}
|
|
6543
|
+
async function createAuditFollowUpTask(options) {
|
|
6544
|
+
const { initiativeId, milestoneId, plan, workstreamId } = options;
|
|
6545
|
+
const resolvedWorkstreamId = workstreamId?.trim() || (await createOrgxEntity(
|
|
6546
|
+
{
|
|
6547
|
+
initiative_id: initiativeId,
|
|
6548
|
+
metadata: {
|
|
6549
|
+
artifact_hash: plan.artifact_hash,
|
|
6550
|
+
source: "ai_native_self_audit"
|
|
6551
|
+
},
|
|
6552
|
+
status: "active",
|
|
6553
|
+
summary: "Follow-up workstream created by @useorgx/wizard audit so the approved action has execution context.",
|
|
6554
|
+
title: "AI-native self-audit follow-up",
|
|
6555
|
+
type: "workstream",
|
|
6556
|
+
workspace_id: plan.workspace.id
|
|
6557
|
+
},
|
|
6558
|
+
options
|
|
6559
|
+
)).id;
|
|
6560
|
+
const resolvedMilestoneId = milestoneId?.trim() || (await createOrgxEntity(
|
|
6561
|
+
{
|
|
6562
|
+
initiative_id: initiativeId,
|
|
6563
|
+
metadata: {
|
|
6564
|
+
artifact_hash: plan.artifact_hash,
|
|
6565
|
+
source: "ai_native_self_audit"
|
|
6566
|
+
},
|
|
6567
|
+
status: "planned",
|
|
6568
|
+
summary: "Milestone created by @useorgx/wizard audit so the approved follow-up task has proof-chain hierarchy.",
|
|
6569
|
+
title: "AI-native self-audit follow-up",
|
|
6570
|
+
type: "milestone",
|
|
6571
|
+
workspace_id: plan.workspace.id,
|
|
6572
|
+
workstream_id: resolvedWorkstreamId
|
|
6573
|
+
},
|
|
6574
|
+
options
|
|
6575
|
+
)).id;
|
|
6576
|
+
return createOrgxEntity(
|
|
6577
|
+
{
|
|
6578
|
+
description: `${plan.recommended_follow_up.summary}
|
|
6579
|
+
|
|
6580
|
+
Rollback: ${plan.recommended_follow_up.rollback}`,
|
|
6581
|
+
initiative_id: initiativeId,
|
|
6582
|
+
milestone_id: resolvedMilestoneId,
|
|
6583
|
+
metadata: {
|
|
6584
|
+
...plan.artifact_invariant,
|
|
6585
|
+
artifact_hash: plan.artifact_hash,
|
|
6586
|
+
source: "ai_native_self_audit",
|
|
6587
|
+
source_action: "approved_follow_up_writeback"
|
|
6588
|
+
},
|
|
6589
|
+
priority: "high",
|
|
6590
|
+
status: "todo",
|
|
6591
|
+
title: plan.recommended_follow_up.title,
|
|
6592
|
+
type: "task",
|
|
6593
|
+
workstream_id: resolvedWorkstreamId,
|
|
6594
|
+
workspace_id: plan.workspace.id
|
|
6595
|
+
},
|
|
6596
|
+
options
|
|
6597
|
+
);
|
|
6598
|
+
}
|
|
6599
|
+
|
|
5928
6600
|
// src/spinner.ts
|
|
5929
6601
|
import ora from "ora";
|
|
5930
6602
|
import pc2 from "picocolors";
|
|
@@ -6025,6 +6697,188 @@ function printPluginMutationReport(report) {
|
|
|
6025
6697
|
);
|
|
6026
6698
|
}
|
|
6027
6699
|
}
|
|
6700
|
+
function formatScoreLine(scores) {
|
|
6701
|
+
return Object.entries(scores).map(([dimension, score]) => `${dimension}=${score}`).join(" ");
|
|
6702
|
+
}
|
|
6703
|
+
function readAuditInput(options, interactive) {
|
|
6704
|
+
if (options.input?.trim()) {
|
|
6705
|
+
return readFileSync4(resolve(options.input.trim()), "utf8");
|
|
6706
|
+
}
|
|
6707
|
+
if (!process.stdin.isTTY) {
|
|
6708
|
+
return readFileSync4(0, "utf8");
|
|
6709
|
+
}
|
|
6710
|
+
if (!interactive) {
|
|
6711
|
+
throw new Error("Audit input is required. Pass --input <file> or pipe text into wizard audit.");
|
|
6712
|
+
}
|
|
6713
|
+
return textPrompt({
|
|
6714
|
+
message: "Paste a short AI-session summary, decision log, or founder context excerpt",
|
|
6715
|
+
placeholder: "Decision: Founder Loop first. Artifact: proof ledger attached. Next action: ...",
|
|
6716
|
+
validate: (value) => value?.trim().length ? void 0 : "Audit context is required."
|
|
6717
|
+
}).then((value) => {
|
|
6718
|
+
if (clack.isCancel(value) || typeof value !== "string") {
|
|
6719
|
+
clack.cancel("Audit cancelled.");
|
|
6720
|
+
return "";
|
|
6721
|
+
}
|
|
6722
|
+
return value;
|
|
6723
|
+
});
|
|
6724
|
+
}
|
|
6725
|
+
function parsePositiveInteger(value, fallback, label) {
|
|
6726
|
+
if (!value?.trim()) return fallback;
|
|
6727
|
+
const parsed = Number.parseInt(value.trim(), 10);
|
|
6728
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
6729
|
+
throw new Error(`${label} must be a positive integer.`);
|
|
6730
|
+
}
|
|
6731
|
+
return parsed;
|
|
6732
|
+
}
|
|
6733
|
+
async function readAuditImports(options, interactive) {
|
|
6734
|
+
const sources = parseAiSessionSources(options.from);
|
|
6735
|
+
const imports = [];
|
|
6736
|
+
const connectedSources = [];
|
|
6737
|
+
const missingSources = [];
|
|
6738
|
+
if (sources.length > 0) {
|
|
6739
|
+
const imported = loadAiSessionImports({
|
|
6740
|
+
...options.claudeProjectsDir?.trim() ? { claudeProjectsDir: resolve(options.claudeProjectsDir.trim()) } : {},
|
|
6741
|
+
...options.codexSessionsDir?.trim() ? { codexSessionsDir: resolve(options.codexSessionsDir.trim()) } : {},
|
|
6742
|
+
limitPerSource: parsePositiveInteger(options.sessionLimit, 3, "--session-limit"),
|
|
6743
|
+
sinceDays: parsePositiveInteger(options.sessionDays, 30, "--session-days"),
|
|
6744
|
+
sources
|
|
6745
|
+
});
|
|
6746
|
+
imports.push(...imported.imports);
|
|
6747
|
+
connectedSources.push(...imported.connectedSources);
|
|
6748
|
+
missingSources.push(...imported.missingSources);
|
|
6749
|
+
}
|
|
6750
|
+
const shouldReadManualInput = Boolean(options.input?.trim()) || sources.length === 0 || !process.stdin.isTTY;
|
|
6751
|
+
if (shouldReadManualInput) {
|
|
6752
|
+
const text2 = (await readAuditInput(options, interactive)).trim();
|
|
6753
|
+
if (text2) {
|
|
6754
|
+
imports.push({
|
|
6755
|
+
sourceId: "wizard-audit-input",
|
|
6756
|
+
sourceLabel: options.sourceLabel?.trim() || "Wizard audit input",
|
|
6757
|
+
text: text2
|
|
6758
|
+
});
|
|
6759
|
+
connectedSources.push(options.sourceLabel?.trim() || "Manual AI-session import");
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
if (imports.length === 0) {
|
|
6763
|
+
const sourceHint = sources.length > 0 ? ` No audit-relevant lines were found in ${sources.join(", ")} sessions.` : "";
|
|
6764
|
+
throw new Error(`Audit input is required.${sourceHint} Pass --input <file>, pipe text, or use --from codex|claude|all.`);
|
|
6765
|
+
}
|
|
6766
|
+
return {
|
|
6767
|
+
connectedSources,
|
|
6768
|
+
imports,
|
|
6769
|
+
missingSources
|
|
6770
|
+
};
|
|
6771
|
+
}
|
|
6772
|
+
function requireWriteApproval(options, interactive) {
|
|
6773
|
+
const wantsWrite = Boolean(options.createInitiative || options.attachToInitiative || options.writeFollowUp);
|
|
6774
|
+
if (!wantsWrite || options.yes || options.dryRun) return true;
|
|
6775
|
+
if (!interactive) {
|
|
6776
|
+
throw new Error("Write flags require --yes in non-interactive mode.");
|
|
6777
|
+
}
|
|
6778
|
+
return clack.confirm({
|
|
6779
|
+
message: "Approve OrgX writes for this audit run?"
|
|
6780
|
+
}).then((value) => {
|
|
6781
|
+
if (clack.isCancel(value) || value !== true) {
|
|
6782
|
+
clack.cancel("Audit writeback cancelled.");
|
|
6783
|
+
return false;
|
|
6784
|
+
}
|
|
6785
|
+
return true;
|
|
6786
|
+
});
|
|
6787
|
+
}
|
|
6788
|
+
async function resolveAuditWorkspace(options) {
|
|
6789
|
+
const explicitId = options.workspaceId?.trim();
|
|
6790
|
+
const explicitName = options.workspaceName?.trim();
|
|
6791
|
+
if (explicitId || explicitName) {
|
|
6792
|
+
return {
|
|
6793
|
+
id: explicitId || "manual-workspace",
|
|
6794
|
+
name: explicitName || explicitId || "Manual workspace"
|
|
6795
|
+
};
|
|
6796
|
+
}
|
|
6797
|
+
try {
|
|
6798
|
+
const workspace = await getCurrentWorkspace();
|
|
6799
|
+
if (workspace) {
|
|
6800
|
+
return {
|
|
6801
|
+
id: workspace.id,
|
|
6802
|
+
name: workspace.name
|
|
6803
|
+
};
|
|
6804
|
+
}
|
|
6805
|
+
} catch {
|
|
6806
|
+
}
|
|
6807
|
+
return {
|
|
6808
|
+
id: "local-workspace",
|
|
6809
|
+
name: "Local workspace"
|
|
6810
|
+
};
|
|
6811
|
+
}
|
|
6812
|
+
async function runAuditCommand(options) {
|
|
6813
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
6814
|
+
const auditImports = await readAuditImports(options, interactive);
|
|
6815
|
+
const workspace = await resolveAuditWorkspace(options);
|
|
6816
|
+
const plan = buildSelfAuditPlan({
|
|
6817
|
+
connectedSources: [
|
|
6818
|
+
...auditImports.connectedSources,
|
|
6819
|
+
...workspace.id === "local-workspace" ? [] : ["OrgX workspace"]
|
|
6820
|
+
],
|
|
6821
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6822
|
+
imports: auditImports.imports,
|
|
6823
|
+
missingSources: [
|
|
6824
|
+
...workspace.id === "local-workspace" ? ["OrgX workspace auth"] : [],
|
|
6825
|
+
...auditImports.missingSources
|
|
6826
|
+
],
|
|
6827
|
+
workspace
|
|
6828
|
+
});
|
|
6829
|
+
const markdown = renderSelfAuditMarkdown(plan);
|
|
6830
|
+
const outputDir = resolve(options.outputDir?.trim() || ".orgx/audits");
|
|
6831
|
+
const timestamp = plan.generated_at.replace(/[:.]/g, "-");
|
|
6832
|
+
const jsonPath = resolve(outputDir, `ai-native-self-audit-${timestamp}.json`);
|
|
6833
|
+
const markdownPath = resolve(outputDir, `ai-native-self-audit-${timestamp}.md`);
|
|
6834
|
+
writeJsonFile(jsonPath, plan);
|
|
6835
|
+
writeTextFile(markdownPath, markdown);
|
|
6836
|
+
if (options.json) {
|
|
6837
|
+
console.log(JSON.stringify({ jsonPath, markdownPath, scores: plan.scores }, null, 2));
|
|
6838
|
+
} else {
|
|
6839
|
+
console.log(` ${ICON.ok} ${pc3.green("audit generated")} ${pc3.dim(markdownPath)}`);
|
|
6840
|
+
console.log(` ${ICON.ok} ${pc3.green("scores ")} ${pc3.dim(formatScoreLine(plan.scores))}`);
|
|
6841
|
+
const belowTarget = plan.self_critique.filter((item) => !item.passed);
|
|
6842
|
+
if (belowTarget.length === 0) {
|
|
6843
|
+
console.log(` ${ICON.ok} ${pc3.green("score gate ")} ${pc3.dim("all dimensions at 95+")}`);
|
|
6844
|
+
} else {
|
|
6845
|
+
console.log(` ${ICON.warn} ${pc3.yellow("score gate ")} ${pc3.dim(`${belowTarget.length} dimension${belowTarget.length === 1 ? "" : "s"} below 95`)}`);
|
|
6846
|
+
}
|
|
6847
|
+
}
|
|
6848
|
+
const approved = await requireWriteApproval(options, interactive);
|
|
6849
|
+
if (!approved) return;
|
|
6850
|
+
let targetInitiativeId = options.attachToInitiative?.trim() || "";
|
|
6851
|
+
if (options.createInitiative) {
|
|
6852
|
+
const initiative = await createInitiativeFromAuditPlan({
|
|
6853
|
+
dryRun: Boolean(options.dryRun),
|
|
6854
|
+
plan
|
|
6855
|
+
});
|
|
6856
|
+
targetInitiativeId = initiative.id;
|
|
6857
|
+
console.log(` ${ICON.ok} ${pc3.green("initiative ")} ${pc3.bold(initiative.title)} ${pc3.dim(initiative.id)}`);
|
|
6858
|
+
}
|
|
6859
|
+
if (targetInitiativeId && (options.attachToInitiative || options.createInitiative)) {
|
|
6860
|
+
const artifact = await createAuditArtifact({
|
|
6861
|
+
dryRun: Boolean(options.dryRun),
|
|
6862
|
+
initiativeId: targetInitiativeId,
|
|
6863
|
+
markdown,
|
|
6864
|
+
plan
|
|
6865
|
+
});
|
|
6866
|
+
console.log(` ${ICON.ok} ${pc3.green("artifact ")} ${pc3.bold(artifact.title)} ${pc3.dim(artifact.id)}`);
|
|
6867
|
+
}
|
|
6868
|
+
if (options.writeFollowUp) {
|
|
6869
|
+
if (!targetInitiativeId) {
|
|
6870
|
+
throw new Error("--write-follow-up requires --attach-to-initiative <id> or --create-initiative.");
|
|
6871
|
+
}
|
|
6872
|
+
const followUp = await createAuditFollowUpTask({
|
|
6873
|
+
dryRun: Boolean(options.dryRun),
|
|
6874
|
+
initiativeId: targetInitiativeId,
|
|
6875
|
+
...options.milestoneId?.trim() ? { milestoneId: options.milestoneId.trim() } : {},
|
|
6876
|
+
plan,
|
|
6877
|
+
...options.workstreamId?.trim() ? { workstreamId: options.workstreamId.trim() } : {}
|
|
6878
|
+
});
|
|
6879
|
+
console.log(` ${ICON.ok} ${pc3.green("follow-up ")} ${pc3.bold(followUp.title)} ${pc3.dim(followUp.id)}`);
|
|
6880
|
+
}
|
|
6881
|
+
}
|
|
6028
6882
|
async function checkPluginStatusesCompact() {
|
|
6029
6883
|
const spinner = createOrgxSpinner("Checking OrgX companion plugin status");
|
|
6030
6884
|
spinner.start();
|
|
@@ -6323,14 +7177,14 @@ async function readSingleKey() {
|
|
|
6323
7177
|
const stdin = process.stdin;
|
|
6324
7178
|
if (!stdin.isTTY) return null;
|
|
6325
7179
|
const previousRawMode = stdin.isRaw === true;
|
|
6326
|
-
return await new Promise((
|
|
7180
|
+
return await new Promise((resolve2) => {
|
|
6327
7181
|
const cleanup = (result) => {
|
|
6328
7182
|
stdin.off("data", onData);
|
|
6329
7183
|
if (stdin.isTTY) {
|
|
6330
7184
|
stdin.setRawMode(previousRawMode);
|
|
6331
7185
|
}
|
|
6332
7186
|
stdin.pause();
|
|
6333
|
-
|
|
7187
|
+
resolve2(result);
|
|
6334
7188
|
};
|
|
6335
7189
|
const onData = (chunk) => {
|
|
6336
7190
|
const text2 = chunk.toString("utf8");
|
|
@@ -6942,7 +7796,7 @@ function printDoctorReport(report, assessment) {
|
|
|
6942
7796
|
async function main() {
|
|
6943
7797
|
const program = new Command();
|
|
6944
7798
|
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.
|
|
7799
|
+
const pkgVersion = true ? "0.1.23" : void 0;
|
|
6946
7800
|
program.version(pkgVersion ?? "unknown", "-V, --version");
|
|
6947
7801
|
program.hook("preAction", () => {
|
|
6948
7802
|
console.log(renderBanner(pkgVersion));
|
|
@@ -7604,6 +8458,16 @@ async function main() {
|
|
|
7604
8458
|
jsonOutput: Boolean(options.json)
|
|
7605
8459
|
});
|
|
7606
8460
|
});
|
|
8461
|
+
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("--from <sources>", "auto-import recent local AI sessions: codex, claude, or all").option("--session-limit <count>", "max recent sessions to import per selected source", "3").option("--session-days <days>", "lookback window for local AI-session imports", "30").option("--codex-sessions-dir <path>", "override Codex sessions directory for audit import").option("--claude-projects-dir <path>", "override Claude projects directory for audit import").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) => {
|
|
8462
|
+
await safeTrackWizardTelemetry("audit_started", {
|
|
8463
|
+
attach_to_initiative: Boolean(options.attachToInitiative),
|
|
8464
|
+
command: "audit",
|
|
8465
|
+
create_initiative: Boolean(options.createInitiative),
|
|
8466
|
+
dry_run: Boolean(options.dryRun),
|
|
8467
|
+
write_follow_up: Boolean(options.writeFollowUp)
|
|
8468
|
+
});
|
|
8469
|
+
await runAuditCommand(options);
|
|
8470
|
+
});
|
|
7607
8471
|
program.command("doctor").description("Verify local OrgX surface config and optional remote setup status.").action(async () => {
|
|
7608
8472
|
const spinner = createOrgxSpinner("Running OrgX health check");
|
|
7609
8473
|
spinner.start();
|