@oxagen/cli 2.1.4-430 → 2.1.4-438

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.
Files changed (2) hide show
  1. package/oxagen.mjs +131 -10
  2. package/package.json +1 -1
package/oxagen.mjs CHANGED
@@ -22995,7 +22995,7 @@ import { readFileSync as readFileSync10 } from "node:fs";
22995
22995
  import { dirname as dirname7, resolve as resolve2 } from "node:path";
22996
22996
  import { fileURLToPath } from "node:url";
22997
22997
  function readVersion() {
22998
- if (true) return "2.1.4-430";
22998
+ if (true) return "2.1.4-438";
22999
22999
  try {
23000
23000
  const here = dirname7(fileURLToPath(import.meta.url));
23001
23001
  const pkg = JSON.parse(
@@ -51676,7 +51676,7 @@ var init_package = __esm({
51676
51676
  "package.json"() {
51677
51677
  package_default = {
51678
51678
  name: "@oxagen/cli",
51679
- version: "2.1.4-430",
51679
+ version: "2.1.4-438",
51680
51680
  description: "Oxagen governance CLI \u2014 spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
51681
51681
  type: "module",
51682
51682
  main: "./dist/index.js",
@@ -57966,7 +57966,7 @@ var init_steering_markdown_import_shared = __esm({
57966
57966
  });
57967
57967
 
57968
57968
  // ../../packages/oxagen/src/contracts/context.steering.shared.ts
57969
- var recordKindSchema2, steeringPrKindSchema, proposalKindSchema, RECORD_KINDS2, STEERING_PR_KINDS, GOVERNANCE_LINEAGE, recordForceSchema2, constraintEffectSchema, publishedSharingScopeSchema, appendKindSchema, proposalStatusSchema, proposalStateSchema, repositoryProviderSchema, governanceModeSchema, GOVERNANCE_MODES2, checkNameSchema, CHECK_NAMES, steeringCheckNameSchema, STEERING_CHECK_NAMES, instant, checkResultSchema, RECORD_LINEAGE_ID, lineageIdSchema, proposedRecordSchema, proposalSupportSchema, proposalViewSchema, publishedRecordSchema;
57969
+ var recordKindSchema2, steeringPrKindSchema, proposalKindSchema, RECORD_KINDS2, STEERING_PR_KINDS, GOVERNANCE_LINEAGE, recordForceSchema2, constraintEffectSchema, publishedSharingScopeSchema, appendKindSchema, proposalStatusSchema, proposalStateSchema, repositoryProviderSchema, governanceModeSchema, GOVERNANCE_MODES2, checkNameSchema, CHECK_NAMES, steeringCheckNameSchema, STEERING_CHECK_NAMES, instant, checkResultSchema, checkFindingSchema, RECORD_LINEAGE_ID, lineageIdSchema, proposedRecordSchema, proposalSupportSchema, proposalViewSchema, publishedRecordSchema;
57970
57970
  var init_context_steering_shared = __esm({
57971
57971
  "../../packages/oxagen/src/contracts/context.steering.shared.ts"() {
57972
57972
  "use strict";
@@ -58058,6 +58058,15 @@ var init_context_steering_shared = __esm({
58058
58058
  startedAt: instant.nullable(),
58059
58059
  completedAt: instant.nullable()
58060
58060
  }).strict();
58061
+ checkFindingSchema = external_exports.object({
58062
+ rule: external_exports.enum(["managed-block"]),
58063
+ /** The file the finding is in. */
58064
+ path: external_exports.string(),
58065
+ /** The line it starts on, when the check could name one. */
58066
+ line: external_exports.number().int().positive().nullable(),
58067
+ /** One sentence saying what the check found. */
58068
+ message: external_exports.string()
58069
+ }).strict();
58061
58070
  RECORD_LINEAGE_ID = new RegExp(
58062
58071
  `^(?!${GOVERNANCE_LINEAGE}$)${STEERING_RECORD_LINEAGE.source.replace(/^\^/, "")}`
58063
58072
  );
@@ -70791,15 +70800,38 @@ var init_lineage = __esm({
70791
70800
  });
70792
70801
 
70793
70802
  // ../../packages/steering-check/src/checks/owned.ts
70794
- function writesFindings(env) {
70803
+ function lockServer(path2) {
70804
+ return path2.split("/")[2];
70805
+ }
70806
+ function lockFinding(path2, line, verb, problems) {
70807
+ const shown2 = problems.slice(0, 3).join(" ");
70808
+ const more = problems.length > 3 ? ` ${problems.length - 3} more problems follow.` : "";
70809
+ return find7({
70810
+ rule: "oxagen-writes",
70811
+ path: path2,
70812
+ line,
70813
+ field: null,
70814
+ message: `This steering PR ${verb} ${path2}, and the lock it holds is not one Oxagen writes. ${shown2}${more}`,
70815
+ expected: `${path2} as Studio's Review or a sync writes it.`,
70816
+ fix: `Restore ${path2} from the production branch. Change the server's tools in Studio and open its Review, or sync the server, and Oxagen writes the lock.`
70817
+ });
70818
+ }
70819
+ function writesFindings(env, base2) {
70795
70820
  const findings = [];
70821
+ const readLock3 = env.servers?.lock;
70796
70822
  for (const path2 of [...env.changed, ...env.removed].sort()) {
70797
- const what = OXAGEN_WRITES[classifySteeringRepoPath(path2)];
70823
+ const kind = classifySteeringRepoPath(path2);
70824
+ const what = OXAGEN_WRITES[kind];
70798
70825
  if (what === void 0) continue;
70799
- const before = env.base?.get(path2);
70826
+ const before = base2.get(path2);
70800
70827
  const after = env.head.get(path2);
70801
70828
  const line = after === void 0 ? null : before === void 0 ? 1 : firstDifferingLine(before, after);
70802
70829
  const verb = after === void 0 ? "removes" : before === void 0 ? "adds" : "changes";
70830
+ if (kind === "server-lock" && after !== void 0 && readLock3 !== void 0) {
70831
+ const outcome = readLock3(lockServer(path2), env.head, base2);
70832
+ if (!outcome.ok) findings.push(lockFinding(path2, line, verb, outcome.problems));
70833
+ continue;
70834
+ }
70803
70835
  findings.push(
70804
70836
  find7({
70805
70837
  rule: "oxagen-writes",
@@ -70867,7 +70899,7 @@ var init_owned = __esm({
70867
70899
  MANAGED_FILES = [AGENTS_MD_PATH, CLAUDE_MD_PATH, README_PATH];
70868
70900
  BEGIN_MARKER = "<!-- oxagen:begin managed sha256:... -->";
70869
70901
  ownedCheck = (env) => {
70870
- const findings = env.base === null ? [] : writesFindings(env);
70902
+ const findings = env.base === null ? [] : writesFindings(env, env.base);
70871
70903
  for (const path2 of MANAGED_FILES) {
70872
70904
  if (env.base !== null && !env.changed.has(path2) && !env.removed.has(path2)) continue;
70873
70905
  const finding = managedFinding(env, path2);
@@ -74513,6 +74545,9 @@ async function promoteWorkspaceMemories(input) {
74513
74545
  async function dismissWorkspaceMemories(input) {
74514
74546
  return apiPostOrThrow(ROUTES.dismiss, input);
74515
74547
  }
74548
+ async function dropMemoryPrRecord(input) {
74549
+ return apiPostOrThrow(ROUTES.drop, input);
74550
+ }
74516
74551
  function truncate2(text4, max2) {
74517
74552
  const line = text4.trim().replace(/\s+/g, " ");
74518
74553
  return line.length <= max2 ? line : `${line.slice(0, max2 - 3)}...`;
@@ -74639,6 +74674,15 @@ function formatDismissResult(result2, restore) {
74639
74674
  );
74640
74675
  return lines.join("\n");
74641
74676
  }
74677
+ function formatDropResult(result2) {
74678
+ const pr = result2.pull_request;
74679
+ const short5 = result2.commit_sha.slice(0, 7);
74680
+ return [
74681
+ result2.already_dropped ? `${result2.path} was already dropped from memory PR #${pr.number} in commit ${short5}.` : `Dropped ${result2.path} from memory PR #${pr.number} in commit ${short5} on ${pr.branch}.`,
74682
+ "When the PR merges, the record's statements are rejected and its memories wait again.",
74683
+ pr.url
74684
+ ].join("\n");
74685
+ }
74642
74686
  var ROUTES, WORKSPACE_MEMORY_STATES, STATE_LABELS, SKIP_REASONS2, SKIPPED_STATES;
74643
74687
  var init_workspace_memory_client = __esm({
74644
74688
  "src/lib/workspace-memory-client.ts"() {
@@ -74647,7 +74691,8 @@ var init_workspace_memory_client = __esm({
74647
74691
  list: "context/steering/memories/list",
74648
74692
  get: "context/steering/memories/get",
74649
74693
  promote: "context/steering/memories/promote",
74650
- dismiss: "context/steering/memories/dismiss"
74694
+ dismiss: "context/steering/memories/dismiss",
74695
+ drop: "context/steering/memory-prs/records/drop"
74651
74696
  };
74652
74697
  WORKSPACE_MEMORY_STATES = [
74653
74698
  "waiting",
@@ -74684,6 +74729,7 @@ __export(memory_exports, {
74684
74729
  MEMORY_COMMAND_CAPABILITIES: () => MEMORY_COMMAND_CAPABILITIES,
74685
74730
  MEMORY_IMPORT_CAPABILITIES: () => MEMORY_IMPORT_CAPABILITIES,
74686
74731
  handleMemoryDismiss: () => handleMemoryDismiss,
74732
+ handleMemoryDrop: () => handleMemoryDrop,
74687
74733
  handleMemoryImport: () => handleMemoryImport,
74688
74734
  handleMemoryList: () => handleMemoryList,
74689
74735
  handleMemoryPromote: () => handleMemoryPromote,
@@ -74795,6 +74841,23 @@ async function handleMemoryDismiss(ids, opts, writer = stdoutWriter) {
74795
74841
  handleApiError(err2, writer);
74796
74842
  }
74797
74843
  }
74844
+ async function handleMemoryDrop(number2, path2, opts, writer = stdoutWriter) {
74845
+ if (!/^\d+$/.test(number2.trim()) || Number(number2) < 1)
74846
+ failCommand(`Invalid memory PR number "${number2}". Use the PR's number, such as 12.`, writer);
74847
+ const pr = Number(number2.trim());
74848
+ if (path2.trim() === "")
74849
+ failCommand("Name the record file to drop, such as steering/memory/workspace/general/use-pnpm.md.", writer);
74850
+ try {
74851
+ const result2 = await dropMemoryPrRecord({ number: pr, path: path2.trim() });
74852
+ if (opts.json) {
74853
+ writer.write(JSON.stringify(result2, null, 2));
74854
+ return;
74855
+ }
74856
+ writer.write(formatDropResult(result2));
74857
+ } catch (err2) {
74858
+ handleApiError(err2, writer);
74859
+ }
74860
+ }
74798
74861
  async function handleMemoryImport(files2, opts, writer = stdoutWriter) {
74799
74862
  if (files2.length === 0) {
74800
74863
  failCommand(
@@ -74824,7 +74887,8 @@ var init_memory2 = __esm({
74824
74887
  "list_workspace_memories",
74825
74888
  "get_workspace_memory",
74826
74889
  "promote_memories",
74827
- "dismiss_memories"
74890
+ "dismiss_memories",
74891
+ "drop_memory_record"
74828
74892
  ];
74829
74893
  HARNESSES2 = ["claude-code", "codex", "cursor", "stella", "claude-desktop"];
74830
74894
  KINDS2 = [
@@ -112977,6 +113041,56 @@ function lockFindings2(name, text4, lock) {
112977
113041
  }
112978
113042
  return findings;
112979
113043
  }
113044
+ function versionProblem(name, key, entry2, before) {
113045
+ const tool = `${name}__${key}`;
113046
+ if (before === void 0) {
113047
+ return entry2.version === 1 ? null : `${tool} is at version ${entry2.version}, and a tool new to the lock starts at version 1.`;
113048
+ }
113049
+ if (before.definition_hash === entry2.definition_hash) {
113050
+ return entry2.version === before.version ? null : `${tool} is at version ${entry2.version}. Its definition_hash is the production lock's, so its version stays ${before.version}.`;
113051
+ }
113052
+ return entry2.version === before.version + 1 ? null : `${tool} is at version ${entry2.version}. Its definition_hash differs from the production lock's, so its version is ${before.version + 1}.`;
113053
+ }
113054
+ function lockOutcome(name, head2, base2) {
113055
+ const path2 = toolsLockPath(name);
113056
+ const text4 = head2.get(path2);
113057
+ if (text4 === void 0) return { ok: false, problems: [`The steering PR holds no ${path2}.`] };
113058
+ const read2 = parseLock(text4);
113059
+ if (!read2.ok) {
113060
+ const problems2 = read2.issues.map(
113061
+ (issue) => closed(issue.field === null ? issue.message : `${issue.field}: ${issue.message}`)
113062
+ );
113063
+ return { ok: false, problems: problems2 };
113064
+ }
113065
+ const pinned = read2.value;
113066
+ const problems = [];
113067
+ const serverText = head2.get(serverTomlPath(name));
113068
+ const server = serverText === void 0 ? void 0 : parseServerToml(serverText);
113069
+ if (server?.ok === true && server.value.source.type !== pinned.source.type) {
113070
+ problems.push(`The lock's source is ${pinned.source.type}, and server.toml's source is ${server.value.source.type}.`);
113071
+ }
113072
+ const toolsText = head2.get(toolsTomlPath(name));
113073
+ const tools = toolsText === void 0 ? void 0 : parseToolsToml(toolsText);
113074
+ if (tools?.ok === true) {
113075
+ const imported = tools.value.tools ?? {};
113076
+ for (const key of Object.keys(pinned.tools)) {
113077
+ if (!Object.hasOwn(imported, key)) {
113078
+ problems.push(`The lock holds ${name}__${key}, and tools.toml imports no tool keyed ${key}.`);
113079
+ }
113080
+ }
113081
+ }
113082
+ const baseText = base2.get(path2);
113083
+ const previous = baseText === void 0 ? null : readLock2(baseText);
113084
+ if (previous === null || previous.ok) {
113085
+ const prior = previous === null ? {} : previous.lock.tools;
113086
+ const entries2 = Object.entries(pinned.tools);
113087
+ for (const [key, entry2] of entries2) {
113088
+ const problem = versionProblem(name, key, entry2, Object.hasOwn(prior, key) ? prior[key] : void 0);
113089
+ if (problem !== null) problems.push(problem);
113090
+ }
113091
+ }
113092
+ return problems.length === 0 ? { ok: true } : { ok: false, problems };
113093
+ }
112980
113094
  function toolField(tool, field) {
112981
113095
  return field === void 0 ? `tools.${tool}` : `tools.${tool}.${field}`;
112982
113096
  }
@@ -113243,7 +113357,8 @@ var init_servers = __esm({
113243
113357
  CALLS_FILE = "tests/calls.jsonl";
113244
113358
  SERVER_READERS = {
113245
113359
  server: (text4) => outcomeOf2(parseServerToml(text4)),
113246
- tools: (text4) => outcomeOf2(parseToolsToml(text4))
113360
+ tools: (text4) => outcomeOf2(parseToolsToml(text4)),
113361
+ lock: (name, head2, base2) => lockOutcome(name, head2, base2)
113247
113362
  };
113248
113363
  DEFINITION_SOURCES = /* @__PURE__ */ new Set(["openapi", "graphql", "grpc"]);
113249
113364
  RESYNC = "Restore tools.lock.json from the production branch. If the production branch has this lock, sync the server in Studio so Oxagen writes it again.";
@@ -116150,6 +116265,12 @@ function buildProgram() {
116150
116265
  await handleMemoryDismiss2(ids, opts);
116151
116266
  }
116152
116267
  );
116268
+ memory.command("drop <number> <path>").description(
116269
+ "Drop one proposed record from an open memory PR. When the PR merges, the record's statements are rejected and its memories wait again"
116270
+ ).option("--json", "Output JSON").action(async (number2, path2, opts) => {
116271
+ const { handleMemoryDrop: handleMemoryDrop2 } = await Promise.resolve().then(() => (init_memory2(), memory_exports));
116272
+ await handleMemoryDrop2(number2, path2, opts);
116273
+ });
116153
116274
  memory.command("import <files...>").description(
116154
116275
  "Read Markdown files into steering records with a kind and a force for each statement. Previews unless --yes."
116155
116276
  ).option(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxagen/cli",
3
- "version": "2.1.4-430",
3
+ "version": "2.1.4-438",
4
4
  "description": "Oxagen governance CLI — spend, lineage, grounding, credentials, and audit (agentic coding lives in the stella CLI)",
5
5
  "type": "module",
6
6
  "bin": {