@useorgx/wizard 0.1.22 → 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 +233 -17
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
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
|
|
6
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
7
7
|
import { hostname } from "os";
|
|
8
8
|
import { resolve } from "path";
|
|
9
9
|
import { Command } from "commander";
|
|
@@ -81,6 +81,8 @@ var CURSOR_DIR = join(HOME, ".cursor");
|
|
|
81
81
|
var CODEX_DIR = join(HOME, ".codex");
|
|
82
82
|
var OPENCLAW_DIR = join(HOME, ".openclaw");
|
|
83
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");
|
|
84
86
|
var CLAUDE_SKILLS_DIR = join(CLAUDE_DIR, "skills");
|
|
85
87
|
var CLAUDE_ORGX_SKILL_DIR = join(CLAUDE_SKILLS_DIR, "orgx");
|
|
86
88
|
var CLAUDE_ORGX_SKILL_PATH = join(CLAUDE_ORGX_SKILL_DIR, "SKILL.md");
|
|
@@ -4102,8 +4104,8 @@ function encodeRepoPath2(value) {
|
|
|
4102
4104
|
return value.split("/").filter((segment) => segment.length > 0).map((segment) => encodeURIComponent(segment)).join("/");
|
|
4103
4105
|
}
|
|
4104
4106
|
function isLikelyRepoFilePath(path) {
|
|
4105
|
-
const
|
|
4106
|
-
return
|
|
4107
|
+
const basename3 = path.split("/").pop() ?? path;
|
|
4108
|
+
return basename3.includes(".") && !/^\.[^./]+$/.test(basename3);
|
|
4107
4109
|
}
|
|
4108
4110
|
function buildContentsUrl2(spec, path) {
|
|
4109
4111
|
const encodedPath = encodeRepoPath2(path);
|
|
@@ -5927,6 +5929,177 @@ async function fetchOnboardingState(auth) {
|
|
|
5927
5929
|
}
|
|
5928
5930
|
}
|
|
5929
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
|
+
|
|
5930
6103
|
// src/lib/self-audit.ts
|
|
5931
6104
|
import { createHash as createHash3 } from "crypto";
|
|
5932
6105
|
var SELF_AUDIT_SCHEMA_VERSION = "2026-04-27";
|
|
@@ -6529,10 +6702,10 @@ function formatScoreLine(scores) {
|
|
|
6529
6702
|
}
|
|
6530
6703
|
function readAuditInput(options, interactive) {
|
|
6531
6704
|
if (options.input?.trim()) {
|
|
6532
|
-
return
|
|
6705
|
+
return readFileSync4(resolve(options.input.trim()), "utf8");
|
|
6533
6706
|
}
|
|
6534
6707
|
if (!process.stdin.isTTY) {
|
|
6535
|
-
return
|
|
6708
|
+
return readFileSync4(0, "utf8");
|
|
6536
6709
|
}
|
|
6537
6710
|
if (!interactive) {
|
|
6538
6711
|
throw new Error("Audit input is required. Pass --input <file> or pipe text into wizard audit.");
|
|
@@ -6549,6 +6722,53 @@ function readAuditInput(options, interactive) {
|
|
|
6549
6722
|
return value;
|
|
6550
6723
|
});
|
|
6551
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
|
+
}
|
|
6552
6772
|
function requireWriteApproval(options, interactive) {
|
|
6553
6773
|
const wantsWrite = Boolean(options.createInitiative || options.attachToInitiative || options.writeFollowUp);
|
|
6554
6774
|
if (!wantsWrite || options.yes || options.dryRun) return true;
|
|
@@ -6591,23 +6811,19 @@ async function resolveAuditWorkspace(options) {
|
|
|
6591
6811
|
}
|
|
6592
6812
|
async function runAuditCommand(options) {
|
|
6593
6813
|
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
6594
|
-
const
|
|
6595
|
-
if (!text2) return;
|
|
6814
|
+
const auditImports = await readAuditImports(options, interactive);
|
|
6596
6815
|
const workspace = await resolveAuditWorkspace(options);
|
|
6597
6816
|
const plan = buildSelfAuditPlan({
|
|
6598
6817
|
connectedSources: [
|
|
6599
|
-
|
|
6818
|
+
...auditImports.connectedSources,
|
|
6600
6819
|
...workspace.id === "local-workspace" ? [] : ["OrgX workspace"]
|
|
6601
6820
|
],
|
|
6602
6821
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6603
|
-
imports:
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
text: text2
|
|
6608
|
-
}
|
|
6822
|
+
imports: auditImports.imports,
|
|
6823
|
+
missingSources: [
|
|
6824
|
+
...workspace.id === "local-workspace" ? ["OrgX workspace auth"] : [],
|
|
6825
|
+
...auditImports.missingSources
|
|
6609
6826
|
],
|
|
6610
|
-
missingSources: workspace.id === "local-workspace" ? ["OrgX workspace auth", "automatic AI-session import"] : ["automatic AI-session import"],
|
|
6611
6827
|
workspace
|
|
6612
6828
|
});
|
|
6613
6829
|
const markdown = renderSelfAuditMarkdown(plan);
|
|
@@ -7580,7 +7796,7 @@ function printDoctorReport(report, assessment) {
|
|
|
7580
7796
|
async function main() {
|
|
7581
7797
|
const program = new Command();
|
|
7582
7798
|
program.name("orgx-wizard").description("Add OrgX MCP configs, skills/rules, and companion plugins to your local AI tools.").showHelpAfterError();
|
|
7583
|
-
const pkgVersion = true ? "0.1.
|
|
7799
|
+
const pkgVersion = true ? "0.1.23" : void 0;
|
|
7584
7800
|
program.version(pkgVersion ?? "unknown", "-V, --version");
|
|
7585
7801
|
program.hook("preAction", () => {
|
|
7586
7802
|
console.log(renderBanner(pkgVersion));
|
|
@@ -8242,7 +8458,7 @@ async function main() {
|
|
|
8242
8458
|
jsonOutput: Boolean(options.json)
|
|
8243
8459
|
});
|
|
8244
8460
|
});
|
|
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) => {
|
|
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) => {
|
|
8246
8462
|
await safeTrackWizardTelemetry("audit_started", {
|
|
8247
8463
|
attach_to_initiative: Boolean(options.attachToInitiative),
|
|
8248
8464
|
command: "audit",
|