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