@oxagen/cli 2.1.4-705 → 2.1.4-710
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/oxagen.mjs +167 -30
- package/package.json +1 -1
package/oxagen.mjs
CHANGED
|
@@ -24941,7 +24941,7 @@ import { readFileSync as readFileSync10 } from "node:fs";
|
|
|
24941
24941
|
import { dirname as dirname9, resolve as resolve3 } from "node:path";
|
|
24942
24942
|
import { fileURLToPath } from "node:url";
|
|
24943
24943
|
function readVersion() {
|
|
24944
|
-
if (true) return "2.1.4-
|
|
24944
|
+
if (true) return "2.1.4-710";
|
|
24945
24945
|
try {
|
|
24946
24946
|
const here = dirname9(fileURLToPath(import.meta.url));
|
|
24947
24947
|
const pkg = JSON.parse(
|
|
@@ -57199,7 +57199,7 @@ var init_package = __esm({
|
|
|
57199
57199
|
"package.json"() {
|
|
57200
57200
|
package_default = {
|
|
57201
57201
|
name: "@oxagen/cli",
|
|
57202
|
-
version: "2.1.4-
|
|
57202
|
+
version: "2.1.4-710",
|
|
57203
57203
|
description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
|
|
57204
57204
|
type: "module",
|
|
57205
57205
|
main: "./dist/index.js",
|
|
@@ -63570,7 +63570,8 @@ var init_names = __esm({
|
|
|
63570
63570
|
"tools",
|
|
63571
63571
|
"agents",
|
|
63572
63572
|
"policy",
|
|
63573
|
-
"workspace"
|
|
63573
|
+
"workspace",
|
|
63574
|
+
"codegraph"
|
|
63574
63575
|
];
|
|
63575
63576
|
TOOL_SEPARATOR = "__";
|
|
63576
63577
|
BUILTIN_SERVER = "builtin";
|
|
@@ -79849,9 +79850,10 @@ async function readImportDocuments(sources, target2, writer) {
|
|
|
79849
79850
|
tooLong.push(source.path);
|
|
79850
79851
|
continue;
|
|
79851
79852
|
}
|
|
79852
|
-
const filename = importFilename(source.path, source.folder);
|
|
79853
|
+
const filename = source.filename ?? importFilename(source.path, source.folder);
|
|
79853
79854
|
const document = { filename, content };
|
|
79854
|
-
|
|
79855
|
+
const chosen = source.target ?? target2;
|
|
79856
|
+
if (chosen !== void 0) document.target = chosen;
|
|
79855
79857
|
if (source.source !== void 0) document.source = source.source;
|
|
79856
79858
|
if (source.files !== void 0 && source.files.length > 0) {
|
|
79857
79859
|
const files2 = [];
|
|
@@ -80042,12 +80044,19 @@ async function runMarkdownImport(documents, run3, writer) {
|
|
|
80042
80044
|
return;
|
|
80043
80045
|
}
|
|
80044
80046
|
if (!run3.json) writeFileNotes(files2, writer);
|
|
80047
|
+
let conflicts = 0;
|
|
80045
80048
|
for (const row of records) {
|
|
80046
80049
|
if (row.action !== null) continue;
|
|
80050
|
+
conflicts += 1;
|
|
80047
80051
|
writer.writeErr(
|
|
80048
80052
|
` Left out ${row.file}:${row.line} (${row.lineage}): it conflicts with ${row.conflict?.lineage ?? "a published record"}.`
|
|
80049
80053
|
);
|
|
80050
80054
|
}
|
|
80055
|
+
if (conflicts > 0) {
|
|
80056
|
+
writer.writeErr(
|
|
80057
|
+
` Left out ${conflicts} conflicting ${conflicts === 1 ? "record" : "records"}. Import ${conflicts === 1 ? "it" : "them"} in the app to choose which statement stays.`
|
|
80058
|
+
);
|
|
80059
|
+
}
|
|
80051
80060
|
for (const policy of policies) {
|
|
80052
80061
|
const issue = policy.issues[0];
|
|
80053
80062
|
if (policy.action !== "skip" || issue === void 0) continue;
|
|
@@ -80096,17 +80105,79 @@ __export(steering_import_exports, {
|
|
|
80096
80105
|
CATALOGUE_FOLDERS: () => CATALOGUE_FOLDERS,
|
|
80097
80106
|
STEERING_IMPORT_CAPABILITIES: () => STEERING_IMPORT_CAPABILITIES,
|
|
80098
80107
|
findMarkdownFiles: () => findMarkdownFiles,
|
|
80099
|
-
handleSteeringImport: () => handleSteeringImport
|
|
80108
|
+
handleSteeringImport: () => handleSteeringImport,
|
|
80109
|
+
harnessHome: () => harnessHome
|
|
80100
80110
|
});
|
|
80101
80111
|
import { readdir as readdir4, realpath as realpath2, stat as stat4 } from "node:fs/promises";
|
|
80112
|
+
import { homedir as homedir12 } from "node:os";
|
|
80102
80113
|
import { basename as basename8, extname, join as join51, relative as relative6, sep as sep7 } from "node:path";
|
|
80114
|
+
function envDir2(env, key) {
|
|
80115
|
+
const value = env[key];
|
|
80116
|
+
return value === void 0 || value.trim() === "" ? null : value;
|
|
80117
|
+
}
|
|
80118
|
+
function harnessHome(harness, env = process.env, home = homedir12()) {
|
|
80119
|
+
switch (harness) {
|
|
80120
|
+
case "claude-code": {
|
|
80121
|
+
const config = envDir2(env, "CLAUDE_CONFIG_DIR") ?? join51(home, ".claude");
|
|
80122
|
+
return {
|
|
80123
|
+
harness,
|
|
80124
|
+
folders: [
|
|
80125
|
+
{
|
|
80126
|
+
dir: skillsRoot("claude-code", env, home) ?? join51(config, "skills"),
|
|
80127
|
+
mount: ".claude/skills"
|
|
80128
|
+
},
|
|
80129
|
+
{ dir: join51(config, "commands"), mount: ".claude/commands" },
|
|
80130
|
+
{ dir: join51(config, "agents"), mount: ".claude/agents" }
|
|
80131
|
+
],
|
|
80132
|
+
instructions: [
|
|
80133
|
+
{ file: join51(config, "CLAUDE.md"), filename: ".claude/CLAUDE.md" }
|
|
80134
|
+
]
|
|
80135
|
+
};
|
|
80136
|
+
}
|
|
80137
|
+
case "codex": {
|
|
80138
|
+
const codexHome = envDir2(env, "CODEX_HOME") ?? join51(home, ".codex");
|
|
80139
|
+
return {
|
|
80140
|
+
harness,
|
|
80141
|
+
folders: [
|
|
80142
|
+
{
|
|
80143
|
+
dir: skillsRoot("codex", env, home) ?? join51(home, ".agents", "skills"),
|
|
80144
|
+
mount: ".agents/skills"
|
|
80145
|
+
}
|
|
80146
|
+
],
|
|
80147
|
+
instructions: ["AGENTS.override.md", "AGENTS.md"].map((name) => ({
|
|
80148
|
+
file: join51(codexHome, name),
|
|
80149
|
+
filename: `.codex/${name}`
|
|
80150
|
+
}))
|
|
80151
|
+
};
|
|
80152
|
+
}
|
|
80153
|
+
case "cursor":
|
|
80154
|
+
return {
|
|
80155
|
+
harness,
|
|
80156
|
+
folders: [
|
|
80157
|
+
{ dir: join51(home, ".cursor", "skills"), mount: ".cursor/skills" },
|
|
80158
|
+
{ dir: join51(home, ".cursor", "commands"), mount: ".cursor/commands" }
|
|
80159
|
+
],
|
|
80160
|
+
instructions: []
|
|
80161
|
+
};
|
|
80162
|
+
}
|
|
80163
|
+
}
|
|
80103
80164
|
function byName(a, b3) {
|
|
80104
80165
|
return a.name < b3.name ? -1 : 1;
|
|
80105
80166
|
}
|
|
80106
80167
|
function under(root, path2) {
|
|
80107
80168
|
return relative6(root, path2).split(sep7).join("/");
|
|
80108
80169
|
}
|
|
80109
|
-
|
|
80170
|
+
function isPersonal(rel) {
|
|
80171
|
+
return classifyHarnessFile(rel)?.kind === "personal";
|
|
80172
|
+
}
|
|
80173
|
+
async function isFolder(path2) {
|
|
80174
|
+
try {
|
|
80175
|
+
return (await stat4(path2)).isDirectory();
|
|
80176
|
+
} catch {
|
|
80177
|
+
return false;
|
|
80178
|
+
}
|
|
80179
|
+
}
|
|
80180
|
+
async function findMarkdownFiles(paths, harness) {
|
|
80110
80181
|
const sources = [];
|
|
80111
80182
|
const unreadable = [];
|
|
80112
80183
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -80140,7 +80211,7 @@ async function findMarkdownFiles(paths) {
|
|
|
80140
80211
|
}
|
|
80141
80212
|
return found;
|
|
80142
80213
|
};
|
|
80143
|
-
const walk2 = async (dir,
|
|
80214
|
+
const walk2 = async (dir, frame) => {
|
|
80144
80215
|
let entries2;
|
|
80145
80216
|
try {
|
|
80146
80217
|
entries2 = await readdir4(dir, { withFileTypes: true });
|
|
@@ -80149,27 +80220,31 @@ async function findMarkdownFiles(paths) {
|
|
|
80149
80220
|
return;
|
|
80150
80221
|
}
|
|
80151
80222
|
entries2.sort(byName);
|
|
80223
|
+
const { folder } = frame;
|
|
80224
|
+
const named = (rel) => frame.fixedNames ? { filename: rel } : {};
|
|
80152
80225
|
for (const entry2 of entries2) {
|
|
80153
80226
|
const path2 = join51(dir, entry2.name);
|
|
80154
|
-
const rel =
|
|
80227
|
+
const rel = frame.relOf(path2);
|
|
80155
80228
|
if (entry2.isDirectory()) {
|
|
80156
80229
|
if (entry2.name === "node_modules") continue;
|
|
80157
80230
|
if (entry2.name.startsWith(".")) {
|
|
80158
|
-
if (!inCatalogue && CATALOGUE_FOLDERS.has(entry2.name))
|
|
80159
|
-
await walk2(path2,
|
|
80231
|
+
if (!frame.inCatalogue && CATALOGUE_FOLDERS.has(entry2.name))
|
|
80232
|
+
await walk2(path2, { ...frame, inCatalogue: true });
|
|
80160
80233
|
continue;
|
|
80161
80234
|
}
|
|
80162
|
-
await walk2(path2,
|
|
80235
|
+
await walk2(path2, frame);
|
|
80163
80236
|
continue;
|
|
80164
80237
|
}
|
|
80165
80238
|
if (!entry2.isFile() && !entry2.isSymbolicLink()) continue;
|
|
80166
80239
|
const source = markdownImportSourceOf(rel);
|
|
80167
|
-
if (inCatalogue) {
|
|
80240
|
+
if (frame.inCatalogue) {
|
|
80168
80241
|
if (source === null) continue;
|
|
80169
80242
|
if (source.kind === "skill") {
|
|
80243
|
+
if (entries2.some((e) => e.name === SESSION_MARKER)) continue;
|
|
80170
80244
|
const skillDir = dir;
|
|
80171
80245
|
await take(path2, {
|
|
80172
80246
|
folder,
|
|
80247
|
+
...named(rel),
|
|
80173
80248
|
source: { ...source, path: rel },
|
|
80174
80249
|
files: (await filesUnder(skillDir, skillDir)).map((file) => ({
|
|
80175
80250
|
path: under(skillDir, file),
|
|
@@ -80177,11 +80252,17 @@ async function findMarkdownFiles(paths) {
|
|
|
80177
80252
|
}))
|
|
80178
80253
|
});
|
|
80179
80254
|
} else {
|
|
80180
|
-
await take(path2, {
|
|
80255
|
+
await take(path2, {
|
|
80256
|
+
folder,
|
|
80257
|
+
...named(rel),
|
|
80258
|
+
source: { ...source, path: rel }
|
|
80259
|
+
});
|
|
80181
80260
|
}
|
|
80182
80261
|
continue;
|
|
80183
80262
|
}
|
|
80184
|
-
if (
|
|
80263
|
+
if (isPersonal(rel)) {
|
|
80264
|
+
await take(path2, { folder, ...named(rel), target: "memories" });
|
|
80265
|
+
} else if (MARKDOWN_EXTENSIONS.has(extname(entry2.name).toLowerCase())) {
|
|
80185
80266
|
await take(
|
|
80186
80267
|
path2,
|
|
80187
80268
|
source === null ? { folder } : { folder, source: { ...source, path: rel } }
|
|
@@ -80192,18 +80273,28 @@ async function findMarkdownFiles(paths) {
|
|
|
80192
80273
|
}
|
|
80193
80274
|
};
|
|
80194
80275
|
for (const path2 of paths) {
|
|
80195
|
-
let
|
|
80276
|
+
let folderGiven;
|
|
80196
80277
|
try {
|
|
80197
|
-
|
|
80278
|
+
folderGiven = (await stat4(path2)).isDirectory();
|
|
80198
80279
|
} catch {
|
|
80199
80280
|
unreadable.push(path2);
|
|
80200
80281
|
continue;
|
|
80201
80282
|
}
|
|
80202
|
-
if (
|
|
80203
|
-
const
|
|
80204
|
-
|
|
80283
|
+
if (folderGiven) {
|
|
80284
|
+
const catalogue = CATALOGUE_FOLDERS.has(basename8(path2));
|
|
80285
|
+
const root = catalogue ? join51(path2, "..") : path2;
|
|
80286
|
+
await walk2(path2, {
|
|
80287
|
+
relOf: (p) => under(root, p),
|
|
80288
|
+
folder: path2,
|
|
80289
|
+
inCatalogue: catalogue,
|
|
80290
|
+
fixedNames: false
|
|
80291
|
+
});
|
|
80205
80292
|
} else {
|
|
80206
80293
|
const rel = under(process.cwd(), path2);
|
|
80294
|
+
if (isPersonal(rel.startsWith("..") ? basename8(path2) : rel)) {
|
|
80295
|
+
await take(path2, { target: "memories" });
|
|
80296
|
+
continue;
|
|
80297
|
+
}
|
|
80207
80298
|
const source = rel.startsWith("..") ? null : markdownImportSourceOf(rel);
|
|
80208
80299
|
await take(
|
|
80209
80300
|
path2,
|
|
@@ -80211,8 +80302,38 @@ async function findMarkdownFiles(paths) {
|
|
|
80211
80302
|
);
|
|
80212
80303
|
}
|
|
80213
80304
|
}
|
|
80305
|
+
if (harness !== void 0) {
|
|
80306
|
+
for (const { dir, mount } of harness.folders) {
|
|
80307
|
+
if (!await isFolder(dir)) continue;
|
|
80308
|
+
await walk2(dir, {
|
|
80309
|
+
relOf: (p) => `${mount}/${under(dir, p)}`,
|
|
80310
|
+
folder: dir,
|
|
80311
|
+
inCatalogue: true,
|
|
80312
|
+
fixedNames: true
|
|
80313
|
+
});
|
|
80314
|
+
}
|
|
80315
|
+
for (const { file, filename } of harness.instructions) {
|
|
80316
|
+
let found = false;
|
|
80317
|
+
try {
|
|
80318
|
+
found = (await stat4(file)).isFile();
|
|
80319
|
+
} catch {
|
|
80320
|
+
}
|
|
80321
|
+
if (!found) continue;
|
|
80322
|
+
await take(file, { filename, target: "memories" });
|
|
80323
|
+
break;
|
|
80324
|
+
}
|
|
80325
|
+
}
|
|
80214
80326
|
return { sources, unreadable };
|
|
80215
80327
|
}
|
|
80328
|
+
function parseHarness(value, writer) {
|
|
80329
|
+
if (value === void 0) return void 0;
|
|
80330
|
+
const harness = LAPTOP_HARNESSES.find((h) => h === value.toLowerCase());
|
|
80331
|
+
if (harness !== void 0) return harness;
|
|
80332
|
+
failCommand(
|
|
80333
|
+
`Invalid --harness "${value}". Use claude-code, codex, or cursor.`,
|
|
80334
|
+
writer
|
|
80335
|
+
);
|
|
80336
|
+
}
|
|
80216
80337
|
function parseTarget(value, writer) {
|
|
80217
80338
|
if (value === void 0) return void 0;
|
|
80218
80339
|
const target2 = TARGETS.find((t) => t === value.toLowerCase());
|
|
@@ -80222,15 +80343,17 @@ function parseTarget(value, writer) {
|
|
|
80222
80343
|
writer
|
|
80223
80344
|
);
|
|
80224
80345
|
}
|
|
80225
|
-
async function handleSteeringImport(paths, opts, writer = stdoutWriter) {
|
|
80226
|
-
|
|
80346
|
+
async function handleSteeringImport(paths, opts, writer = stdoutWriter, env = process.env, home = homedir12()) {
|
|
80347
|
+
const harness = parseHarness(opts.harness, writer);
|
|
80348
|
+
if (paths.length === 0 && harness === void 0) {
|
|
80227
80349
|
failCommand(
|
|
80228
|
-
"Nothing to import. Pass Markdown files or folders, such as `oxagen steering import docs`.",
|
|
80350
|
+
"Nothing to import. Pass Markdown files or folders, such as `oxagen steering import docs`, or a harness, such as `oxagen steering import --harness claude-code`.",
|
|
80229
80351
|
writer
|
|
80230
80352
|
);
|
|
80231
80353
|
}
|
|
80232
80354
|
const target2 = parseTarget(opts.as, writer);
|
|
80233
|
-
const
|
|
80355
|
+
const folders = harness === void 0 ? void 0 : harnessHome(harness, env, home);
|
|
80356
|
+
const walk2 = await findMarkdownFiles(paths, folders);
|
|
80234
80357
|
if (walk2.unreadable.length > 0) {
|
|
80235
80358
|
writer.writeErr(
|
|
80236
80359
|
`Skipped paths that do not exist or cannot be read:
|
|
@@ -80238,8 +80361,13 @@ async function handleSteeringImport(paths, opts, writer = stdoutWriter) {
|
|
|
80238
80361
|
);
|
|
80239
80362
|
}
|
|
80240
80363
|
if (walk2.sources.length === 0) {
|
|
80364
|
+
const where = [
|
|
80365
|
+
...paths,
|
|
80366
|
+
...folders?.folders.map((f) => f.dir) ?? [],
|
|
80367
|
+
...folders?.instructions.map((f) => f.file) ?? []
|
|
80368
|
+
];
|
|
80241
80369
|
failCommand(
|
|
80242
|
-
`Found no .md, .markdown, .mdx, or .mdc file in ${paths.join(", ")}. Pass a Markdown file, or a folder that holds one.`,
|
|
80370
|
+
folders === void 0 ? `Found no .md, .markdown, .mdx, or .mdc file in ${paths.join(", ")}. Pass a Markdown file, or a folder that holds one.` : `Found no skill, command, subagent file, instruction file, or Markdown file in ${where.join(", ")}.`,
|
|
80243
80371
|
writer
|
|
80244
80372
|
);
|
|
80245
80373
|
}
|
|
@@ -80250,11 +80378,12 @@ async function handleSteeringImport(paths, opts, writer = stdoutWriter) {
|
|
|
80250
80378
|
writer
|
|
80251
80379
|
);
|
|
80252
80380
|
}
|
|
80253
|
-
var STEERING_IMPORT_CAPABILITIES, MARKDOWN_EXTENSIONS, CATALOGUE_FOLDERS, TARGETS;
|
|
80381
|
+
var STEERING_IMPORT_CAPABILITIES, MARKDOWN_EXTENSIONS, CATALOGUE_FOLDERS, TARGETS, LAPTOP_HARNESSES;
|
|
80254
80382
|
var init_steering_import = __esm({
|
|
80255
80383
|
"src/commands/steering-import.ts"() {
|
|
80256
80384
|
init_steering_markdown_import_shared();
|
|
80257
80385
|
init_harness_files();
|
|
80386
|
+
init_skills();
|
|
80258
80387
|
init_capture_writer();
|
|
80259
80388
|
init_markdown_import();
|
|
80260
80389
|
STEERING_IMPORT_CAPABILITIES = [
|
|
@@ -80277,6 +80406,11 @@ var init_steering_import = __esm({
|
|
|
80277
80406
|
"policies",
|
|
80278
80407
|
"memories"
|
|
80279
80408
|
];
|
|
80409
|
+
LAPTOP_HARNESSES = [
|
|
80410
|
+
"claude-code",
|
|
80411
|
+
"codex",
|
|
80412
|
+
"cursor"
|
|
80413
|
+
];
|
|
80280
80414
|
}
|
|
80281
80415
|
});
|
|
80282
80416
|
|
|
@@ -82939,7 +83073,7 @@ import {
|
|
|
82939
83073
|
realpathSync as realpathSync8,
|
|
82940
83074
|
writeFileSync as writeFileSync7
|
|
82941
83075
|
} from "node:fs";
|
|
82942
|
-
import { homedir as
|
|
83076
|
+
import { homedir as homedir13, hostname as osHostname3 } from "node:os";
|
|
82943
83077
|
import { join as join53, relative as relative7, resolve as resolve19, sep as sep8 } from "node:path";
|
|
82944
83078
|
function git4(cwd, args) {
|
|
82945
83079
|
return new Promise((done) => {
|
|
@@ -83035,7 +83169,7 @@ function machineId(configDir = getConfigDir()) {
|
|
|
83035
83169
|
`, { encoding: "utf8", mode: 384 });
|
|
83036
83170
|
}
|
|
83037
83171
|
} catch {
|
|
83038
|
-
secret = `fallback:${osHostname3()}:${
|
|
83172
|
+
secret = `fallback:${osHostname3()}:${homedir13()}`;
|
|
83039
83173
|
}
|
|
83040
83174
|
return createHash17("sha256").update(secret).digest("hex");
|
|
83041
83175
|
}
|
|
@@ -134527,10 +134661,13 @@ function buildProgram() {
|
|
|
134527
134661
|
}
|
|
134528
134662
|
);
|
|
134529
134663
|
steeringCmd.command("import").argument(
|
|
134530
|
-
"
|
|
134664
|
+
"[paths...]",
|
|
134531
134665
|
"Markdown files, or folders to search for .md, .markdown, .mdx, and .mdc files"
|
|
134532
134666
|
).description(
|
|
134533
|
-
"Read Markdown files into steering records, Cedar policies, or memories. Previews unless --yes."
|
|
134667
|
+
"Read Markdown files, or your own harness folders, into steering records, Cedar policies, or memories. Previews unless --yes."
|
|
134668
|
+
).option(
|
|
134669
|
+
"--harness <name>",
|
|
134670
|
+
"claude-code, codex, or cursor. Also read that harness's skills, commands, and subagent files on this machine as workspace records, and its user instruction file, such as ~/.claude/CLAUDE.md, as your memories. Honours CLAUDE_CONFIG_DIR and CODEX_HOME."
|
|
134534
134671
|
).option(
|
|
134535
134672
|
"--as <target>",
|
|
134536
134673
|
"records, policies, or memories for every file. Without it, each file takes the target its text implies, such as policies for a file with a cedar block."
|
package/package.json
CHANGED