agent-valley 2.2.1 → 2.3.1

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/index.js CHANGED
@@ -6439,6 +6439,72 @@ var init_zod = __esm(() => {
6439
6439
  init_external();
6440
6440
  });
6441
6441
 
6442
+ // ../../packages/core/src/oma/skill-matrix-schema.ts
6443
+ var hash, name, bounded, path, skillCompatibilityConfigSchema, skillCompatibilityPolicySchema, omaConfigSchema, matrixSkillSchema, matrixReportSchema;
6444
+ var init_skill_matrix_schema = __esm(() => {
6445
+ init_zod();
6446
+ hash = string2().regex(/^[a-f0-9]{64}$/);
6447
+ name = string2().regex(/^[a-z0-9][a-z0-9-]{0,127}$/);
6448
+ bounded = string2().trim().min(1).max(2000);
6449
+ path = string2().min(1).max(4096).refine((value) => !value.includes("\x00"));
6450
+ skillCompatibilityConfigSchema = strictObject({
6451
+ report_path: path,
6452
+ max_age_hours: number2().finite().positive().max(8760).default(168),
6453
+ mode: _enum(["warn", "require"])
6454
+ });
6455
+ skillCompatibilityPolicySchema = strictObject({
6456
+ reportPath: path,
6457
+ maxAgeHours: number2().finite().positive().max(8760),
6458
+ mode: _enum(["warn", "require"])
6459
+ });
6460
+ omaConfigSchema = strictObject({
6461
+ mode: _enum(["off", "strict"]).default("off"),
6462
+ skill_compatibility: skillCompatibilityConfigSchema.optional()
6463
+ });
6464
+ matrixSkillSchema = object({
6465
+ name,
6466
+ hash,
6467
+ caseId: bounded,
6468
+ requiredFiles: array(path).min(1).max(500),
6469
+ missingFiles: array(path).max(500),
6470
+ excludedReferences: array(object({ path, reason: bounded })).max(500)
6471
+ });
6472
+ matrixReportSchema = object({
6473
+ schemaVersion: literal(1),
6474
+ kind: literal("skill-compatibility-matrix"),
6475
+ mode: _enum(["plan", "live"]),
6476
+ status: _enum(["planned", "completed", "cancelled", "interrupted"]),
6477
+ createdAt: exports_iso.datetime(),
6478
+ omaVersion: bounded,
6479
+ host: object({ platform: bounded, arch: bounded, node: bounded }),
6480
+ suiteHash: hash,
6481
+ sourceKind: _enum(["synthetic", "installed"]),
6482
+ delivery: _enum(["native", "injected"]),
6483
+ auditScope: _enum(["fixture-contract", "read-reference"]),
6484
+ protocolVersion: literal("oma-skill-matrix-v2"),
6485
+ bundle: object({ hash, skills: array(matrixSkillSchema).min(1).max(100) }).optional(),
6486
+ cases: array(object({ id: bounded, skill: name })).max(100),
6487
+ models: object({ claude: bounded.nullable(), codex: bounded.nullable() }),
6488
+ cells: array(object({
6489
+ caseId: bounded,
6490
+ skill: name,
6491
+ vendor: _enum(["claude", "codex"]),
6492
+ status: _enum(["pass", "fail", "unverifiable", "error"]),
6493
+ contentHash: hash,
6494
+ checks: array(object({
6495
+ id: bounded,
6496
+ status: _enum(["pass", "fail", "unverifiable"]),
6497
+ detail: bounded,
6498
+ proof: _enum(["read", "canary"]).optional()
6499
+ })).max(1000),
6500
+ nativeActivation: _enum(["observed", "unobserved"]),
6501
+ cliVersion: string2().regex(/^[\w .()+/-]{1,160}$/).nullable(),
6502
+ model: bounded.nullable(),
6503
+ durationMs: number2().finite().nonnegative()
6504
+ })).max(200)
6505
+ });
6506
+ });
6507
+
6442
6508
  // ../../packages/core/src/config/task-schema.ts
6443
6509
  var reportPath, taskSchema, resolvedTaskSchema;
6444
6510
  var init_task_schema = __esm(() => {
@@ -6896,6 +6962,7 @@ var init_execution = __esm(() => {
6896
6962
  var actorType, text, amount, routingCandidateSchema, chiefOperatingPolicySchema, operatingRunSchema, routeEvidenceSchema, reviewDecisionSchema, chiefOperationsSchema;
6897
6963
  var init_operations = __esm(() => {
6898
6964
  init_zod();
6965
+ init_skill_matrix_schema();
6899
6966
  actorType = string2().regex(/^[a-z0-9][a-z0-9-]{0,127}$/);
6900
6967
  text = string2().trim().min(1).max(2000);
6901
6968
  amount = number2().finite().nonnegative();
@@ -6914,6 +6981,7 @@ var init_operations = __esm(() => {
6914
6981
  reviewVendor: _enum(["prefer", "require", "off"]),
6915
6982
  readyActors: array(actorType).max(20).optional(),
6916
6983
  memory: boolean2(),
6984
+ skillCompatibility: skillCompatibilityPolicySchema.optional(),
6917
6985
  metricTargets: array(strictObject({
6918
6986
  name: text,
6919
6987
  unit: text.optional(),
@@ -7232,7 +7300,7 @@ function chiefExecutionPolicy(config) {
7232
7300
  autoResume: execution.auto_resume
7233
7301
  } : {});
7234
7302
  }
7235
- function chiefOperatingPolicy(config, readyActors, automatic = true) {
7303
+ function chiefOperatingPolicy(config, readyActors, automatic = true, skillCompatibility) {
7236
7304
  return chiefOperatingPolicySchema.parse({
7237
7305
  routing: config.routing ? {
7238
7306
  candidates: config.routing.candidates.map((item) => ({
@@ -7247,7 +7315,8 @@ function chiefOperatingPolicy(config, readyActors, automatic = true) {
7247
7315
  reviewVendor: config.review_vendor ?? "prefer",
7248
7316
  memory: config.memory ?? true,
7249
7317
  metricTargets: config.metric_targets,
7250
- readyActors
7318
+ readyActors,
7319
+ skillCompatibility
7251
7320
  });
7252
7321
  }
7253
7322
  function chiefCapturePolicy(config) {
@@ -14575,7 +14644,7 @@ function mergeConfigs(global2, project, env) {
14575
14644
  tunnel: buildTunnelConfig(project),
14576
14645
  verify: buildVerifyConfig(project),
14577
14646
  task: project?.task?.kind === "analysis" ? { kind: "analysis", reportPath: project.task.report_path } : { kind: "code" },
14578
- oma: { mode: project?.oma?.mode ?? "off" },
14647
+ oma: project?.oma ?? { mode: "off" },
14579
14648
  chief: global2?.chief || project?.chief ? mergeChiefConfig(global2?.chief, project?.chief) : undefined
14580
14649
  };
14581
14650
  }
@@ -14613,6 +14682,7 @@ Symphony cannot start until all config errors are resolved.`);
14613
14682
  var globalConfigSchema, projectConfigSchema, githubConfigSchema, mergedConfigSchema;
14614
14683
  var init_yaml_loader = __esm(() => {
14615
14684
  init_zod();
14685
+ init_skill_matrix_schema();
14616
14686
  init_actor_schema();
14617
14687
  init_budget_schema();
14618
14688
  init_chief_schema();
@@ -14706,7 +14776,7 @@ var init_yaml_loader = __esm(() => {
14706
14776
  tunnel: tunnelProjectSchema,
14707
14777
  verify: verifyProjectSchema,
14708
14778
  task: taskSchema.optional(),
14709
- oma: object({ mode: _enum(["off", "strict"]).default("off") }).optional(),
14779
+ oma: omaConfigSchema.optional(),
14710
14780
  chief: chiefConfigSchema.optional()
14711
14781
  }).strict().overwrite(normalizeActorDefaults);
14712
14782
  githubConfigSchema = object({
@@ -14775,7 +14845,7 @@ var init_yaml_loader = __esm(() => {
14775
14845
  tunnel: tunnelMergedSchema,
14776
14846
  verify: verifyMergedSchema,
14777
14847
  task: resolvedTaskSchema.optional(),
14778
- oma: object({ mode: _enum(["off", "strict"]) }).optional(),
14848
+ oma: omaConfigSchema.optional(),
14779
14849
  chief: chiefConfigSchema.optional()
14780
14850
  }).superRefine((cfg, ctx) => {
14781
14851
  if (cfg.trackerKind === "linear") {
@@ -20724,7 +20794,7 @@ var init_readdirp = __esm(() => {
20724
20794
 
20725
20795
  // ../../node_modules/.bun/chokidar@5.0.0/node_modules/chokidar/handler.js
20726
20796
  import { watch as fs_watch, unwatchFile, watchFile } from "node:fs";
20727
- import { realpath as fsrealpath, lstat as lstat18, open as open11, stat as stat4 } from "node:fs/promises";
20797
+ import { realpath as fsrealpath, lstat as lstat18, open as open12, stat as stat4 } from "node:fs/promises";
20728
20798
  import { type as osType } from "node:os";
20729
20799
  import * as sp from "node:path";
20730
20800
  function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
@@ -20755,9 +20825,9 @@ class NodeFsHandler {
20755
20825
  _watchWithNodeFs(path, listener) {
20756
20826
  const opts = this.fsw.options;
20757
20827
  const directory = sp.dirname(path);
20758
- const basename2 = sp.basename(path);
20828
+ const basename = sp.basename(path);
20759
20829
  const parent = this.fsw._getWatchedDir(directory);
20760
- parent.add(basename2);
20830
+ parent.add(basename);
20761
20831
  const absolutePath = sp.resolve(path);
20762
20832
  const options = {
20763
20833
  persistent: opts.persistent
@@ -20767,7 +20837,7 @@ class NodeFsHandler {
20767
20837
  let closer;
20768
20838
  if (opts.usePolling) {
20769
20839
  const enableBin = opts.interval !== opts.binaryInterval;
20770
- options.interval = enableBin && isBinaryPath(basename2) ? opts.binaryInterval : opts.interval;
20840
+ options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;
20771
20841
  closer = setFsWatchFileListener(path, absolutePath, options, {
20772
20842
  listener,
20773
20843
  rawEmitter: this.fsw._emitRaw
@@ -20786,10 +20856,10 @@ class NodeFsHandler {
20786
20856
  return;
20787
20857
  }
20788
20858
  const dirname = sp.dirname(file);
20789
- const basename2 = sp.basename(file);
20859
+ const basename = sp.basename(file);
20790
20860
  const parent = this.fsw._getWatchedDir(dirname);
20791
20861
  let prevStats = stats;
20792
- if (parent.has(basename2))
20862
+ if (parent.has(basename))
20793
20863
  return;
20794
20864
  const listener = async (path, newStats) => {
20795
20865
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
@@ -20814,9 +20884,9 @@ class NodeFsHandler {
20814
20884
  prevStats = newStats;
20815
20885
  }
20816
20886
  } catch (error) {
20817
- this.fsw._remove(dirname, basename2);
20887
+ this.fsw._remove(dirname, basename);
20818
20888
  }
20819
- } else if (parent.has(basename2)) {
20889
+ } else if (parent.has(basename)) {
20820
20890
  const at = newStats.atimeMs;
20821
20891
  const mt = newStats.mtimeMs;
20822
20892
  if (!at || at <= mt || mt !== prevStats.mtimeMs) {
@@ -21066,7 +21136,7 @@ var STR_DATA = "data", STR_END = "end", STR_CLOSE = "close", EMPTY_FN = () => {}
21066
21136
  cont.watcherUnusable = true;
21067
21137
  if (isWindows && error.code === "EPERM") {
21068
21138
  try {
21069
- const fd = await open11(path, "r");
21139
+ const fd = await open12(path, "r");
21070
21140
  await fd.close();
21071
21141
  broadcastErr(error);
21072
21142
  } catch (err) {}
@@ -22448,8 +22518,8 @@ function canonicalConfig(config) {
22448
22518
  // src/agent-provisioning.ts
22449
22519
  import { spawn as spawn17 } from "node:child_process";
22450
22520
  import { mkdtempSync, rmSync as rmSync2 } from "node:fs";
22451
- import { homedir as homedir7, tmpdir as tmpdir4 } from "node:os";
22452
- import { delimiter as delimiter3, join as join46 } from "node:path";
22521
+ import { homedir as homedir8, tmpdir as tmpdir4 } from "node:os";
22522
+ import { delimiter as delimiter3, join as join47 } from "node:path";
22453
22523
  function runTerminalCommand(request, spawnCommand = spawn17) {
22454
22524
  return new Promise((resolve) => {
22455
22525
  let child;
@@ -22492,13 +22562,13 @@ function runTerminalCommand(request, spawnCommand = spawn17) {
22492
22562
  function defaults() {
22493
22563
  return {
22494
22564
  platform: process.platform,
22495
- home: homedir7(),
22565
+ home: homedir8(),
22496
22566
  env: process.env,
22497
22567
  resolveBinary: resolveBinaryPath,
22498
22568
  discover: discoverAgents,
22499
22569
  runCommand: runTerminalCommand,
22500
22570
  supportsLoginCommand: (agent, path, env) => supportsNativeLoginCommand(agent, path, { env }),
22501
- makeTempDir: () => mkdtempSync(join46(tmpdir4(), "av-agent-install-")),
22571
+ makeTempDir: () => mkdtempSync(join47(tmpdir4(), "av-agent-install-")),
22502
22572
  removeTempDir: (path) => rmSync2(path, { recursive: true, force: true })
22503
22573
  };
22504
22574
  }
@@ -22525,7 +22595,7 @@ async function runOfficialInstaller(installerUrl, deps, options = {}) {
22525
22595
  let directory;
22526
22596
  try {
22527
22597
  directory = deps.makeTempDir();
22528
- const scriptPath = join46(directory, "install.sh");
22598
+ const scriptPath = join47(directory, "install.sh");
22529
22599
  const request = { env: options.env ?? deps.env, ...options.cwd ? { cwd: options.cwd } : {} };
22530
22600
  const download = await deps.runCommand({
22531
22601
  command: curl,
@@ -22596,7 +22666,7 @@ async function installChiefAgent(agent, overrides = {}) {
22596
22666
  const install = await runOfficialInstaller(plan.installerUrl, deps);
22597
22667
  if (!install.success)
22598
22668
  return commandFailure(install.stage === "download" ? "Installer download" : "Installation", install, plan.documentation);
22599
- const localBin = join46(deps.home, ".local", "bin");
22669
+ const localBin = join47(deps.home, ".local", "bin");
22600
22670
  const pathParts = (deps.env.PATH ?? "").split(delimiter3);
22601
22671
  if (!pathParts.includes(localBin))
22602
22672
  deps.env.PATH = [localBin, ...pathParts.filter(Boolean)].join(delimiter3);
@@ -22698,17 +22768,17 @@ var init_agent_provisioning = __esm(() => {
22698
22768
  // src/oma-provisioning.ts
22699
22769
  import { mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
22700
22770
  import { chmod as chmod4, lstat as lstat19, readdir as readdir12, readFile as readFile16, realpath as realpath25, unlink as unlink8, writeFile as writeFile14 } from "node:fs/promises";
22701
- import { homedir as homedir8, tmpdir as tmpdir5 } from "node:os";
22702
- import { delimiter as delimiter4, isAbsolute as isAbsolute15, join as join47, relative as relative14, resolve as resolve27 } from "node:path";
22771
+ import { homedir as homedir9, tmpdir as tmpdir5 } from "node:os";
22772
+ import { delimiter as delimiter4, isAbsolute as isAbsolute16, join as join48, relative as relative15, resolve as resolve29 } from "node:path";
22703
22773
  function defaults2() {
22704
- const home = homedir8();
22774
+ const home = homedir9();
22705
22775
  return {
22706
22776
  platform: process.platform,
22707
22777
  home,
22708
22778
  env: process.env,
22709
- resolveBinary: (name) => resolveBinaryPath(name, name === "bun" ? [join47(process.env.BUN_INSTALL ?? join47(home, ".bun"), "bin", "bun")] : []),
22779
+ resolveBinary: (name) => resolveBinaryPath(name, name === "bun" ? [join48(process.env.BUN_INSTALL ?? join48(home, ".bun"), "bin", "bun")] : []),
22710
22780
  runCommand: runTerminalCommand,
22711
- makeTempDir: () => mkdtempSync2(join47(tmpdir5(), "av-oma-install-")),
22781
+ makeTempDir: () => mkdtempSync2(join48(tmpdir5(), "av-oma-install-")),
22712
22782
  removeTempDir: (path) => rmSync3(path, { recursive: true, force: true })
22713
22783
  };
22714
22784
  }
@@ -22729,7 +22799,7 @@ async function present(path) {
22729
22799
  }
22730
22800
  async function installedVersion2(skills) {
22731
22801
  try {
22732
- const marker = JSON.parse(await readFile16(join47(skills, "_version.json"), "utf8"));
22802
+ const marker = JSON.parse(await readFile16(join48(skills, "_version.json"), "utf8"));
22733
22803
  return marker.schemaVersion === 2 && marker.mode === "project" && typeof marker.version === "string" && /^\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?$/.test(marker.version) ? marker.version : null;
22734
22804
  } catch {
22735
22805
  return null;
@@ -22738,7 +22808,7 @@ async function installedVersion2(skills) {
22738
22808
  async function snapshotConfig(agents) {
22739
22809
  const snapshots = [];
22740
22810
  for (const name of CUSTOM_CONFIG_NAMES) {
22741
- const path = join47(agents, name);
22811
+ const path = join48(agents, name);
22742
22812
  if (!await present(path))
22743
22813
  continue;
22744
22814
  const file = await lstat19(path);
@@ -22758,10 +22828,10 @@ async function restoreConfig(agents, snapshots) {
22758
22828
  ["oma-config.yaml", "oma-config.cue"],
22759
22829
  ["oma-config.local.yaml", "oma-config.local.cue"]
22760
22830
  ]) {
22761
- if (!pair.some((name) => original.has(join47(agents, name))))
22831
+ if (!pair.some((name) => original.has(join48(agents, name))))
22762
22832
  continue;
22763
22833
  for (const name of pair) {
22764
- const path = join47(agents, name);
22834
+ const path = join48(agents, name);
22765
22835
  if (!original.has(path))
22766
22836
  await unlink8(path).catch((error) => {
22767
22837
  if (error.code !== "ENOENT")
@@ -22771,17 +22841,17 @@ async function restoreConfig(agents, snapshots) {
22771
22841
  }
22772
22842
  }
22773
22843
  async function workspacePath(input) {
22774
- if (!input.trim() || !isAbsolute15(input))
22844
+ if (!input.trim() || !isAbsolute16(input))
22775
22845
  return null;
22776
- const root = resolve27(input);
22846
+ const root = resolve29(input);
22777
22847
  if (!await directory2(root))
22778
22848
  return null;
22779
- for (const path of [join47(root, ".agents"), join47(root, ".agents", "skills")]) {
22849
+ for (const path of [join48(root, ".agents"), join48(root, ".agents", "skills")]) {
22780
22850
  if (!await present(path))
22781
22851
  continue;
22782
22852
  const actual = await realpath25(path);
22783
- const location = relative14(await realpath25(root), actual);
22784
- if (location === ".." || location.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute15(location))
22853
+ const location = relative15(await realpath25(root), actual);
22854
+ if (location === ".." || location.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute16(location))
22785
22855
  return null;
22786
22856
  }
22787
22857
  return root;
@@ -22791,7 +22861,7 @@ async function inspectOma(workspaceRoot, _overrides = {}) {
22791
22861
  const root = await workspacePath(workspaceRoot);
22792
22862
  if (!root)
22793
22863
  return { success: false, message: "Choose an existing absolute workspace with project-local OMA files." };
22794
- const skills = join47(root, ".agents", "skills");
22864
+ const skills = join48(root, ".agents", "skills");
22795
22865
  const version = await installedVersion2(skills);
22796
22866
  if (!version)
22797
22867
  throw new Error("Invalid installed metadata");
@@ -22799,7 +22869,7 @@ async function inspectOma(workspaceRoot, _overrides = {}) {
22799
22869
  if (!entries.length)
22800
22870
  throw new Error("No installed skills");
22801
22871
  for (const entry of entries) {
22802
- if (!entry.isDirectory() || !(await lstat19(join47(skills, entry.name, "SKILL.md"))).isFile())
22872
+ if (!entry.isDirectory() || !(await lstat19(join48(skills, entry.name, "SKILL.md"))).isFile())
22803
22873
  throw new Error("Incomplete installed skill");
22804
22874
  }
22805
22875
  return {
@@ -22847,16 +22917,16 @@ async function prepareOma(workspaceRoot, overrides = {}) {
22847
22917
  delete environment.OMA_YES;
22848
22918
  environment.CI = "true";
22849
22919
  const paths = [
22850
- deps.env.BUN_INSTALL_BIN ?? join47(deps.env.BUN_INSTALL ?? join47(deps.home, ".bun"), "bin"),
22851
- join47(deps.home, ".local", "bin")
22920
+ deps.env.BUN_INSTALL_BIN ?? join48(deps.env.BUN_INSTALL ?? join48(deps.home, ".bun"), "bin"),
22921
+ join48(deps.home, ".local", "bin")
22852
22922
  ];
22853
22923
  environment.PATH = [...new Set([...paths, ...(environment.PATH ?? "").split(delimiter4).filter(Boolean)])].join(delimiter4);
22854
22924
  const request = { command: bun, env: environment, cwd: root, timeoutMs: 300000 };
22855
22925
  const latest = await deps.runCommand({ ...request, args: ["install", "--global", LATEST_PACKAGE] });
22856
22926
  if (!latest.success)
22857
22927
  return failure3("OMA CLI update", latest);
22858
- const agents = join47(root, ".agents");
22859
- const existing = await installedVersion2(join47(agents, "skills")) !== null || await directory2(join47(agents, "skills")) && (await present(join47(agents, "oma-config.yaml")) || await present(join47(agents, "mcp.json")) || await directory2(join47(agents, "workflows")));
22928
+ const agents = join48(root, ".agents");
22929
+ const existing = await installedVersion2(join48(agents, "skills")) !== null || await directory2(join48(agents, "skills")) && (await present(join48(agents, "oma-config.yaml")) || await present(join48(agents, "mcp.json")) || await directory2(join48(agents, "workflows")));
22860
22930
  const custom = await snapshotConfig(agents);
22861
22931
  const args = existing ? ["update", "--yes", "--with-new-skills", "--all"] : ["install"];
22862
22932
  let installed;
@@ -24343,9 +24413,9 @@ var init_ui = __esm(() => {
24343
24413
 
24344
24414
  // src/setup/workspace-step.ts
24345
24415
  import { statSync as statSync3 } from "node:fs";
24346
- import { isAbsolute as isAbsolute16 } from "node:path";
24416
+ import { isAbsolute as isAbsolute17 } from "node:path";
24347
24417
  async function validateOrderWorkspace(path) {
24348
- if (!isAbsolute16(path))
24418
+ if (!isAbsolute17(path))
24349
24419
  return "Set workspace.root in av.yaml to an absolute Git repository path.";
24350
24420
  try {
24351
24421
  if (!statSync3(path).isDirectory())
@@ -24372,7 +24442,7 @@ async function stepWorkspace(ctx, step, total) {
24372
24442
  validate: (v) => {
24373
24443
  if (!v?.trim())
24374
24444
  return "Required";
24375
- if (!isAbsolute16(v.trim()))
24445
+ if (!isAbsolute17(v.trim()))
24376
24446
  return "Must be an absolute path";
24377
24447
  }
24378
24448
  });
@@ -24399,7 +24469,7 @@ var init_workspace_step = __esm(() => {
24399
24469
 
24400
24470
  // src/setup/noninteractive-config.ts
24401
24471
  import { lstat as lstat20, realpath as realpath26 } from "node:fs/promises";
24402
- import { isAbsolute as isAbsolute17, join as join48, parse as parsePath, resolve as resolve28 } from "node:path";
24472
+ import { isAbsolute as isAbsolute18, join as join49, parse as parsePath, resolve as resolve30 } from "node:path";
24403
24473
  function validateNoninteractiveOptions(options) {
24404
24474
  if (!options.yes || options.edit || options.mode !== undefined && options.mode !== "order")
24405
24475
  throw new Error("Use av setup --yes only for local order setup; --edit and --mode tracker require interactive setup.");
@@ -24442,7 +24512,7 @@ function selectChief(options, deps, project, global2) {
24442
24512
  const globalActor = actor(global2);
24443
24513
  const selected = options.actor ?? runtime?.actorType ?? projectActor.type ?? globalActor.type;
24444
24514
  if (!selected)
24445
- throw new Error(`actor.type is missing in ${join48(deps.projectRoot, "av.yaml")} and ${deps.globalConfigPath}, and the current agent runtime is unknown. Rerun av setup --yes --actor <current-vendor> --model <current-model-or-empty>.`);
24515
+ throw new Error(`actor.type is missing in ${join49(deps.projectRoot, "av.yaml")} and ${deps.globalConfigPath}, and the current agent runtime is unknown. Rerun av setup --yes --actor <current-vendor> --model <current-model-or-empty>.`);
24446
24516
  const actorType = selected;
24447
24517
  const actorSource = options.actor !== undefined ? "explicit" : runtime ? "runtime" : projectActor.type ? "project" : "global";
24448
24518
  const previousType = projectActor.type ?? globalActor.type;
@@ -24480,14 +24550,14 @@ async function prepareNoninteractiveConfig(options, deps) {
24480
24550
  validateNoninteractiveOptions(options);
24481
24551
  let projectRoot;
24482
24552
  try {
24483
- projectRoot = await realpath26(resolve28(deps.projectRoot));
24553
+ projectRoot = await realpath26(resolve30(deps.projectRoot));
24484
24554
  if (!(await lstat20(projectRoot)).isDirectory())
24485
24555
  throw new Error("not a directory");
24486
24556
  } catch {
24487
24557
  throw new Error(`AV configuration directory ${deps.projectRoot} does not exist. Run av setup from an existing directory.`);
24488
24558
  }
24489
- const globalPath = resolve28(deps.globalConfigPath);
24490
- const projectPath = join48(projectRoot, "av.yaml");
24559
+ const globalPath = resolve30(deps.globalConfigPath);
24560
+ const projectPath = join49(projectRoot, "av.yaml");
24491
24561
  const project = await configFile(projectPath, projectConfigSchema);
24492
24562
  const global2 = await configFile(globalPath, globalConfigSchema);
24493
24563
  const chief = selectChief(options, { ...deps, projectRoot, globalConfigPath: globalPath }, project.raw, global2.raw);
@@ -24504,7 +24574,7 @@ async function prepareNoninteractiveConfig(options, deps) {
24504
24574
  }
24505
24575
  const savedWorkspace = project.raw.workspace?.root;
24506
24576
  const selectedWorkspace = options.workspace ?? savedWorkspace ?? projectRoot;
24507
- const workspacePath = isAbsolute17(selectedWorkspace) ? selectedWorkspace : resolve28(projectRoot, selectedWorkspace);
24577
+ const workspacePath = isAbsolute18(selectedWorkspace) ? selectedWorkspace : resolve30(projectRoot, selectedWorkspace);
24508
24578
  const workspaceError = await validateOrderWorkspace(workspacePath);
24509
24579
  if (workspaceError)
24510
24580
  throw new Error(workspaceError);
@@ -24539,7 +24609,7 @@ var init_noninteractive_config = __esm(() => {
24539
24609
  });
24540
24610
 
24541
24611
  // src/setup/noninteractive.ts
24542
- import { join as join49, parse as parsePath2, resolve as resolve29 } from "node:path";
24612
+ import { join as join50, parse as parsePath2, resolve as resolve31 } from "node:path";
24543
24613
  function rerunCommand(result, options) {
24544
24614
  const quote = (value) => `'${value.replace(/'/g, "'\\''")}'`;
24545
24615
  return `cd ${quote(result.projectRoot)} && av setup --yes --actor ${result.chief.actorType} --model ${quote(result.chief.model ?? "")} --workspace ${quote(result.workspace ?? result.projectRoot)} --oma ${options.oma ?? "prepare"} --json`;
@@ -24550,11 +24620,11 @@ async function setupNoninteractive(options, overrides = {}) {
24550
24620
  version: 1,
24551
24621
  status: "failed",
24552
24622
  exitCode: 1,
24553
- projectRoot: resolve29(deps.projectRoot),
24623
+ projectRoot: resolve31(deps.projectRoot),
24554
24624
  workspace: null,
24555
24625
  config: {
24556
- project: join49(resolve29(deps.projectRoot), "av.yaml"),
24557
- global: resolve29(deps.globalConfigPath),
24626
+ project: join50(resolve31(deps.projectRoot), "av.yaml"),
24627
+ global: resolve31(deps.globalConfigPath),
24558
24628
  saved: false
24559
24629
  },
24560
24630
  chief: {
@@ -25035,7 +25105,7 @@ var init_container_step = __esm(() => {
25035
25105
  });
25036
25106
 
25037
25107
  // src/setup/metric-step.ts
25038
- import { isAbsolute as isAbsolute18 } from "node:path";
25108
+ import { isAbsolute as isAbsolute19 } from "node:path";
25039
25109
  async function text12(message, initialValue, validate) {
25040
25110
  const value = await text10({
25041
25111
  message: `${message} (:back goes back)`,
@@ -25119,7 +25189,7 @@ async function stepMetrics(ctx) {
25119
25189
  draft.token_env = token;
25120
25190
  } else {
25121
25191
  const file = await text12("Repository-relative JSON file", old?.file ?? "metrics/revenue.json", (value) => {
25122
- if (!value || value.length > 2000 || isAbsolute18(value) || /^[A-Za-z]:/.test(value) || value.startsWith("\\") || value.split(/[\\/]/).includes(".."))
25192
+ if (!value || value.length > 2000 || isAbsolute19(value) || /^[A-Za-z]:/.test(value) || value.startsWith("\\") || value.split(/[\\/]/).includes(".."))
25123
25193
  return "Use a relative file inside the repository, without ..";
25124
25194
  });
25125
25195
  if (navigated2(file))
@@ -25127,18 +25197,18 @@ async function stepMetrics(ctx) {
25127
25197
  draft.file = file;
25128
25198
  }
25129
25199
  for (const field of ["value_path", "timestamp_path", "unit_path"]) {
25130
- const value = await text12(`JSON ${field}`, old?.[field] ?? field.replace("_path", ""), path3);
25200
+ const value = await text12(`JSON ${field}`, old?.[field] ?? field.replace("_path", ""), path4);
25131
25201
  if (navigated2(value))
25132
25202
  return value;
25133
25203
  draft[field] = value;
25134
25204
  }
25135
- const start = await text12("JSON measurement window start path (optional; blank omits window)", old?.window_start_path ?? "", (value) => value ? path3(value) : undefined);
25205
+ const start = await text12("JSON measurement window start path (optional; blank omits window)", old?.window_start_path ?? "", (value) => value ? path4(value) : undefined);
25136
25206
  if (navigated2(start))
25137
25207
  return start;
25138
25208
  delete draft.window_start_path;
25139
25209
  delete draft.window_end_path;
25140
25210
  if (start) {
25141
- const end = await text12("JSON measurement window end path", old?.window_end_path ?? "window.end", path3);
25211
+ const end = await text12("JSON measurement window end path", old?.window_end_path ?? "window.end", path4);
25142
25212
  if (navigated2(end))
25143
25213
  return end;
25144
25214
  draft.window_start_path = start;
@@ -25184,7 +25254,7 @@ async function stepMetrics(ctx) {
25184
25254
  ctx.chiefChanged = true;
25185
25255
  log2.info("Metric settings are saved after confirmation. Measurements are collected at mission runtime; setup does not contact the source. Set --duration or chief.execution.max_duration_sec long enough for work and the full measurement/observation windows. The default mission limit is 86400 seconds including waits; Stripe's default measurement window is also 86400 seconds.");
25186
25256
  }
25187
- var envName3 = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value), navigated2 = (value) => typeof value !== "string", required2 = (limit) => (value) => value && value.length <= limit ? undefined : `Enter 1 to ${limit} characters.`, environment = (optional = false) => (value) => optional && !value || envName3(value) ? undefined : "Enter an environment variable name, never a token or URL.", number4 = (minimum, maximum) => (value) => value && Number.isInteger(Number(value)) && Number(value) >= minimum && Number(value) <= maximum ? undefined : `Enter a whole number from ${minimum} to ${maximum}.`, path3 = (value) => {
25257
+ var envName3 = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value), navigated2 = (value) => typeof value !== "string", required2 = (limit) => (value) => value && value.length <= limit ? undefined : `Enter 1 to ${limit} characters.`, environment = (optional = false) => (value) => optional && !value || envName3(value) ? undefined : "Enter an environment variable name, never a token or URL.", number4 = (minimum, maximum) => (value) => value && Number.isInteger(Number(value)) && Number(value) >= minimum && Number(value) <= maximum ? undefined : `Enter a whole number from ${minimum} to ${maximum}.`, path4 = (value) => {
25188
25258
  const result = metricSourceSchema.shape.value_path.safeParse(value);
25189
25259
  return result.success ? undefined : "Use dot-separated JSON keys or array indexes, without prototype keys.";
25190
25260
  };
@@ -27577,8 +27647,8 @@ var init_issue = __esm(() => {
27577
27647
 
27578
27648
  // src/login.ts
27579
27649
  import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "node:fs";
27580
- import { homedir as homedir9 } from "node:os";
27581
- import { join as join50 } from "node:path";
27650
+ import { homedir as homedir10 } from "node:os";
27651
+ import { join as join51 } from "node:path";
27582
27652
  function ensureConfigDir() {
27583
27653
  if (!existsSync9(CONFIG_DIR)) {
27584
27654
  mkdirSync4(CONFIG_DIR, { recursive: true, mode: 448 });
@@ -27753,8 +27823,8 @@ var import_picocolors14, CONFIG_DIR, CREDENTIALS_FILE;
27753
27823
  var init_login = __esm(() => {
27754
27824
  init_dist6();
27755
27825
  import_picocolors14 = __toESM(require_picocolors(), 1);
27756
- CONFIG_DIR = join50(homedir9(), ".agent-valley");
27757
- CREDENTIALS_FILE = join50(CONFIG_DIR, "credentials.json");
27826
+ CONFIG_DIR = join51(homedir10(), ".agent-valley");
27827
+ CREDENTIALS_FILE = join51(CONFIG_DIR, "credentials.json");
27758
27828
  });
27759
27829
 
27760
27830
  // src/index.ts
@@ -27762,7 +27832,7 @@ init_project_config_path();
27762
27832
  init_yaml_loader();
27763
27833
  import { spawn as spawn24, spawnSync as spawnSync5 } from "node:child_process";
27764
27834
  import { existsSync as existsSync10, unlinkSync as unlinkSync2 } from "node:fs";
27765
- import { resolve as resolve30 } from "node:path";
27835
+ import { resolve as resolve32 } from "node:path";
27766
27836
 
27767
27837
  // ../../packages/core/src/version.ts
27768
27838
  import { readFileSync as readFileSync2 } from "node:fs";
@@ -27872,7 +27942,7 @@ function humanReadableArgName(arg) {
27872
27942
  // ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/command.js
27873
27943
  import { EventEmitter } from "node:events";
27874
27944
  import childProcess from "node:child_process";
27875
- import path from "node:path";
27945
+ import path2 from "node:path";
27876
27946
  import fs from "node:fs";
27877
27947
  import process2 from "node:process";
27878
27948
  import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
@@ -29016,10 +29086,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
29016
29086
  args = args.slice();
29017
29087
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
29018
29088
  function findFile(baseDir, baseName) {
29019
- const localBin = path.resolve(baseDir, baseName);
29089
+ const localBin = path2.resolve(baseDir, baseName);
29020
29090
  if (fs.existsSync(localBin))
29021
29091
  return localBin;
29022
- if (sourceExt.includes(path.extname(baseName)))
29092
+ if (sourceExt.includes(path2.extname(baseName)))
29023
29093
  return;
29024
29094
  const foundExt = sourceExt.find((ext) => fs.existsSync(`${localBin}${ext}`));
29025
29095
  if (foundExt)
@@ -29037,19 +29107,19 @@ Expecting one of '${allowedValues.join("', '")}'`);
29037
29107
  } catch {
29038
29108
  resolvedScriptPath = this._scriptPath;
29039
29109
  }
29040
- executableDir = path.resolve(path.dirname(resolvedScriptPath), executableDir);
29110
+ executableDir = path2.resolve(path2.dirname(resolvedScriptPath), executableDir);
29041
29111
  }
29042
29112
  if (executableDir) {
29043
29113
  let localFile = findFile(executableDir, executableFile);
29044
29114
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
29045
- const legacyName = path.basename(this._scriptPath, path.extname(this._scriptPath));
29115
+ const legacyName = path2.basename(this._scriptPath, path2.extname(this._scriptPath));
29046
29116
  if (legacyName !== this._name) {
29047
29117
  localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
29048
29118
  }
29049
29119
  }
29050
29120
  executableFile = localFile || executableFile;
29051
29121
  }
29052
- const launchWithNode = sourceExt.includes(path.extname(executableFile));
29122
+ const launchWithNode = sourceExt.includes(path2.extname(executableFile));
29053
29123
  let proc;
29054
29124
  if (process2.platform !== "win32") {
29055
29125
  if (launchWithNode) {
@@ -29640,13 +29710,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
29640
29710
  cmd.helpGroup(this._defaultCommandGroup);
29641
29711
  }
29642
29712
  nameFromFilename(filename) {
29643
- this._name = path.basename(filename, path.extname(filename));
29713
+ this._name = path2.basename(filename, path2.extname(filename));
29644
29714
  return this;
29645
29715
  }
29646
- executableDir(path2) {
29647
- if (path2 === undefined)
29716
+ executableDir(path) {
29717
+ if (path === undefined)
29648
29718
  return this._executableDir;
29649
- this._executableDir = path2;
29719
+ this._executableDir = path;
29650
29720
  return this;
29651
29721
  }
29652
29722
  helpInformation(contextOptions) {
@@ -29824,7 +29894,7 @@ var import_picocolors15 = __toESM(require_picocolors(), 1);
29824
29894
 
29825
29895
  // src/agent-client-commands.ts
29826
29896
  init_client_integrations();
29827
- import { resolve as resolve21 } from "node:path";
29897
+ import { resolve as resolve22 } from "node:path";
29828
29898
 
29829
29899
  // src/mcp-oauth.ts
29830
29900
  init_webapi();
@@ -48175,7 +48245,7 @@ async function startAvMcpHttp(api, options) {
48175
48245
  // src/mission-api.ts
48176
48246
  import { randomUUID as randomUUID17 } from "node:crypto";
48177
48247
  import { lstat as lstat15, readdir as readdir8, realpath as realpath21 } from "node:fs/promises";
48178
- import { isAbsolute as isAbsolute12, join as join37 } from "node:path";
48248
+ import { isAbsolute as isAbsolute13, join as join38 } from "node:path";
48179
48249
 
48180
48250
  // ../../packages/core/src/chief/reports.ts
48181
48251
  init_zod();
@@ -48938,7 +49008,7 @@ var sha256 = string2().regex(/^[a-f0-9]{64}$/);
48938
49008
  function safeVerificationPath(path) {
48939
49009
  return path.length > 0 && path.length <= 1024 && !isAbsolute2(path) && !/^[a-z]:/i.test(path) && !/[\\\0\r\n]/.test(path) && path.split("/").every((part) => part !== "" && part !== "." && part !== "..") && !/^(?:\.git(?:\/|$)|\.agent-valley(?:\/|$)|\.agents\/(?:state|results)(?:\/|$))/.test(path);
48940
49010
  }
48941
- var path2 = string2().refine(safeVerificationPath, "Use a literal relative product path inside the worktree.");
49011
+ var path3 = string2().refine(safeVerificationPath, "Use a literal relative product path inside the worktree.");
48942
49012
  var testPath = (name, nodeOnly = false) => safeVerificationPath(name) && !name.startsWith("-") && !/[*?{}]/.test(name) && !name.startsWith("node_modules/") && (nodeOnly ? /(?:\.test|\.spec)\.(?:js|mjs|cjs)$/ : /(?:\.test|\.spec)\.(?:[cm]?[jt]sx?)$/).test(name);
48943
49013
  function verificationCommandTestPaths(program, args) {
48944
49014
  if (program === "bun" && args[0] === "test")
@@ -48975,14 +49045,14 @@ function safeVerificationCommand(program, args) {
48975
49045
  var goalVerificationCheckSchema = discriminatedUnion("kind", [
48976
49046
  strictObject({
48977
49047
  kind: literal("file"),
48978
- path: path2,
49048
+ path: path3,
48979
49049
  minBytes: number2().int().min(1).max(4194304).default(1),
48980
49050
  contains: array(text4).min(1).max(10).optional(),
48981
49051
  sha256: sha256.optional()
48982
49052
  }),
48983
49053
  strictObject({
48984
49054
  kind: literal("json"),
48985
- path: path2,
49055
+ path: path3,
48986
49056
  pointer: string2().max(1024).refine((value) => value === "" || /^(?:\/(?:[^~]|~[01])*)+$/.test(value), {
48987
49057
  message: "Use an RFC 6901 JSON pointer such as /engines/node."
48988
49058
  }),
@@ -49444,16 +49514,29 @@ function routeEvidence(mission) {
49444
49514
  function price2(candidate) {
49445
49515
  return candidate.inputPerMillionUsd !== undefined && candidate.outputPerMillionUsd !== undefined ? candidate.inputPerMillionUsd + candidate.outputPerMillionUsd : Number.POSITIVE_INFINITY;
49446
49516
  }
49447
- function selectWorkActor(mission, actor, taskId) {
49517
+ function workActorCandidates(mission, actor, preserveExplicit = false) {
49448
49518
  const routing = mission.operatingPolicy?.routing;
49449
- if (!routing || actor.id === mission.chiefId || !mission.availableAgents && actor.model)
49519
+ if (!routing || actor.id === mission.chiefId || !mission.availableAgents && (actor.model || preserveExplicit))
49520
+ return [{ actorType: actor.agentType, model: actor.model }];
49521
+ const ready = mission.operatingPolicy?.readyActors ?? mission.availableAgents ?? [];
49522
+ return routing.candidates.filter((candidate) => ready.includes(candidate.actorType));
49523
+ }
49524
+ function selectWorkActor(mission, actor, taskId, compatibleRoutes) {
49525
+ const routing = mission.operatingPolicy?.routing;
49526
+ if (!routing || actor.id === mission.chiefId || !mission.availableAgents && (actor.model || compatibleRoutes)) {
49527
+ if (compatibleRoutes && !compatibleRoutes.has(routeKey({ actorType: actor.agentType, model: actor.model })))
49528
+ throw new Error("Skill compatibility required: the configured Actor/model has no current passing evidence. Refresh oma.skill_compatibility.report_path in av.yaml; explicit Actors are not rerouted.");
49450
49529
  return { actor, reason: "Preserved the configured Actor and explicit model." };
49530
+ }
49451
49531
  const ready = mission.operatingPolicy?.readyActors ?? mission.availableAgents ?? [];
49452
49532
  const candidates = routing.candidates.filter((candidate) => ready.includes(candidate.actorType));
49453
49533
  if (!candidates.length)
49454
49534
  throw new Error("No configured work routing candidate is ready. Install/login a candidate CLI or update chief.routing.candidates in av.yaml.");
49535
+ const compatible = compatibleRoutes ? candidates.filter((candidate) => compatibleRoutes.has(routeKey(candidate))) : candidates;
49536
+ if (!compatible.length)
49537
+ throw new Error("Skill compatibility required: no ready work candidate has current passing installed evidence. Refresh oma.skill_compatibility.report_path in av.yaml with explicit models before retrying.");
49455
49538
  const evidence = routeEvidence(mission);
49456
- const eligible = candidates.filter((candidate) => {
49539
+ const eligible = compatible.filter((candidate) => {
49457
49540
  const observed = evidence.find((item) => routeKey(item) === routeKey(candidate));
49458
49541
  return !observed || observed.samples < routing.minSamples || observed.successes / observed.samples >= routing.minSuccessRate;
49459
49542
  });
@@ -49515,6 +49598,10 @@ function operationsEvidence(mission) {
49515
49598
  pricingBasis: "Estimates from configured input/output prices and actual adapter-reported tokens; excludes unreported cache/reasoning/subagent usage and subscription billing.",
49516
49599
  routeQuality: routeEvidence(mission).slice(0, 20),
49517
49600
  reviewPolicy: mission.operatingPolicy?.reviewVendor ?? "legacy independent Actor",
49601
+ skillCompatibility: mission.operatingPolicy?.skillCompatibility ? {
49602
+ mode: mission.operatingPolicy.skillCompatibility.mode,
49603
+ recentChecks: mission.history.filter((entry) => entry.stage === "skill-compatibility").slice(-10)
49604
+ } : undefined,
49518
49605
  recentRuns: runs.slice(-20),
49519
49606
  crossVendorReviews: mission.operations?.reviewDecisions.slice(-20) ?? [],
49520
49607
  organizationContext: mission.organizationContext,
@@ -49530,6 +49617,10 @@ function operationsReportLines(mission) {
49530
49617
  `기록된 token·설정 단가 기반 부분 비용 추정 USD ${evidence.knownEstimatedCostUsd.toFixed(6)} / 비용 미확인 ${evidence.unknownCostRuns}회 / 전체 추정 ${evidence.totalEstimatedCostUsd === null ? "미확인" : `USD ${evidence.totalEstimatedCostUsd.toFixed(6)}`}`,
49531
49618
  `최근 독립 리뷰 배정: 다른 vendor ${evidence.crossVendorReviews.filter((review) => review.crossVendor).length}회 / 동일 vendor fallback ${evidence.crossVendorReviews.filter((review) => !review.crossVendor).length}회 / 실제 리뷰 통과 ${evidence.crossVendorReviews.filter((review) => review.outcome === "passed").length}회`,
49532
49619
  `vendor 리뷰 정책: ${evidence.reviewPolicy}`,
49620
+ ...evidence.skillCompatibility ? [
49621
+ `OMA 스킬 읽기·참조 정책: ${evidence.skillCompatibility.mode}; AV 실행 환경 또는 작업 품질 인증이 아닙니다.`,
49622
+ ...evidence.skillCompatibility.recentChecks.map((entry) => `${entry.at}: ${entry.message}`)
49623
+ ] : [],
49533
49624
  ...mission.organizationContext ? [
49534
49625
  `계획·리뷰에 제공한 조직 근거: 승인 memory ${mission.organizationContext.memories.length}개 / 과거 outcome ${mission.organizationContext.outcomes.length}개 / 기록된 metric sample ${mission.organizationContext.metrics.length}개`
49535
49626
  ] : [],
@@ -49557,15 +49648,15 @@ var chiefReportSchema = strictObject({
49557
49648
  checks: entries,
49558
49649
  remaining: entries
49559
49650
  });
49560
- function bounded(value, limit = 500) {
49651
+ function bounded2(value, limit = 500) {
49561
49652
  const content = value.trim();
49562
49653
  return content.length <= limit ? content : `${content.slice(0, limit - 8)}… [생략]`;
49563
49654
  }
49564
49655
  function compact(values, limit = 20) {
49565
49656
  if (values.length <= limit)
49566
- return values.map((value) => bounded(value)).filter(Boolean);
49657
+ return values.map((value) => bounded2(value)).filter(Boolean);
49567
49658
  return [
49568
- ...values.slice(0, limit - 1).map((value) => bounded(value)).filter(Boolean),
49659
+ ...values.slice(0, limit - 1).map((value) => bounded2(value)).filter(Boolean),
49569
49660
  `${values.length - limit + 1}개 항목 생략`
49570
49661
  ];
49571
49662
  }
@@ -49580,7 +49671,7 @@ function criteria(mission) {
49580
49671
  function incompleteReasons(mission) {
49581
49672
  const reasons = [];
49582
49673
  if (mission.error)
49583
- reasons.push(`${["waiting", "paused"].includes(mission.status) ? "대기·중단 이유" : "실패 원인"}: ${bounded(mission.error, 450)}`);
49674
+ reasons.push(`${["waiting", "paused"].includes(mission.status) ? "대기·중단 이유" : "실패 원인"}: ${bounded2(mission.error, 450)}`);
49584
49675
  if (mission.status !== "completed")
49585
49676
  reasons.push(`미션 상태: ${mission.status}. 완료 판정이 없습니다.`);
49586
49677
  if (!mission.verification)
@@ -49633,33 +49724,33 @@ function incompleteReasons(mission) {
49633
49724
  }
49634
49725
  function decisionEvidence(mission) {
49635
49726
  const actions = { repair: "수정", reassign: "담당 교체", replan: "재계획", wait: "대기", stop: "중단" };
49636
- return (mission.supervision?.decisions ?? []).slice(-20).map((decision) => bounded(`${decision.round}차 ${actions[decision.action]}${decision.taskId ? ` / 작업 ${decision.taskId}` : ""}${decision.personaId ? ` / 담당 ${decision.personaId}` : ""}: ${decision.reason}`));
49727
+ return (mission.supervision?.decisions ?? []).slice(-20).map((decision) => bounded2(`${decision.round}차 ${actions[decision.action]}${decision.taskId ? ` / 작업 ${decision.taskId}` : ""}${decision.personaId ? ` / 담당 ${decision.personaId}` : ""}: ${decision.reason}`));
49637
49728
  }
49638
49729
  function reviewEvidence(review) {
49639
49730
  return review ? {
49640
49731
  passed: review.passed,
49641
- summary: bounded(review.summary),
49732
+ summary: bounded2(review.summary),
49642
49733
  findings: compact(review.findings),
49643
49734
  criteria: review.criteria?.slice(0, 20).map((item) => ({
49644
- criterion: bounded(item.criterion),
49735
+ criterion: bounded2(item.criterion),
49645
49736
  passed: item.passed,
49646
- evidence: bounded(item.evidence)
49737
+ evidence: bounded2(item.evidence)
49647
49738
  }))
49648
49739
  } : undefined;
49649
49740
  }
49650
49741
  function verificationEvidence(verification) {
49651
49742
  return verification ? {
49652
49743
  ok: verification.ok,
49653
- output: verification.output ? bounded(verification.output, 3000) : undefined,
49654
- fingerprint: bounded(verification.fingerprint, 128)
49744
+ output: verification.output ? bounded2(verification.output, 3000) : undefined,
49745
+ fingerprint: bounded2(verification.fingerprint, 128)
49655
49746
  } : undefined;
49656
49747
  }
49657
49748
  function advisoryEvidence(kind, advisory) {
49658
49749
  return advisory ? {
49659
49750
  kind: `upfront ${kind} advice; historical snapshot; not current approval`,
49660
- planKey: bounded(advisory.planKey, 128),
49751
+ planKey: bounded2(advisory.planKey, 128),
49661
49752
  reviewerId: advisory.reviewerId,
49662
- fingerprint: bounded(advisory.fingerprint, 128),
49753
+ fingerprint: bounded2(advisory.fingerprint, 128),
49663
49754
  review: reviewEvidence(advisory.review)
49664
49755
  } : undefined;
49665
49756
  }
@@ -49669,24 +49760,24 @@ function historicalEvidence(mission) {
49669
49760
  const verification = decision.evidence?.verification;
49670
49761
  const review = decision.evidence?.finalReview;
49671
49762
  if (verification)
49672
- lines.push(bounded(`${decision.round}차 판단 당시 검증: ${verification.ok ? "통과" : "실패"} / 파일 상태 ${bounded(verification.fingerprint, 128)}${verification.output ? ` / ${bounded(verification.output, 250)}` : ""}`));
49763
+ lines.push(bounded2(`${decision.round}차 판단 당시 검증: ${verification.ok ? "통과" : "실패"} / 파일 상태 ${bounded2(verification.fingerprint, 128)}${verification.output ? ` / ${bounded2(verification.output, 250)}` : ""}`));
49673
49764
  if (review) {
49674
- lines.push(bounded(`${decision.round}차 판단 당시 최종 리뷰: ${review.passed ? "통과" : "실패"} / ${bounded(review.summary, 350)}`));
49675
- lines.push(...compact(review.findings, 3).map((finding) => bounded(`${decision.round}차 판단 당시 지적: ${finding}`)));
49765
+ lines.push(bounded2(`${decision.round}차 판단 당시 최종 리뷰: ${review.passed ? "통과" : "실패"} / ${bounded2(review.summary, 350)}`));
49766
+ lines.push(...compact(review.findings, 3).map((finding) => bounded2(`${decision.round}차 판단 당시 지적: ${finding}`)));
49676
49767
  }
49677
49768
  return lines;
49678
49769
  });
49679
49770
  }
49680
49771
  function checkEvidence(mission) {
49681
49772
  return compact([
49682
- `운영자 검증: ${mission.verification ? mission.verification.ok ? "통과" : "실패" : "미실행"} / 명령: ${bounded(mission.supervision?.operatorVerifyCommand ?? mission.verifyCommand, 350)}`,
49773
+ `운영자 검증: ${mission.verification ? mission.verification.ok ? "통과" : "실패" : "미실행"} / 명령: ${bounded2(mission.supervision?.operatorVerifyCommand ?? mission.verifyCommand, 350)}`,
49683
49774
  ...mission.verification?.output ? [`검증 출력: ${mission.verification.output}`] : [],
49684
49775
  `Chief Director 최종 리뷰: ${mission.finalReview ? mission.finalReview.passed && mission.finalReview.findings.length === 0 ? "통과" : "실패" : "미실행"}${mission.finalReview ? ` / ${mission.finalReview.summary}` : ""}`,
49685
49776
  ...mission.tasks.map((task) => `${task.id}: 상태 ${task.status}, 시도 ${task.attempts}회, 독립 리뷰 ${task.review ? task.review.passed && task.review.findings.length === 0 ? "통과" : "실패" : "미실행"} / 리뷰어 ${task.reviewerId}`)
49686
49777
  ]);
49687
49778
  }
49688
49779
  function criterionEvidence(mission) {
49689
- return (mission.finalReview?.criteria ?? []).map((item) => bounded(`${bounded(item.criterion, 200)}: ${item.passed ? "통과" : "실패"} / 근거: ${bounded(item.evidence, 250)}`));
49780
+ return (mission.finalReview?.criteria ?? []).map((item) => bounded2(`${bounded2(item.criterion, 200)}: ${item.passed ? "통과" : "실패"} / 근거: ${bounded2(item.evidence, 250)}`));
49690
49781
  }
49691
49782
  function reportPrompt(mission) {
49692
49783
  const goal = mission.supervision?.operatorGoal ?? mission.goal;
@@ -49714,8 +49805,8 @@ function reportPrompt(mission) {
49714
49805
  '{"summary":"result","eli5":"plain-language result and user impact","goalAssessment":"criteria and actual verdict","assumptions":[],"decisions":[],"deliverables":[],"checks":[],"remaining":[]}',
49715
49806
  `Report evidence (JSON data):
49716
49807
  ${JSON.stringify({
49717
- operatorGoal: bounded(goal, 4000),
49718
- interpretation: mission.goalBrief ? bounded(mission.goalBrief.interpretation, 2000) : undefined,
49808
+ operatorGoal: bounded2(goal, 4000),
49809
+ interpretation: mission.goalBrief ? bounded2(mission.goalBrief.interpretation, 2000) : undefined,
49719
49810
  assumptions: compact(mission.goalBrief?.assumptions ?? []),
49720
49811
  successCriteria: compact(criteria(mission)),
49721
49812
  status: mission.status,
@@ -49724,9 +49815,9 @@ ${JSON.stringify({
49724
49815
  containerObservation: mission.containerObservation,
49725
49816
  verdict: incompleteReasons(mission).length === 0 ? "completed" : "incomplete",
49726
49817
  incompleteReasons: incompleteReasons(mission),
49727
- error: mission.error ? bounded(mission.error, 2000) : undefined,
49728
- workspace: bounded(mission.workspace.path, 2000),
49729
- branch: bounded(mission.workspace.branch),
49818
+ error: mission.error ? bounded2(mission.error, 2000) : undefined,
49819
+ workspace: bounded2(mission.workspace.path, 2000),
49820
+ branch: bounded2(mission.workspace.branch),
49730
49821
  chiefId: mission.chiefId,
49731
49822
  technicalLeadId: mission.technicalLeadId,
49732
49823
  technicalAdvice: advisoryEvidence("technical", mission.technicalReview),
@@ -49736,10 +49827,10 @@ ${JSON.stringify({
49736
49827
  marketingAdvice: advisoryEvidence("marketing", mission.marketingReview),
49737
49828
  actors: mission.personas.slice(0, 20).map((persona) => ({
49738
49829
  id: persona.id,
49739
- name: bounded(persona.name),
49740
- role: bounded(persona.role),
49741
- cli: bounded(persona.agentType),
49742
- model: persona.model ? bounded(persona.model) : "native default (actual model not recorded)",
49830
+ name: bounded2(persona.name),
49831
+ role: bounded2(persona.role),
49832
+ cli: bounded2(persona.agentType),
49833
+ model: persona.model ? bounded2(persona.model) : "native default (actual model not recorded)",
49743
49834
  selectedSkills: persona.skills.slice(0, 30)
49744
49835
  })),
49745
49836
  decisions: decisions.map((decision) => ({
@@ -49747,8 +49838,8 @@ ${JSON.stringify({
49747
49838
  action: decision.action,
49748
49839
  taskId: decision.taskId,
49749
49840
  actorId: decision.personaId,
49750
- reason: bounded(decision.reason),
49751
- instructions: decision.instructions ? bounded(decision.instructions) : undefined,
49841
+ reason: bounded2(decision.reason),
49842
+ instructions: decision.instructions ? bounded2(decision.instructions) : undefined,
49752
49843
  historicalEvidence: decision.evidence && snapshotDecisions.has(decision) ? {
49753
49844
  kind: "evidence at the recovery decision; not current approval",
49754
49845
  finalReview: reviewEvidence(decision.evidence.finalReview),
@@ -49757,25 +49848,25 @@ ${JSON.stringify({
49757
49848
  })),
49758
49849
  tasks: mission.tasks.slice(0, 12).map((state) => ({
49759
49850
  id: state.id,
49760
- title: bounded(mission.plan?.tasks.find((task) => task.id === state.id)?.title ?? state.id),
49851
+ title: bounded2(mission.plan?.tasks.find((task) => task.id === state.id)?.title ?? state.id),
49761
49852
  actorId: mission.plan?.tasks.find((task) => task.id === state.id)?.personaId,
49762
49853
  reviewerId: state.reviewerId,
49763
49854
  status: state.status,
49764
49855
  attempts: state.attempts,
49765
- actorClaim: state.output ? bounded(state.output, 3000) : undefined,
49856
+ actorClaim: state.output ? bounded2(state.output, 3000) : undefined,
49766
49857
  review: reviewEvidence(state.review)
49767
49858
  })),
49768
- verifyCommand: bounded(mission.supervision?.operatorVerifyCommand ?? mission.verifyCommand, 1200),
49859
+ verifyCommand: bounded2(mission.supervision?.operatorVerifyCommand ?? mission.verifyCommand, 1200),
49769
49860
  verification: verificationEvidence(mission.verification),
49770
49861
  goalVerification: mission.goalVerification,
49771
49862
  execution: mission.execution,
49772
49863
  executionPolicy: mission.executionPolicy,
49773
49864
  finalReview: reviewEvidence(mission.finalReview),
49774
49865
  history: mission.history.slice(-30).map((event) => ({
49775
- at: bounded(event.at),
49776
- stage: bounded(event.stage),
49866
+ at: bounded2(event.at),
49867
+ stage: bounded2(event.stage),
49777
49868
  taskId: event.taskId,
49778
- message: bounded(event.message)
49869
+ message: bounded2(event.message)
49779
49870
  }))
49780
49871
  })}`
49781
49872
  ].join(`
@@ -49797,10 +49888,10 @@ function parseReport(source) {
49797
49888
  function fallbackReport(mission) {
49798
49889
  const reasons = incompleteReasons(mission);
49799
49890
  const complete = reasons.length === 0;
49800
- const goal = bounded(mission.supervision?.operatorGoal ?? mission.goal, 350);
49891
+ const goal = bounded2(mission.supervision?.operatorGoal ?? mission.goal, 350);
49801
49892
  return {
49802
49893
  summary: complete ? "작업, 독립 리뷰, 운영자 검증과 Chief Director 최종 리뷰를 통과했습니다." : "목표는 미완료입니다. 확인된 미해결 조건과 보관된 실행 기록을 보고합니다.",
49803
- eli5: complete ? `“${goal}”을 위한 결과물을 만들고, 다른 담당자의 점검과 지정한 확인 절차를 마쳤습니다. 결과물은 아래 작업 경로에 보관되어 있어 직접 확인할 수 있습니다.` : `“${goal}”을 위해 작업했지만, 아직 모든 확인 절차를 통과한 결과는 아닙니다. ${bounded(reasons[0] ?? "완료 증거가 없습니다.", 350)} 이미 만든 작업은 보관되어 있습니다. Chief Director가 기록한 판단과 다음 관측·재개 시각, 아직 충족되지 않은 조건을 아래에서 보고합니다.`,
49894
+ eli5: complete ? `“${goal}”을 위한 결과물을 만들고, 다른 담당자의 점검과 지정한 확인 절차를 마쳤습니다. 결과물은 아래 작업 경로에 보관되어 있어 직접 확인할 수 있습니다.` : `“${goal}”을 위해 작업했지만, 아직 모든 확인 절차를 통과한 결과는 아닙니다. ${bounded2(reasons[0] ?? "완료 증거가 없습니다.", 350)} 이미 만든 작업은 보관되어 있습니다. Chief Director가 기록한 판단과 다음 관측·재개 시각, 아직 충족되지 않은 조건을 아래에서 보고합니다.`,
49804
49895
  goalAssessment: complete ? "기록된 성공 기준에 대해 작업별 독립 리뷰와 운영자 검증이 통과했고, Chief Director가 최종 승인했습니다." : "성공 기준 전체의 충족을 확인하지 못했습니다. 일부 작업이나 검증이 통과했더라도 목표 달성으로 표시하지 않습니다.",
49805
49896
  assumptions: compact(mission.goalBrief?.assumptions ?? []),
49806
49897
  decisions: decisionEvidence(mission),
@@ -49818,7 +49909,7 @@ function fallbackReport(mission) {
49818
49909
  };
49819
49910
  }
49820
49911
  function markdown(value, limit = 1200) {
49821
- return bounded(value, limit).replace(/[\p{Cc}\p{Cf}]/gu, " ").replace(/\s+/g, " ").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/[\\`*_{}[\]()#+.!|~-]/g, "\\$&");
49912
+ return bounded2(value, limit).replace(/[\p{Cc}\p{Cf}]/gu, " ").replace(/\s+/g, " ").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/[\\`*_{}[\]()#+.!|~-]/g, "\\$&");
49822
49913
  }
49823
49914
  function list(values) {
49824
49915
  return values.length ? compact(values).map((value) => `- ${markdown(value)}`).join(`
@@ -50333,12 +50424,12 @@ async function assertMissionWorkspace(mission) {
50333
50424
  }
50334
50425
 
50335
50426
  // ../../packages/core/src/chief/parallel-workspace.ts
50336
- var hash = (value) => createHash10("sha256").update(value).digest("hex");
50427
+ var hash2 = (value) => createHash10("sha256").update(value).digest("hex");
50337
50428
  var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
50338
50429
  function identity3(missionId, taskId, attempt) {
50339
50430
  if (!taskId || taskId.length > 200 || !Number.isSafeInteger(attempt) || attempt < 1)
50340
50431
  throw new Error("Use a valid task ID and positive attempt number for each parallel Actor.");
50341
- return `${hash(missionId).slice(0, 16)}-${hash(taskId).slice(0, 16)}-${attempt}`;
50432
+ return `${hash2(missionId).slice(0, 16)}-${hash2(taskId).slice(0, 16)}-${attempt}`;
50342
50433
  }
50343
50434
  async function paths(source, missionId, taskId, attempt) {
50344
50435
  const root = await parallelRoot(source);
@@ -50482,7 +50573,7 @@ async function collectTaskDelivery(mission, workspace) {
50482
50573
  version: 1,
50483
50574
  workspace,
50484
50575
  patchPath: location.patch,
50485
- patchSha256: hash(patch),
50576
+ patchSha256: hash2(patch),
50486
50577
  deliveryTree: final.tree,
50487
50578
  changes,
50488
50579
  status: "prepared"
@@ -50498,7 +50589,7 @@ async function integrateTaskDelivery(mission, input) {
50498
50589
  if (delivery.workspace.missionId !== mission.id || !same(delivery.workspace, input.workspace) || delivery.patchSha256 !== input.patchSha256 || delivery.patchPath !== location.patch)
50499
50590
  throw new Error("Parallel delivery does not match its persisted task identity and patch. Inspect the saved artifacts before recovery.");
50500
50591
  const patch = await readFile4(location.patch);
50501
- if (hash(patch) !== delivery.patchSha256)
50592
+ if (hash2(patch) !== delivery.patchSha256)
50502
50593
  throw new Error("Parallel delivery patch changed. Restore its saved SHA256 before integration.");
50503
50594
  const current = await captureParallelBaseline(mission.workspace.path);
50504
50595
  const images = await parallelTreeImages(mission.workspace.path, current.tree);
@@ -66141,7 +66232,11 @@ ${details}` : ""}`);
66141
66232
  timeoutSec,
66142
66233
  maxRepairs,
66143
66234
  maxRounds,
66144
- operatingPolicy: chiefOperatingPolicy(chiefConfig, readyActors, !profile),
66235
+ operatingPolicy: chiefOperatingPolicy(chiefConfig, readyActors, !profile, project?.oma?.skill_compatibility ? {
66236
+ reportPath: resolve11(root, project.oma.skill_compatibility.report_path),
66237
+ maxAgeHours: project.oma.skill_compatibility.max_age_hours,
66238
+ mode: project.oma.skill_compatibility.mode
66239
+ } : undefined),
66145
66240
  capturePolicy: chiefCapturePolicy(chiefConfig),
66146
66241
  executionPolicy,
66147
66242
  metricSourcePolicy: chiefConfig.metric_sources,
@@ -66472,7 +66567,7 @@ async function launchMission(input) {
66472
66567
  // src/operation-api.ts
66473
66568
  import { randomUUID as randomUUID16 } from "node:crypto";
66474
66569
  import { realpath as realpath20 } from "node:fs/promises";
66475
- import { join as join36 } from "node:path";
66570
+ import { join as join37 } from "node:path";
66476
66571
 
66477
66572
  // ../../packages/core/src/chief/continuous-store.ts
66478
66573
  import { randomUUID as randomUUID9 } from "node:crypto";
@@ -66676,10 +66771,10 @@ class ContinuousOperationStore {
66676
66771
  }
66677
66772
 
66678
66773
  // src/chief-continuous.ts
66679
- import { execFile as execFile4 } from "node:child_process";
66774
+ import { execFile as execFile5 } from "node:child_process";
66680
66775
  import { randomUUID as randomUUID15 } from "node:crypto";
66681
66776
  import { mkdir as mkdir17, realpath as realpath19, rename as rename7, unlink as unlink7, writeFile as writeFile13 } from "node:fs/promises";
66682
- import { join as join35, resolve as resolve19 } from "node:path";
66777
+ import { join as join36, resolve as resolve20 } from "node:path";
66683
66778
  import { promisify as promisify2 } from "node:util";
66684
66779
 
66685
66780
  // ../../packages/core/src/chief/container-observation-command.ts
@@ -67676,7 +67771,7 @@ async function createContinuousMissionWorkspace(repositoryRoot, operationId, bas
67676
67771
  init_execution();
67677
67772
 
67678
67773
  // src/chief-continuous-decision.ts
67679
- import { join as join34 } from "node:path";
67774
+ import { join as join35 } from "node:path";
67680
67775
 
67681
67776
  // ../../packages/core/src/chief/coordinator-run.ts
67682
67777
  init_execution();
@@ -67771,13 +67866,13 @@ init_execution();
67771
67866
 
67772
67867
  // ../../packages/core/src/chief/runtime.ts
67773
67868
  import { randomUUID as randomUUID11 } from "node:crypto";
67774
- import { join as join27, resolve as resolve15 } from "node:path";
67869
+ import { join as join28, resolve as resolve16 } from "node:path";
67775
67870
 
67776
67871
  // ../../packages/core/src/oma/receipt-adapter.ts
67777
67872
  import { spawnSync as spawnSync2 } from "node:child_process";
67778
- import { existsSync as existsSync4, lstatSync as lstatSync2, readdirSync, readFileSync as readFileSync9 } from "node:fs";
67873
+ import { existsSync as existsSync4, lstatSync as lstatSync3, readFileSync as readFileSync9 } from "node:fs";
67779
67874
  import { mkdir as mkdir12, writeFile as writeFile9 } from "node:fs/promises";
67780
- import { isAbsolute as isAbsolute7, join as join25, relative as relative7, resolve as resolve14, sep as sep9 } from "node:path";
67875
+ import { basename as basename2, dirname as dirname7, isAbsolute as isAbsolute8, join as join26, relative as relative8, resolve as resolve15, sep as sep10 } from "node:path";
67781
67876
 
67782
67877
  // ../../packages/core/src/config/workflow-router.ts
67783
67878
  import { readFileSync as readFileSync8 } from "node:fs";
@@ -68093,27 +68188,107 @@ function ensureLatestOmaCli(options = {}) {
68093
68188
  return pending;
68094
68189
  }
68095
68190
 
68191
+ // ../../packages/core/src/oma/receipt-storage.ts
68192
+ import { createHash as createHash16 } from "node:crypto";
68193
+ import { lstatSync as lstatSync2, readdirSync, realpathSync as realpathSync5 } from "node:fs";
68194
+ import { homedir as homedir6 } from "node:os";
68195
+ import { basename, dirname as dirname6, isAbsolute as isAbsolute7, join as join25, relative as relative7, resolve as resolve14, sep as sep9 } from "node:path";
68196
+ var OMA_RUN_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
68197
+ function absolutePath(value, key) {
68198
+ if (!isAbsolute7(value) || Array.from(value).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127))
68199
+ throw new Error(`${key} must be an absolute path without control characters`);
68200
+ return resolve14(value);
68201
+ }
68202
+ function omaReceiptDirectories(workspace, options = {}) {
68203
+ const env = options.env ?? process.env;
68204
+ const profile = env.OMA_PROFILE ?? "0";
68205
+ if (!/^(0|[1-9][0-9]{0,9})$/.test(profile))
68206
+ throw new Error("OMA_PROFILE must be a non-negative profile number");
68207
+ const stateHome = env.OMA_STATE_HOME === undefined ? absolutePath(env.OMA_HOME || join25(options.home ?? homedir6(), ".oma"), "OMA_HOME") : absolutePath(env.OMA_STATE_HOME, "OMA_STATE_HOME");
68208
+ const project = createHash16("sha256").update(realpathSync5(resolve14(workspace))).digest("hex");
68209
+ return [
68210
+ join25(stateHome, "u", profile, "projects", project, "agent-runs"),
68211
+ ...profile === "0" ? [join25(resolve14(workspace), ".agents", "state", "agent-runs")] : []
68212
+ ];
68213
+ }
68214
+ function regularDirectory(path) {
68215
+ try {
68216
+ const stat = lstatSync2(path);
68217
+ if (!stat.isDirectory() || stat.isSymbolicLink())
68218
+ throw new Error("OMA receipt directory is not a regular directory");
68219
+ return true;
68220
+ } catch (error) {
68221
+ if (error.code === "ENOENT")
68222
+ return false;
68223
+ throw error;
68224
+ }
68225
+ }
68226
+ function validateDirectory(directory, workspace) {
68227
+ if (!regularDirectory(directory))
68228
+ return false;
68229
+ const legacy = join25(resolve14(workspace), ".agents", "state", "agent-runs");
68230
+ const boundary = directory === legacy ? resolve14(workspace) : dirname6(dirname6(dirname6(dirname6(dirname6(directory)))));
68231
+ const components = relative7(boundary, directory).split(sep9).filter(Boolean);
68232
+ let path = boundary;
68233
+ for (const component of components) {
68234
+ path = join25(path, component);
68235
+ if (!regularDirectory(path))
68236
+ throw new Error("OMA receipt directory changed during inspection");
68237
+ }
68238
+ return true;
68239
+ }
68240
+ function listOmaRunFiles(workspace, options = {}) {
68241
+ return omaReceiptDirectories(workspace, options).flatMap((directory) => {
68242
+ if (!validateDirectory(directory, workspace))
68243
+ return [];
68244
+ return readdirSync(directory).filter((name) => name.endsWith(".json") && OMA_RUN_ID.test(name.slice(0, -5))).map((name) => join25(directory, name));
68245
+ });
68246
+ }
68247
+ function resolveOmaReceiptPath(workspace, entry, options = {}) {
68248
+ const name = basename(entry);
68249
+ if (!name.endsWith(".json") || !OMA_RUN_ID.test(name.slice(0, -5)))
68250
+ throw new Error("Invalid receipt filename");
68251
+ if (entry === name)
68252
+ return join25(resolve14(workspace), ".agents", "state", "agent-runs", name);
68253
+ if (!isAbsolute7(entry) || resolve14(entry) !== entry)
68254
+ throw new Error("Invalid receipt path");
68255
+ if (!omaReceiptDirectories(workspace, options).includes(dirname6(entry)))
68256
+ throw new Error("OMA receipt is outside the selected project/profile");
68257
+ if (!validateDirectory(dirname6(entry), workspace))
68258
+ throw new Error("OMA receipt directory is missing");
68259
+ return entry;
68260
+ }
68261
+
68096
68262
  // ../../packages/core/src/oma/receipt-adapter.ts
68097
68263
  var OMA_RECEIPT_SCHEMA_VERSION = 1;
68098
- var RUN_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
68099
68264
  var HASH = /^[a-f0-9]{64}$/;
68100
- var defaultIO2 = {
68101
- listRunFiles: (workspacePath) => {
68102
- const dir = join25(workspacePath, ".agents", "state", "agent-runs");
68103
- return readdirSync(dir).filter((name) => RUN_ID.test(name.slice(0, -5)) && name.endsWith(".json"));
68104
- },
68105
- readReceipt: (path) => {
68106
- if (!lstatSync2(path).isFile())
68107
- throw new Error("Receipt is not a regular file");
68108
- return readFileSync9(path, "utf-8");
68109
- },
68110
- runCli: (args, cwd) => {
68111
- const result = spawnSync2("oma", args, { cwd, encoding: "utf-8", timeout: 15000, maxBuffer: 1024 * 1024 });
68112
- if (result.error)
68113
- throw result.error;
68114
- return { exitCode: result.status, stdout: result.stdout };
68115
- }
68116
- };
68265
+ function createOmaEvidenceIO(options = {}) {
68266
+ const env = { ...options.env ?? process.env, OMA_SKIP_VERSION_CHECK: "1" };
68267
+ if (options.home !== undefined && !env.OMA_HOME)
68268
+ env.OMA_HOME = join26(options.home, ".oma");
68269
+ const storage = { ...options, env };
68270
+ return {
68271
+ listRunFiles: (workspacePath) => listOmaRunFiles(workspacePath, storage),
68272
+ resolveRunFile: (workspacePath, entry) => resolveOmaReceiptPath(workspacePath, entry, storage),
68273
+ readReceipt: (path) => {
68274
+ if (!lstatSync3(path).isFile())
68275
+ throw new Error("Receipt is not a regular file");
68276
+ return readFileSync9(path, "utf-8");
68277
+ },
68278
+ runCli: (args, cwd) => {
68279
+ const result = spawnSync2("oma", args, {
68280
+ cwd,
68281
+ env,
68282
+ encoding: "utf-8",
68283
+ timeout: 15000,
68284
+ maxBuffer: 1024 * 1024
68285
+ });
68286
+ if (result.error)
68287
+ throw result.error;
68288
+ return { exitCode: result.status, stdout: result.stdout };
68289
+ }
68290
+ };
68291
+ }
68117
68292
  function fail(reason) {
68118
68293
  return { ok: false, reason };
68119
68294
  }
@@ -68137,17 +68312,17 @@ async function prepareOmaAttempt(request, dependencies = {}) {
68137
68312
  const routed = routeIssue(`${request.issue.title}
68138
68313
  ${request.issue.description ?? ""}`, table);
68139
68314
  for (const workflow of routed.workflows) {
68140
- const file = join25(request.workspace.path, ".agents", "workflows", `${workflow}.md`);
68315
+ const file = join26(request.workspace.path, ".agents", "workflows", `${workflow}.md`);
68141
68316
  if (!existsSync4(file))
68142
68317
  throw new Error(`OMA workflow file missing in target worktree: ${file}`);
68143
68318
  }
68144
68319
  await ensureLatestOmaCli({ io: dependencies.latestCliIO });
68145
- const path = join25(request.workspace.path, ".agents", "results", `plan-${request.attempt.id}.json`);
68320
+ const path = join26(request.workspace.path, ".agents", "results", `plan-${request.attempt.id}.json`);
68146
68321
  const plan = {
68147
68322
  session_id: request.attempt.id,
68148
68323
  lineage_id: request.attempt.id,
68149
68324
  valley_issue_id: request.issue.id,
68150
- valley_workspace: resolve14(request.workspace.path),
68325
+ valley_workspace: resolve15(request.workspace.path),
68151
68326
  tasks: [
68152
68327
  {
68153
68328
  id: request.attempt.id,
@@ -68167,7 +68342,7 @@ ${request.issue.description ?? ""}`, table);
68167
68342
  }
68168
68343
  ]
68169
68344
  };
68170
- await mkdir12(join25(request.workspace.path, ".agents", "results"), { recursive: true });
68345
+ await mkdir12(join26(request.workspace.path, ".agents", "results"), { recursive: true });
68171
68346
  await writeFile9(path, JSON.stringify(plan, null, 2), { encoding: "utf-8", flag: "wx" });
68172
68347
  return path;
68173
68348
  }
@@ -68195,8 +68370,8 @@ function buildOmaGuidance(request) {
68195
68370
  ].join(`
68196
68371
  `);
68197
68372
  }
68198
- function validateOmaEvidence(request, io = defaultIO2) {
68199
- const root = resolve14(request.workspace.path);
68373
+ function validateOmaEvidence(request, io = createOmaEvidenceIO()) {
68374
+ const root = resolve15(request.workspace.path);
68200
68375
  if (!request.verifyCommand.trim())
68201
68376
  return fail("Strict OMA mode has no configured verify command");
68202
68377
  let cliVersion;
@@ -68210,26 +68385,37 @@ function validateOmaEvidence(request, io = defaultIO2) {
68210
68385
  return fail(`OMA CLI unavailable: ${String(err)}`);
68211
68386
  }
68212
68387
  let receipts;
68388
+ const locations = new Map;
68213
68389
  try {
68214
- receipts = io.listRunFiles(root).map((name) => {
68215
- if (!RUN_ID.test(name.slice(0, -5)) || !name.endsWith(".json"))
68390
+ receipts = io.listRunFiles(root).map((entry) => {
68391
+ const name = basename2(entry);
68392
+ const path = (io.resolveRunFile ?? resolveOmaReceiptPath)(root, entry);
68393
+ if (!OMA_RUN_ID.test(name.slice(0, -5)) || !name.endsWith(".json"))
68216
68394
  throw new Error("Invalid receipt filename");
68217
- const parsed = JSON.parse(io.readReceipt(join25(root, ".agents", "state", "agent-runs", name)));
68395
+ const parsed = JSON.parse(io.readReceipt(path));
68218
68396
  if (!isRecord(parsed) || parsed.runId !== name.slice(0, -5))
68219
68397
  throw new Error("Malformed run receipt");
68398
+ locations.set(parsed, dirname7(path));
68220
68399
  return parsed;
68221
68400
  });
68222
68401
  } catch (err) {
68223
68402
  return fail(`Missing or malformed OMA receipt: ${String(err)}`);
68224
68403
  }
68225
- const forAttempt = receipts.filter((run) => run.sessionId === request.attempt.id && run.agentId === request.agentId).sort((a, b) => Number(a.sequence) - Number(b.sequence));
68404
+ const forAttempt = receipts.filter((run) => run.sessionId === request.attempt.id && run.agentId === request.agentId);
68405
+ if (forAttempt.some((run) => !Number.isSafeInteger(run.sequence) || Number(run.sequence) < 1))
68406
+ return fail("OMA receipt sequence is malformed");
68407
+ if (new Set(forAttempt.map((run) => run.sequence)).size !== forAttempt.length)
68408
+ return fail("OMA receipt sequence is ambiguous across matching runs");
68409
+ if (new Set(forAttempt.map((run) => locations.get(run))).size > 1)
68410
+ return fail("Matching OMA receipts span multiple stores; generate current evidence in the active CLI's selected project/profile");
68411
+ forAttempt.sort((a, b) => Number(a.sequence) - Number(b.sequence));
68226
68412
  const run = forAttempt.at(-1);
68227
68413
  if (!run)
68228
68414
  return fail("No OMA receipt is bound to this Valley attempt");
68229
68415
  if (run.schemaVersion !== OMA_RECEIPT_SCHEMA_VERSION) {
68230
68416
  return fail(`OMA CLI ${cliVersion} returned an unsupported receipt schema. AV requires agent-run schema v${OMA_RECEIPT_SCHEMA_VERSION}; update AV and OMA (npm install -g oh-my-agent@latest), then generate and verify a compatible receipt.`);
68231
68417
  }
68232
- if (run.taskId !== request.attempt.id || !RUN_ID.test(String(run.runId))) {
68418
+ if (run.taskId !== request.attempt.id || !OMA_RUN_ID.test(String(run.runId))) {
68233
68419
  return fail("OMA receipt task identity is incompatible");
68234
68420
  }
68235
68421
  if (run.workspace !== root || run.artifactRoot !== root || run.status !== "completed" || run.exitCode !== 0) {
@@ -68263,12 +68449,12 @@ function validateOmaEvidence(request, io = defaultIO2) {
68263
68449
  if (!template?.includes("{{attempt.id}}"))
68264
68450
  return fail("Analysis requires a configured current-attempt report path");
68265
68451
  const expanded = template.replaceAll("{{attempt.id}}", request.attempt.id);
68266
- const target = resolve14(root, expanded);
68267
- const subpath = relative7(root, target);
68268
- if (isAbsolute7(expanded) || expanded.split(/[\\/]/).includes("..") || subpath === "" || subpath === ".." || subpath.startsWith(`..${sep9}`) || isAbsolute7(subpath)) {
68452
+ const target = resolve15(root, expanded);
68453
+ const subpath = relative8(root, target);
68454
+ if (isAbsolute8(expanded) || expanded.split(/[\\/]/).includes("..") || subpath === "" || subpath === ".." || subpath.startsWith(`..${sep10}`) || isAbsolute8(subpath)) {
68269
68455
  return fail("Configured analysis report escapes the workspace");
68270
68456
  }
68271
- if (!isRecord(run.artifacts) || !Object.entries(run.artifacts).some(([path, hash]) => !isAbsolute7(path) && !path.split(/[\\/]/).includes("..") && resolve14(root, path) === target && HASH.test(String(hash)))) {
68457
+ if (!isRecord(run.artifacts) || !Object.entries(run.artifacts).some(([path, hash]) => !isAbsolute8(path) && !path.split(/[\\/]/).includes("..") && resolve15(root, path) === target && HASH.test(String(hash)))) {
68272
68458
  return fail("OMA receipt does not bind the configured current-attempt report");
68273
68459
  }
68274
68460
  }
@@ -68285,7 +68471,7 @@ function validateOmaEvidence(request, io = defaultIO2) {
68285
68471
  for (const check of run.checks) {
68286
68472
  if (!isRecord(check) || !stringArray(check.command) || !check.command.length || typeof check.cwd !== "string")
68287
68473
  return fail("OMA verification receipt is malformed");
68288
- latestChecks.set(JSON.stringify([check.command, resolve14(check.cwd)]), check);
68474
+ latestChecks.set(JSON.stringify([check.command, resolve15(check.cwd)]), check);
68289
68475
  }
68290
68476
  if ([...latestChecks.values()].some((check) => check.exitCode !== 0 || check.before !== run.after || check.after !== run.after)) {
68291
68477
  return fail("An OMA verification check failed or is stale");
@@ -68307,6 +68493,214 @@ function validateOmaEvidence(request, io = defaultIO2) {
68307
68493
  return { ok: true, runId: String(run.runId) };
68308
68494
  }
68309
68495
 
68496
+ // ../../packages/core/src/oma/skill-matrix-adapter.ts
68497
+ import { posix } from "node:path";
68498
+
68499
+ // ../../packages/core/src/oma/skill-matrix-io.ts
68500
+ init_skill_matrix_schema();
68501
+ import { execFile as execFile4 } from "node:child_process";
68502
+ import { constants as constants5 } from "node:fs";
68503
+ import { open as open7 } from "node:fs/promises";
68504
+ var MAX_BYTES = 4 * 1024 * 1024;
68505
+ async function command(binary, args, signal) {
68506
+ return new Promise((resolve, reject) => {
68507
+ execFile4(binary, args, {
68508
+ encoding: "utf8",
68509
+ timeout: 1e4,
68510
+ maxBuffer: MAX_BYTES,
68511
+ signal,
68512
+ ...binary === "oma" ? { env: { ...process.env, OMA_SKIP_VERSION_CHECK: "1" } } : {}
68513
+ }, (error, stdout) => {
68514
+ if (error)
68515
+ reject(new Error(`${binary} local diagnostic command failed. Check its installation/version and retry.`));
68516
+ else
68517
+ resolve(stdout);
68518
+ });
68519
+ });
68520
+ }
68521
+ async function readReport(path) {
68522
+ const file = await open7(path, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
68523
+ try {
68524
+ const info = await file.stat();
68525
+ if (!info.isFile() || info.size > MAX_BYTES)
68526
+ throw new Error("Matrix report must be a regular file at most 4 MiB.");
68527
+ const bytes = Buffer.alloc(info.size + 1);
68528
+ let length = 0;
68529
+ while (length < bytes.length) {
68530
+ const result = await file.read(bytes, length, bytes.length - length, length);
68531
+ if (!result.bytesRead)
68532
+ break;
68533
+ length += result.bytesRead;
68534
+ }
68535
+ if (length !== info.size)
68536
+ throw new Error("Matrix report changed during the read. Retry after its writer finishes.");
68537
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
68538
+ } finally {
68539
+ await file.close();
68540
+ }
68541
+ }
68542
+ var defaultSkillMatrixDeps = {
68543
+ now: Date.now,
68544
+ platform: process.platform,
68545
+ arch: process.arch,
68546
+ readReport,
68547
+ plan: async (workspace, skills, signal) => JSON.parse(await command("oma", [
68548
+ "skills",
68549
+ "matrix",
68550
+ "--project-root",
68551
+ workspace,
68552
+ "--skills",
68553
+ skills.join(","),
68554
+ "--delivery",
68555
+ "injected",
68556
+ "--vendors",
68557
+ "claude,codex",
68558
+ "--json"
68559
+ ], signal)),
68560
+ cliVersion: async (vendor, signal) => {
68561
+ const version = (await command(vendor, ["--version"], signal)).trim();
68562
+ return /^[\w .()+/-]{1,160}$/.test(version) ? version : null;
68563
+ }
68564
+ };
68565
+ function parseSkillMatrix(value) {
68566
+ const parsed = matrixReportSchema.safeParse(value);
68567
+ if (!parsed.success)
68568
+ throw new Error("Matrix report uses an unsupported or malformed evidence contract. Regenerate it with the current OMA CLI.");
68569
+ const report = parsed.data;
68570
+ const unique = (values) => new Set(values).size === values.length;
68571
+ if (!unique(report.cases.map((entry) => entry.id)) || !unique(report.cells.map((entry) => `${entry.vendor}\x00${entry.caseId}`)) || report.bundle && (!unique(report.bundle.skills.map((entry) => entry.name)) || !unique(report.bundle.skills.map((entry) => entry.caseId))) || report.cells.some((cell) => !unique(cell.checks.map((check) => check.id))))
68572
+ throw new Error("Matrix report repeats a skill, case or vendor cell. Regenerate an unambiguous report.");
68573
+ return report;
68574
+ }
68575
+
68576
+ // ../../packages/core/src/oma/skill-matrix-adapter.ts
68577
+ var scope = "installed injected read-reference audit; not AV runtime or task-quality certification";
68578
+ var safeNames = /^[a-z0-9][a-z0-9-]{0,127}$/;
68579
+ var remediation = "Regenerate the installed injected matrix with explicit models, then set oma.skill_compatibility.report_path in av.yaml.";
68580
+ var matrixRouteKey = (route) => `${route.actorType}\x00${route.model ?? ""}`;
68581
+ function sourceProblem(report) {
68582
+ if (report.sourceKind !== "installed" || report.delivery !== "injected" || report.auditScope !== "read-reference" || !report.bundle)
68583
+ return "Evidence is not an installed, injected, read-reference audit. Synthetic probes cannot authorize installed skills.";
68584
+ return;
68585
+ }
68586
+ function sameCoverage(a, b) {
68587
+ const sorted = (items) => JSON.stringify([...items].sort());
68588
+ return a.hash === b.hash && a.caseId === b.caseId && sorted(a.requiredFiles) === sorted(b.requiredFiles) && sorted(a.missingFiles) === sorted(b.missingFiles) && JSON.stringify(a.excludedReferences) === JSON.stringify(b.excludedReferences);
68589
+ }
68590
+ function assessRoute(report, plan, skills, route, version) {
68591
+ const result = (status, reason) => ({
68592
+ ...route,
68593
+ status,
68594
+ reason
68595
+ });
68596
+ if (route.actorType !== "claude" && route.actorType !== "codex")
68597
+ return result("unknown", "This matrix protocol measures only Claude and Codex.");
68598
+ if (!route.model)
68599
+ return result("unknown", "The candidate uses an unpinned native model default; it cannot match a measured model.");
68600
+ if (!version)
68601
+ return result("unknown", "The current native CLI version could not be verified.");
68602
+ for (const name of skills) {
68603
+ const current = plan.bundle?.skills.find((entry) => entry.name === name);
68604
+ const saved = report.bundle?.skills.find((entry) => entry.name === name);
68605
+ if (!current || !saved)
68606
+ return result("unknown", `Skill ${name} has no complete installed audit coverage.`);
68607
+ if (!sameCoverage(current, saved))
68608
+ return result("unknown", `Skill ${name} content or reference coverage changed after the audit.`);
68609
+ if (current.missingFiles.length || current.excludedReferences.length || saved.missingFiles.length || saved.excludedReferences.length)
68610
+ return result("unknown", `Skill ${name} has missing or excluded references; complete its audit coverage first.`);
68611
+ if (!report.cases.some((entry) => entry.id === saved.caseId && entry.skill === name))
68612
+ return result("unknown", `Skill ${name} required case is absent from the measured selection.`);
68613
+ const cell = report.cells.find((entry) => entry.caseId === saved.caseId && entry.vendor === route.actorType);
68614
+ if (!cell || cell.skill !== name || cell.contentHash !== current.hash)
68615
+ return result("unknown", `Skill ${name} lacks a matching measured vendor cell.`);
68616
+ if (cell.cliVersion !== version)
68617
+ return result("unknown", `Skill ${name} was measured with a different or unknown native CLI version.`);
68618
+ if (cell.model !== route.model)
68619
+ return result("unknown", `Skill ${name} was measured with a different or unknown reported model.`);
68620
+ if (cell.status !== "pass" || !cell.checks.length || cell.checks.some((check) => check.status !== "pass"))
68621
+ return result(cell.status === "fail" ? "fail" : "unknown", `Skill ${name} audit is ${cell.status}; passing read-reference evidence is required.`);
68622
+ const entry = `${name}/SKILL.md`;
68623
+ if (!current.requiredFiles.includes(entry))
68624
+ return result("unknown", `Skill ${name} audit omits its installed SKILL.md.`);
68625
+ const required = [
68626
+ "process",
68627
+ "output",
68628
+ "content",
68629
+ "integrity",
68630
+ "reference-coverage",
68631
+ ...current.requiredFiles.filter((file) => file !== entry).map((file) => `reference:${posix.relative(name, file)}`)
68632
+ ];
68633
+ if (required.some((id) => !cell.checks.some((check) => check.id === id && check.status === "pass" && (id === "content" || id.startsWith("reference:") ? check.proof === "read" : true))))
68634
+ return result("unknown", `Skill ${name} audit lacks a mandatory successful read-reference check.`);
68635
+ }
68636
+ return result("pass", "All selected skills have current passing installed injected read-reference evidence.");
68637
+ }
68638
+ async function inspectSkillCompatibility(policy, workspace, selectedSkills, routes, deps = defaultSkillMatrixDeps, signal) {
68639
+ const unknown = (reason) => ({
68640
+ scope,
68641
+ routes: routes.map((route) => ({ ...route, status: "unknown", reason }))
68642
+ });
68643
+ if (selectedSkills?.length === 0)
68644
+ return {
68645
+ scope,
68646
+ routes: routes.map((route) => ({
68647
+ ...route,
68648
+ status: "pass",
68649
+ reason: "No skills selected; no compatibility claim is required."
68650
+ }))
68651
+ };
68652
+ try {
68653
+ if (signal?.aborted)
68654
+ throw new Error("Interrupted");
68655
+ const report = parseSkillMatrix(await deps.readReport(policy.reportPath));
68656
+ const source = sourceProblem(report);
68657
+ if (source)
68658
+ return unknown(source);
68659
+ if (report.mode !== "live" || report.status !== "completed")
68660
+ return unknown("The report is not a completed live measurement; a plan is unmeasured.");
68661
+ const age = deps.now() - Date.parse(report.createdAt);
68662
+ if (age < -60000 || age > policy.maxAgeHours * 3600000)
68663
+ return unknown("The cached matrix is stale or has a future timestamp.");
68664
+ if (report.host.platform !== deps.platform || report.host.arch !== deps.arch)
68665
+ return unknown("The matrix host platform or architecture differs from this runtime.");
68666
+ const skills = [...new Set(selectedSkills ?? report.bundle?.skills.map((entry) => entry.name) ?? [])];
68667
+ if (!skills.length || skills.length > 100 || skills.some((name) => !safeNames.test(name)))
68668
+ return unknown("Select a bounded list of valid installed skill names.");
68669
+ const plan = parseSkillMatrix(await deps.plan(workspace, skills, signal));
68670
+ if (sourceProblem(plan) || plan.mode !== "plan" || plan.status !== "planned")
68671
+ return unknown("OMA did not return a supported installed injected plan.");
68672
+ if (plan.omaVersion !== report.omaVersion)
68673
+ return unknown("The OMA version changed after measurement; refresh the cached matrix.");
68674
+ if (plan.host.platform !== deps.platform || plan.host.arch !== deps.arch)
68675
+ return unknown("The current OMA plan host does not match this runtime.");
68676
+ const versions = new Map;
68677
+ for (const route of routes) {
68678
+ if (versions.has(route.actorType) || route.actorType !== "claude" && route.actorType !== "codex")
68679
+ continue;
68680
+ try {
68681
+ versions.set(route.actorType, await deps.cliVersion(route.actorType, signal));
68682
+ } catch {
68683
+ versions.set(route.actorType, null);
68684
+ }
68685
+ }
68686
+ if (signal?.aborted)
68687
+ throw new Error("Interrupted");
68688
+ return {
68689
+ scope,
68690
+ routes: routes.map((route) => assessRoute(report, plan, skills, route, versions.get(route.actorType) ?? null))
68691
+ };
68692
+ } catch {
68693
+ if (signal?.aborted)
68694
+ throw new Error("Skill compatibility inspection interrupted before Actor launch.");
68695
+ return unknown(`The cached report or local OMA plan could not be validated. ${remediation}`);
68696
+ }
68697
+ }
68698
+ function assertCompatibleRoute(route, inspection) {
68699
+ const result = inspection.routes.find((entry) => matrixRouteKey(entry) === matrixRouteKey(route));
68700
+ if (result?.status !== "pass")
68701
+ throw new Error(`Skill compatibility required for ${route.actorType}/${route.model ?? "native default"}: ${result?.reason ?? "no matching evidence"} ${remediation}`);
68702
+ }
68703
+
68310
68704
  // ../../packages/core/src/orchestrator/agent-runner.ts
68311
68705
  init_logger();
68312
68706
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -68798,9 +69192,9 @@ async function withMissionDeadline(mission, parent, run) {
68798
69192
 
68799
69193
  // ../../packages/core/src/chief/skills.ts
68800
69194
  init_dist();
68801
- import { constants as constants5 } from "node:fs";
68802
- import { lstat as lstat11, mkdir as mkdir13, open as open7, readdir as readdir6, realpath as realpath14, stat, writeFile as writeFile10 } from "node:fs/promises";
68803
- import { isAbsolute as isAbsolute8, join as join26, relative as relative8, sep as sep10 } from "node:path";
69195
+ import { constants as constants6 } from "node:fs";
69196
+ import { lstat as lstat11, mkdir as mkdir13, open as open8, readdir as readdir6, realpath as realpath14, stat, writeFile as writeFile10 } from "node:fs/promises";
69197
+ import { isAbsolute as isAbsolute9, join as join27, relative as relative9, sep as sep11 } from "node:path";
68804
69198
  var MAX_SKILL_BYTES = 256000;
68805
69199
  var MAX_METADATA_BYTES = 16384;
68806
69200
  var MAX_CATALOG_SIZE = 100;
@@ -68809,8 +69203,8 @@ var MAX_HARNESS_ENTRIES = 5000;
68809
69203
  var SKILL_NAME = /^[a-z0-9][a-z0-9-]{0,127}$/;
68810
69204
  var OMA_SKILL_NAME = /^oma-[a-z0-9][a-z0-9-]{0,123}$/;
68811
69205
  function inside(root, path) {
68812
- const child = relative8(root, path);
68813
- return child !== "" && child !== ".." && !child.startsWith(`..${sep10}`) && !isAbsolute8(child);
69206
+ const child = relative9(root, path);
69207
+ return child !== "" && child !== ".." && !child.startsWith(`..${sep11}`) && !isAbsolute9(child);
68814
69208
  }
68815
69209
  function excludedResource(name) {
68816
69210
  return [
@@ -68833,11 +69227,11 @@ async function prepareMissionSkills(sourceRepositoryPath, workspacePath) {
68833
69227
  if (!source)
68834
69228
  return;
68835
69229
  const workspace = await realpath14(workspacePath);
68836
- const agents = join26(workspace, ".agents");
69230
+ const agents = join27(workspace, ".agents");
68837
69231
  await mkdir13(agents, { recursive: true });
68838
69232
  if (!inside(workspace, await realpath14(agents)))
68839
69233
  throw new Error("The target .agents directory escapes the mission worktree. Fix its symlink before creating this order.");
68840
- const target = join26(agents, "skills");
69234
+ const target = join27(agents, "skills");
68841
69235
  await mkdir13(target, { recursive: true });
68842
69236
  const targetRoot = await skillRoot(workspace);
68843
69237
  if (!targetRoot)
@@ -68858,13 +69252,13 @@ async function prepareMissionSkills(sourceRepositoryPath, workspacePath) {
68858
69252
  continue;
68859
69253
  if (++entries > MAX_HARNESS_ENTRIES)
68860
69254
  throw new Error("The installed skill resources exceed 5,000 entries. Remove unused resources before creating this order.");
68861
- const from = await realpath14(join26(sourceDirectory, name)).catch(() => {
69255
+ const from = await realpath14(join27(sourceDirectory, name)).catch(() => {
68862
69256
  return;
68863
69257
  });
68864
69258
  if (!from || !inside(sourceRoot, from))
68865
69259
  continue;
68866
69260
  const info = await stat(from);
68867
- const to = join26(targetDirectory, name);
69261
+ const to = join27(targetDirectory, name);
68868
69262
  const existing = await lstat11(to).catch(() => {
68869
69263
  return;
68870
69264
  });
@@ -68880,7 +69274,7 @@ async function prepareMissionSkills(sourceRepositoryPath, workspacePath) {
68880
69274
  const parent = await realpath14(targetDirectory);
68881
69275
  if (parent !== destinationRoot && !inside(destinationRoot, parent))
68882
69276
  throw new Error("A target skill resource escapes the mission worktree. Fix its symlink before creating this order.");
68883
- const file = await open7(from, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
69277
+ const file = await open8(from, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
68884
69278
  try {
68885
69279
  const current = await file.stat();
68886
69280
  if (!current.isFile())
@@ -68919,7 +69313,7 @@ async function skillRoot(workspacePath) {
68919
69313
  });
68920
69314
  if (!workspace)
68921
69315
  return;
68922
- const root = await realpath14(join26(workspace, ".agents", "skills")).catch(() => {
69316
+ const root = await realpath14(join27(workspace, ".agents", "skills")).catch(() => {
68923
69317
  return;
68924
69318
  });
68925
69319
  if (!root)
@@ -68933,7 +69327,7 @@ async function skillRoot(workspacePath) {
68933
69327
  async function skillPath(root, name) {
68934
69328
  if (!SKILL_NAME.test(name))
68935
69329
  throw new Error(`Invalid skill name: ${name}. Select an installed skill directory name.`);
68936
- const path = await realpath14(join26(root, name, "SKILL.md")).catch(() => {
69330
+ const path = await realpath14(join27(root, name, "SKILL.md")).catch(() => {
68937
69331
  throw new Error(`Skill ${name}/SKILL.md is missing. Restore that installed skill in ${root} before resuming.`);
68938
69332
  });
68939
69333
  if (!inside(root, path))
@@ -68941,7 +69335,7 @@ async function skillPath(root, name) {
68941
69335
  return path;
68942
69336
  }
68943
69337
  async function readSkill(path, metadataOnly) {
68944
- const file = await open7(path, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
69338
+ const file = await open8(path, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
68945
69339
  try {
68946
69340
  const info = await file.stat();
68947
69341
  if (!info.isFile())
@@ -68989,7 +69383,7 @@ function metadata(source, name, path) {
68989
69383
  async function descriptor(root, name) {
68990
69384
  if (!OMA_SKILL_NAME.test(name))
68991
69385
  return;
68992
- const directory = await realpath14(join26(root, name));
69386
+ const directory = await realpath14(join27(root, name));
68993
69387
  if (!inside(root, directory) || !(await stat(directory)).isDirectory())
68994
69388
  return;
68995
69389
  const path = await skillPath(root, name);
@@ -69169,11 +69563,13 @@ class ChiefRuntime {
69169
69563
  store;
69170
69564
  signal;
69171
69565
  onStage;
69566
+ skillMatrixDeps;
69172
69567
  runners = new Set;
69173
- constructor(store, signal, onStage = () => {}) {
69568
+ constructor(store, signal, onStage = () => {}, skillMatrixDeps) {
69174
69569
  this.store = store;
69175
69570
  this.signal = signal;
69176
69571
  this.onStage = onStage;
69572
+ this.skillMatrixDeps = skillMatrixDeps;
69177
69573
  }
69178
69574
  ports() {
69179
69575
  return {
@@ -69244,18 +69640,32 @@ class ChiefRuntime {
69244
69640
  workspace,
69245
69641
  availableSkills: mission.availableSkills?.map((skill) => ({
69246
69642
  ...skill,
69247
- path: join27(workspace.path, ".agents", "skills", skill.name, "SKILL.md")
69643
+ path: join28(workspace.path, ".agents", "skills", skill.name, "SKILL.md")
69248
69644
  }))
69249
69645
  };
69250
69646
  if (signal?.aborted)
69251
69647
  throw new Error("Order interrupted. Resume it with av order --resume followed by its mission ID.");
69252
- const route = stage === "work" ? selectWorkActor(mission, persona, context?.taskId) : undefined;
69648
+ const compatibilityPolicy = mission.operatingPolicy?.skillCompatibility;
69649
+ const compatibility = stage === "work" && compatibilityPolicy ? await inspectSkillCompatibility(compatibilityPolicy, workspace.path, persona.skills, workActorCandidates(mission, persona, compatibilityPolicy.mode === "require"), this.skillMatrixDeps, signal) : undefined;
69650
+ const compatibleRoutes = compatibilityPolicy?.mode === "require" && compatibility ? new Set(compatibility.routes.filter((entry) => entry.status === "pass").map(matrixRouteKey)) : undefined;
69651
+ if (compatibility && compatibilityPolicy)
69652
+ mission.history.push({
69653
+ at: new Date().toISOString(),
69654
+ stage: "skill-compatibility",
69655
+ message: `${compatibilityPolicy.mode}: ${compatibility.routes.map((entry) => `${entry.actorType}/${entry.model ?? "native default"} ${entry.status}: ${entry.reason}`).join("; ")} Scope: ${compatibility.scope}.`,
69656
+ ...context?.taskId ? { taskId: context.taskId } : {}
69657
+ });
69658
+ const route = stage === "work" ? selectWorkActor(mission, persona, context?.taskId, compatibleRoutes) : undefined;
69253
69659
  persona = route?.actor ?? persona;
69660
+ if (compatibility && compatibilityPolicy) {
69661
+ if (compatibilityPolicy.mode === "require")
69662
+ assertCompatibleRoute({ actorType: persona.agentType, model: persona.model }, compatibility);
69663
+ }
69254
69664
  this.onStage(stage, persona);
69255
69665
  const attempt = {
69256
69666
  id: randomUUID11(),
69257
69667
  issueId: mission.id,
69258
- workspacePath: resolve15(workspace.path),
69668
+ workspacePath: resolve16(workspace.path),
69259
69669
  startedAt: new Date().toISOString(),
69260
69670
  finishedAt: null,
69261
69671
  exitCode: null,
@@ -69461,16 +69871,16 @@ init_execution();
69461
69871
  // src/chief-supervisor.ts
69462
69872
  import { spawn as spawn16 } from "node:child_process";
69463
69873
  import { randomUUID as randomUUID13 } from "node:crypto";
69464
- import { join as join31 } from "node:path";
69874
+ import { join as join32 } from "node:path";
69465
69875
  init_execution();
69466
69876
 
69467
69877
  // src/chief-delivery.ts
69468
- import { createHash as createHash17 } from "node:crypto";
69878
+ import { createHash as createHash18 } from "node:crypto";
69469
69879
  import { mkdir as mkdir15, writeFile as writeFile12 } from "node:fs/promises";
69470
- import { join as join30 } from "node:path";
69880
+ import { join as join31 } from "node:path";
69471
69881
 
69472
69882
  // ../../packages/core/src/chief/report-delivery.ts
69473
- import { join as join29 } from "node:path";
69883
+ import { join as join30 } from "node:path";
69474
69884
 
69475
69885
  // ../../packages/core/src/chief/report-delivery-adapters.ts
69476
69886
  init_report_delivery_contract();
@@ -69851,20 +70261,20 @@ init_report_delivery_contract();
69851
70261
  // ../../packages/core/src/chief/report-delivery-outbox.ts
69852
70262
  init_zod();
69853
70263
  init_report_delivery_contract();
69854
- import { createHash as createHash16, randomUUID as randomUUID12 } from "node:crypto";
69855
- import { constants as constants6 } from "node:fs";
69856
- import { mkdir as mkdir14, open as open8, readdir as readdir7, readFile as readFile11, realpath as realpath15, rename as rename6, unlink as unlink5, writeFile as writeFile11 } from "node:fs/promises";
69857
- import { isAbsolute as isAbsolute9, join as join28, relative as relative9, resolve as resolve16 } from "node:path";
69858
- var hash2 = string2().regex(/^[a-f0-9]{64}$/);
70264
+ import { createHash as createHash17, randomUUID as randomUUID12 } from "node:crypto";
70265
+ import { constants as constants7 } from "node:fs";
70266
+ import { mkdir as mkdir14, open as open9, readdir as readdir7, readFile as readFile11, realpath as realpath15, rename as rename6, unlink as unlink5, writeFile as writeFile11 } from "node:fs/promises";
70267
+ import { isAbsolute as isAbsolute10, join as join29, relative as relative10, resolve as resolve17 } from "node:path";
70268
+ var hash3 = string2().regex(/^[a-f0-9]{64}$/);
69859
70269
  var outboxRecordSchema = strictObject({
69860
70270
  version: literal(1),
69861
- id: hash2,
70271
+ id: hash3,
69862
70272
  missionId: string2().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/),
69863
70273
  missionStatus: _enum(["completed", "failed"]),
69864
70274
  destinationId: string2().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/),
69865
70275
  channel: string2().regex(/^[a-z][a-z0-9-]{0,63}$/),
69866
- reportHash: hash2,
69867
- destinationHash: hash2.optional(),
70276
+ reportHash: hash3,
70277
+ destinationHash: hash3.optional(),
69868
70278
  goal: string2().max(32000),
69869
70279
  markdown: string2().max(256000),
69870
70280
  reportPath: string2().max(4096),
@@ -69878,7 +70288,7 @@ var outboxRecordSchema = strictObject({
69878
70288
  message: string2().max(1000)
69879
70289
  }).refine((record) => record.nextPart <= record.parts && (record.status !== "delivered" || record.nextPart === record.parts));
69880
70290
  function sha2562(content) {
69881
- return createHash16("sha256").update(content).digest("hex");
70291
+ return createHash17("sha256").update(content).digest("hex");
69882
70292
  }
69883
70293
  function receipt(record) {
69884
70294
  const {
@@ -69896,12 +70306,12 @@ function receipt(record) {
69896
70306
  class ReportOutbox {
69897
70307
  directory;
69898
70308
  constructor(stateDir) {
69899
- this.directory = join28(stateDir, "report-outbox");
70309
+ this.directory = join29(stateDir, "report-outbox");
69900
70310
  }
69901
70311
  path(id) {
69902
- if (!hash2.safeParse(id).success)
70312
+ if (!hash3.safeParse(id).success)
69903
70313
  throw new Error("Invalid report receipt ID. Use av reports to find a receipt.");
69904
- return join28(this.directory, `${id}.json`);
70314
+ return join29(this.directory, `${id}.json`);
69905
70315
  }
69906
70316
  lock(id) {
69907
70317
  return new MissionStore(this.directory).lock(id);
@@ -69957,18 +70367,18 @@ async function verifiedAttachment(attachment, artifactRoot, readBytes) {
69957
70367
  try {
69958
70368
  const root = await realpath15(artifactRoot);
69959
70369
  const path = await realpath15(attachment.path);
69960
- const local = relative9(root, path);
69961
- if (!local || local.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || local === ".." || isAbsolute9(local))
70370
+ const local = relative10(root, path);
70371
+ if (!local || local.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || local === ".." || isAbsolute10(local))
69962
70372
  throw failure;
69963
- if (resolve16(attachment.path) !== attachment.path)
70373
+ if (resolve17(attachment.path) !== attachment.path)
69964
70374
  throw failure;
69965
- const file = await open8(attachment.path, constants6.O_RDONLY | constants6.O_NOFOLLOW);
70375
+ const file = await open9(attachment.path, constants7.O_RDONLY | constants7.O_NOFOLLOW);
69966
70376
  try {
69967
70377
  const stat = await file.stat();
69968
70378
  if (!stat.isFile() || stat.size !== attachment.sizeBytes)
69969
70379
  throw failure;
69970
70380
  if (!readBytes) {
69971
- const digest = createHash16("sha256");
70381
+ const digest = createHash17("sha256");
69972
70382
  for await (const chunk of file.createReadStream({ autoClose: false }))
69973
70383
  digest.update(chunk);
69974
70384
  if (digest.digest("hex") !== attachment.sha256)
@@ -70015,7 +70425,7 @@ function dependencies(stateDir, overrides) {
70015
70425
  env: overrides.env ?? process.env,
70016
70426
  registry: { ...createReportChannelRegistry(fetch2), ...overrides.registry },
70017
70427
  attachments: overrides.attachments ?? [],
70018
- artifactRoot: overrides.artifactRoot ?? join29(stateDir, "captures"),
70428
+ artifactRoot: overrides.artifactRoot ?? join30(stateDir, "captures"),
70019
70429
  now: overrides.now ?? (() => new Date)
70020
70430
  };
70021
70431
  }
@@ -70196,8 +70606,8 @@ init_chief_schema();
70196
70606
  init_yaml_loader();
70197
70607
  async function saveAndDeliverMissionReport(mission, root) {
70198
70608
  const repository = mission.repositoryRoot ?? root;
70199
- const directory = join30(root, ".agent-valley/reports");
70200
- const reportPath = join30(directory, `${mission.id}.md`);
70609
+ const directory = join31(root, ".agent-valley/reports");
70610
+ const reportPath = join31(directory, `${mission.id}.md`);
70201
70611
  const report = renderReport(mission);
70202
70612
  await mkdir15(directory, { recursive: true, mode: 448 });
70203
70613
  await writeFile12(reportPath, report, { mode: 384 });
@@ -70212,12 +70622,12 @@ ${explanation.eli5}`);
70212
70622
  try {
70213
70623
  const config = mergeChiefConfig(loadGlobalConfig()?.chief, loadProjectConfig(root)?.chief);
70214
70624
  const attachments = [...mission.capture?.attachments ?? []];
70215
- const artifactRoot = join30(repository, ".agent-valley/captures");
70625
+ const artifactRoot = join31(repository, ".agent-valley/captures");
70216
70626
  if (config.reporting?.destinations.length) {
70217
70627
  const bytes = Buffer.from(report);
70218
- const sha256 = createHash17("sha256").update(bytes).digest("hex");
70219
- const reportDirectory = join30(artifactRoot, mission.id);
70220
- const attachmentPath = join30(reportDirectory, `report-${sha256}.md`);
70628
+ const sha256 = createHash18("sha256").update(bytes).digest("hex");
70629
+ const reportDirectory = join31(artifactRoot, mission.id);
70630
+ const attachmentPath = join31(reportDirectory, `report-${sha256}.md`);
70221
70631
  await mkdir15(reportDirectory, { recursive: true, mode: 448 });
70222
70632
  await writeFile12(attachmentPath, bytes, { mode: 384 });
70223
70633
  attachments.push({
@@ -70228,7 +70638,7 @@ ${explanation.eli5}`);
70228
70638
  sha256
70229
70639
  });
70230
70640
  }
70231
- const receipts = await dispatchMissionReport(mission, report, reportPath, config.reporting, join30(repository, ".agent-valley"), {
70641
+ const receipts = await dispatchMissionReport(mission, report, reportPath, config.reporting, join31(repository, ".agent-valley"), {
70232
70642
  attachments,
70233
70643
  artifactRoot
70234
70644
  });
@@ -70318,7 +70728,7 @@ function runWorker(args, root, signal) {
70318
70728
  async function superviseOrder(goal, options, root, dependencies = {}) {
70319
70729
  assertNotManagedRun();
70320
70730
  const id = options.resume ?? options.missionId ?? randomUUID13();
70321
- const store = new MissionStore(join31(root, ".agent-valley/missions"));
70731
+ const store = new MissionStore(join32(root, ".agent-valley/missions"));
70322
70732
  const controller = new AbortController;
70323
70733
  const interrupt = () => controller.abort();
70324
70734
  dependencies.signal?.addEventListener("abort", interrupt, { once: true });
@@ -70497,9 +70907,9 @@ Return one valid JSON object under the original charter and pinned evidence.` :
70497
70907
 
70498
70908
  // ../../packages/core/src/chief/metric-source-adapters.ts
70499
70909
  init_metric_source_policy();
70500
- import { constants as constants7 } from "node:fs";
70501
- import { lstat as lstat12, open as open9, realpath as realpath16 } from "node:fs/promises";
70502
- import { isAbsolute as isAbsolute10, relative as relative10, resolve as resolve17, sep as sep11 } from "node:path";
70910
+ import { constants as constants8 } from "node:fs";
70911
+ import { lstat as lstat12, open as open10, realpath as realpath16 } from "node:fs/promises";
70912
+ import { isAbsolute as isAbsolute11, relative as relative11, resolve as resolve18, sep as sep12 } from "node:path";
70503
70913
  var MAX_METRIC_RESPONSE_BYTES = 2000000;
70504
70914
  function metricSourceEnvironment(request, name) {
70505
70915
  if (!name || !request.env[name]?.trim())
@@ -70584,19 +70994,19 @@ var jsonFileMetricAdapter = {
70584
70994
  async collect(request) {
70585
70995
  const root = await realpath16(request.repositoryRoot);
70586
70996
  const name = request.source.file;
70587
- if (!name || isAbsolute10(name))
70997
+ if (!name || isAbsolute11(name))
70588
70998
  throw new MetricSourceError("Metric file must be relative to the source repository. Set chief.metric_sources.sources[].file in av.yaml.");
70589
- const path = resolve17(root, name);
70590
- const within = relative10(root, path);
70591
- if (!within || within.startsWith(`..${sep11}`) || within === ".." || isAbsolute10(within))
70999
+ const path = resolve18(root, name);
71000
+ const within = relative11(root, path);
71001
+ if (!within || within.startsWith(`..${sep12}`) || within === ".." || isAbsolute11(within))
70592
71002
  throw new MetricSourceError("Metric file escapes the source repository. Choose a repository-relative JSON file.");
70593
71003
  let current = root;
70594
- for (const part of within.split(sep11)) {
70595
- current = resolve17(current, part);
71004
+ for (const part of within.split(sep12)) {
71005
+ current = resolve18(current, part);
70596
71006
  if ((await lstat12(current)).isSymbolicLink())
70597
71007
  throw new MetricSourceError("Metric file and parent directories must not be symlinks. Choose a regular JSON file inside the source repository.");
70598
71008
  }
70599
- const file = await open9(path, constants7.O_RDONLY | constants7.O_NOFOLLOW);
71009
+ const file = await open10(path, constants8.O_RDONLY | constants8.O_NOFOLLOW);
70600
71010
  try {
70601
71011
  const stat = await file.stat();
70602
71012
  if (!stat.isFile() || stat.size > MAX_METRIC_RESPONSE_BYTES || await realpath16(path) !== path)
@@ -70997,9 +71407,9 @@ function createMissionMetricPorts(repository, mission, dependencies = {}) {
70997
71407
 
70998
71408
  // src/chief-tool-config.ts
70999
71409
  import { randomUUID as randomUUID14 } from "node:crypto";
71000
- import { constants as constants8 } from "node:fs";
71001
- import { link as link2, lstat as lstat13, mkdir as mkdir16, open as open10, realpath as realpath17, unlink as unlink6 } from "node:fs/promises";
71002
- import { join as join32 } from "node:path";
71410
+ import { constants as constants9 } from "node:fs";
71411
+ import { link as link2, lstat as lstat13, mkdir as mkdir16, open as open11, realpath as realpath17, unlink as unlink6 } from "node:fs/promises";
71412
+ import { join as join33 } from "node:path";
71003
71413
  init_dist2();
71004
71414
  init_client_toml();
71005
71415
  var maximumBytes = 1024 * 1024;
@@ -71018,7 +71428,7 @@ async function assertLocalPath(root, local) {
71018
71428
  const parts = local.split("/");
71019
71429
  let current = root;
71020
71430
  for (const [index, part] of parts.entries()) {
71021
- current = join32(current, part);
71431
+ current = join33(current, part);
71022
71432
  const stats = await lstat13(current).catch((error) => {
71023
71433
  if (error.code === "ENOENT")
71024
71434
  return;
@@ -71032,7 +71442,7 @@ async function assertLocalPath(root, local) {
71032
71442
  return true;
71033
71443
  }
71034
71444
  async function readPrivateFile(path) {
71035
- const file = await open10(path, constants8.O_RDONLY | constants8.O_NOFOLLOW);
71445
+ const file = await open11(path, constants9.O_RDONLY | constants9.O_NOFOLLOW);
71036
71446
  try {
71037
71447
  const stats = await file.stat();
71038
71448
  if (!stats.isFile() || stats.size > maximumBytes)
@@ -71075,9 +71485,9 @@ async function privateExclude(original, target, paths) {
71075
71485
  ]);
71076
71486
  const common = targetCommon.trim();
71077
71487
  const path = exclude.trim();
71078
- if (common !== join32(target, ".git") && common !== originalCommon.trim() || path !== join32(common, "info", "exclude") || await realpath17(common) !== common)
71488
+ if (common !== join33(target, ".git") && common !== originalCommon.trim() || path !== join33(common, "info", "exclude") || await realpath17(common) !== common)
71079
71489
  throw new ChiefToolConfigError("Chief MCP configuration requires the workspace's own Git metadata or its original repository's shared worktree metadata.");
71080
- const info = join32(common, "info");
71490
+ const info = join33(common, "info");
71081
71491
  const infoStats = await lstat13(info).catch((error) => {
71082
71492
  if (error.code === "ENOENT")
71083
71493
  return;
@@ -71095,7 +71505,7 @@ async function privateExclude(original, target, paths) {
71095
71505
  const patterns = paths.flatMap((local) => [`/${local}`, `/${local}.av-mcp-*.tmp`]).filter((pattern) => !lines.has(pattern));
71096
71506
  if (!patterns.length)
71097
71507
  return;
71098
- const file = await open10(path, constants8.O_WRONLY | constants8.O_APPEND | constants8.O_CREAT | constants8.O_NOFOLLOW, 384);
71508
+ const file = await open11(path, constants9.O_WRONLY | constants9.O_APPEND | constants9.O_CREAT | constants9.O_NOFOLLOW, 384);
71099
71509
  try {
71100
71510
  await file.writeFile(`${content && !content.endsWith(`
71101
71511
  `) ? `
@@ -71116,14 +71526,14 @@ async function prepareToolConfig(originalRepository, targetWorkspace) {
71116
71526
  continue;
71117
71527
  if (!await assertLocalPath(original, config.path))
71118
71528
  continue;
71119
- const content = selectedNamespace(await readPrivateFile(join32(original, config.path)), config.namespace, config.toml);
71529
+ const content = selectedNamespace(await readPrivateFile(join33(original, config.path)), config.namespace, config.toml);
71120
71530
  if (content)
71121
71531
  selected.push({ path: config.path, content });
71122
71532
  }
71123
71533
  if (!selected.length)
71124
71534
  return;
71125
71535
  for (const root of [original, target]) {
71126
- const stats = await lstat13(join32(root, ".git"));
71536
+ const stats = await lstat13(join33(root, ".git"));
71127
71537
  if (stats.isSymbolicLink() || !stats.isFile() && !stats.isDirectory() || await realpath17((await parallelGit(root, ["rev-parse", "--show-toplevel"])).trim()) !== root)
71128
71538
  throw new ChiefToolConfigError("Chief MCP tools require original local Git repository metadata. Restore the workspace before starting Chief.");
71129
71539
  }
@@ -71131,16 +71541,16 @@ async function prepareToolConfig(originalRepository, targetWorkspace) {
71131
71541
  for (const config of selected) {
71132
71542
  const parts = config.path.split("/");
71133
71543
  if (parts.length > 1) {
71134
- const parent = join32(target, ...parts.slice(0, -1));
71544
+ const parent = join33(target, ...parts.slice(0, -1));
71135
71545
  await mkdir16(parent, { recursive: true, mode: 448 });
71136
71546
  if (await realpath17(parent) !== parent)
71137
71547
  throw new ChiefToolConfigError("Chief MCP configuration parent redirects through a symlink. Restore its local directory.");
71138
71548
  }
71139
71549
  if (await assertLocalPath(target, config.path))
71140
71550
  continue;
71141
- const path = join32(target, config.path);
71551
+ const path = join33(target, config.path);
71142
71552
  const temporary = `${path}.av-mcp-${randomUUID14()}.tmp`;
71143
- const file = await open10(temporary, "wx", 384);
71553
+ const file = await open11(temporary, "wx", 384);
71144
71554
  try {
71145
71555
  await file.writeFile(config.content);
71146
71556
  } finally {
@@ -71169,10 +71579,10 @@ async function prepareChiefToolConfig(originalRepository, targetWorkspace) {
71169
71579
 
71170
71580
  // src/tool-discovery.ts
71171
71581
  init_client_toml();
71172
- import { constants as constants9 } from "node:fs";
71582
+ import { constants as constants10 } from "node:fs";
71173
71583
  import { access, lstat as lstat14, readFile as readFile12, realpath as realpath18 } from "node:fs/promises";
71174
- import { homedir as homedir6 } from "node:os";
71175
- import { delimiter as delimiter2, isAbsolute as isAbsolute11, join as join33, resolve as resolve18 } from "node:path";
71584
+ import { homedir as homedir7 } from "node:os";
71585
+ import { delimiter as delimiter2, isAbsolute as isAbsolute12, join as join34, resolve as resolve19 } from "node:path";
71176
71586
  var binaries = [
71177
71587
  "docker",
71178
71588
  "orb",
@@ -71188,10 +71598,10 @@ var binaries = [
71188
71598
  var MAX_CONFIG_BYTES = 1048576;
71189
71599
  var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
71190
71600
  async function executable(name, env) {
71191
- for (const directory of (env.PATH ?? "").split(delimiter2).filter(isAbsolute11)) {
71601
+ for (const directory of (env.PATH ?? "").split(delimiter2).filter(isAbsolute12)) {
71192
71602
  try {
71193
- const path = join33(directory, name);
71194
- await access(path, constants9.X_OK);
71603
+ const path = join34(directory, name);
71604
+ await access(path, constants10.X_OK);
71195
71605
  if ((await lstat14(await realpath18(path))).isFile())
71196
71606
  return true;
71197
71607
  } catch {}
@@ -71244,7 +71654,7 @@ async function mcpNames(path, scope, project, requestedRoot) {
71244
71654
  }
71245
71655
  async function discoverTools(root, dependencies = {}) {
71246
71656
  const env = dependencies.env ?? process.env;
71247
- const home = dependencies.home ?? homedir6();
71657
+ const home = dependencies.home ?? homedir7();
71248
71658
  const project = await realpath18(root);
71249
71659
  const projectFiles = [
71250
71660
  ".mcp.json",
@@ -71255,11 +71665,11 @@ async function discoverTools(root, dependencies = {}) {
71255
71665
  ".codex/config.toml"
71256
71666
  ];
71257
71667
  const userFiles = [".claude.json", ".cursor/mcp.json", ".qwen/settings.json", ".gemini/settings.json"];
71258
- const codexHome = env.CODEX_HOME && isAbsolute11(env.CODEX_HOME) ? env.CODEX_HOME : join33(home, ".codex");
71668
+ const codexHome = env.CODEX_HOME && isAbsolute12(env.CODEX_HOME) ? env.CODEX_HOME : join34(home, ".codex");
71259
71669
  const configs = [
71260
- ...projectFiles.map((path) => ({ path: join33(project, path), scope: "project" })),
71261
- ...userFiles.map((path) => ({ path: resolve18(home, path), scope: "user" })),
71262
- { path: join33(codexHome, "config.toml"), scope: "user" }
71670
+ ...projectFiles.map((path) => ({ path: join34(project, path), scope: "project" })),
71671
+ ...userFiles.map((path) => ({ path: resolve19(home, path), scope: "user" })),
71672
+ { path: join34(codexHome, "config.toml"), scope: "user" }
71263
71673
  ];
71264
71674
  const [cli, mcp] = await Promise.all([
71265
71675
  Promise.all(binaries.map(async (name) => ({
@@ -71271,7 +71681,7 @@ async function discoverTools(root, dependencies = {}) {
71271
71681
  availability: await executable(name, env) ? "available" : "unavailable",
71272
71682
  reason: "Executable presence only; service access, daemon state and login are unverified."
71273
71683
  }))),
71274
- Promise.all(configs.map(({ path, scope }) => mcpNames(path, scope, project, resolve18(root))))
71684
+ Promise.all(configs.map(({ path, scope }) => mcpNames(path, scope, project, resolve19(root))))
71275
71685
  ]);
71276
71686
  return [...cli, ...mcp.flat()];
71277
71687
  }
@@ -71306,7 +71716,7 @@ function continuousDecisionPrompt(operation, mission, tools, previousReport) {
71306
71716
  async function decideContinuousGoal(operation, decisionId, root, dependencies = {}) {
71307
71717
  if (!operation.baseline)
71308
71718
  throw new Error("An accepted operation baseline is required before selecting a goal.");
71309
- const store = new MissionStore(join34(root, ".agent-valley", "operation-decisions", operation.id));
71719
+ const store = new MissionStore(join35(root, ".agent-valley", "operation-decisions", operation.id));
71310
71720
  const unlock = await store.lock(decisionId);
71311
71721
  const runtime = (dependencies.runtime ?? ((storage, signal) => new ChiefRuntime(storage, signal)))(store, dependencies.signal);
71312
71722
  let mission;
@@ -71415,7 +71825,7 @@ async function decideContinuousGoal(operation, decisionId, root, dependencies =
71415
71825
  const previousId = operation.history.at(-1)?.missionId;
71416
71826
  let previousReport;
71417
71827
  if (previousId) {
71418
- const previous = await new MissionStore(join34(root, ".agent-valley", "missions")).load(previousId);
71828
+ const previous = await new MissionStore(join35(root, ".agent-valley", "missions")).load(previousId);
71419
71829
  if (previous.repositoryRoot !== operation.repositoryRoot || previous.status !== "completed")
71420
71830
  throw new Error("The previous accepted child's evidence no longer matches this operation. Restore its saved checkpoint before selecting another goal.");
71421
71831
  previousReport = renderReport(previous).slice(0, 16000);
@@ -71446,7 +71856,7 @@ async function decideContinuousGoal(operation, decisionId, root, dependencies =
71446
71856
  }
71447
71857
 
71448
71858
  // src/chief-continuous.ts
71449
- var execute = promisify2(execFile4);
71859
+ var execute = promisify2(execFile5);
71450
71860
  var orderKeys = [
71451
71861
  "workspace",
71452
71862
  "verify",
@@ -71474,7 +71884,7 @@ function integerOption(value, name, maximum) {
71474
71884
  return number;
71475
71885
  }
71476
71886
  function operationStore(root) {
71477
- return new ContinuousOperationStore(join35(resolve19(root), ".agent-valley", "operations"));
71887
+ return new ContinuousOperationStore(join36(resolve20(root), ".agent-valley", "operations"));
71478
71888
  }
71479
71889
  async function restoreOperationOrigin(repository, workspace) {
71480
71890
  const env = { ...process.env, ...clearedGitEnvironment };
@@ -71530,7 +71940,7 @@ async function newOperation(charter, options, root, id) {
71530
71940
  ...config.executionPolicy.maxEstimatedCostUsd !== undefined ? { cost: String(config.executionPolicy.maxEstimatedCostUsd) } : {}
71531
71941
  });
71532
71942
  if (typeof settings.actors === "string")
71533
- settings.actors = resolve19(root, settings.actors);
71943
+ settings.actors = resolve20(root, settings.actors);
71534
71944
  const now = new Date().toISOString();
71535
71945
  return operationSchema.parse({
71536
71946
  id,
@@ -71592,9 +72002,9 @@ function renderOperationReport(operation) {
71592
72002
  `);
71593
72003
  }
71594
72004
  async function saveOperationReport(root, operation) {
71595
- const directory = join35(root, ".agent-valley", "operation-reports");
72005
+ const directory = join36(root, ".agent-valley", "operation-reports");
71596
72006
  await mkdir17(directory, { recursive: true, mode: 448 });
71597
- const path = join35(directory, `${operation.id}.md`);
72007
+ const path = join36(directory, `${operation.id}.md`);
71598
72008
  const temporary = `${path}.${randomUUID15()}.tmp`;
71599
72009
  try {
71600
72010
  await writeFile13(temporary, renderOperationReport(operation), { mode: 384, flag: "wx" });
@@ -71629,7 +72039,7 @@ async function runOperation(charter, options, root = process.cwd(), dependencies
71629
72039
  if (decisionBudgetKeys.some((key) => options[key] !== undefined)) {
71630
72040
  if (operation.currentMissionId || !operation.decisionId)
71631
72041
  throw new Error("Operation resume budget reconciliation applies only to an active decision checkpoint. Adjust the current child's budget with av order --resume <child-id>.");
71632
- const decisions = new MissionStore(join35(root, ".agent-valley", "operation-decisions", operation.id));
72042
+ const decisions = new MissionStore(join36(root, ".agent-valley", "operation-decisions", operation.id));
71633
72043
  const unlockDecision = await decisions.lock(operation.decisionId);
71634
72044
  try {
71635
72045
  const decision = await decisions.load(operation.decisionId);
@@ -71675,7 +72085,7 @@ async function runOperation(charter, options, root = process.cwd(), dependencies
71675
72085
  console.log(`Operation ${id}
71676
72086
  Charter: ${operation.charter}
71677
72087
  Resume: av order --resume ${id}`);
71678
- const missions = new MissionStore(join35(root, ".agent-valley", "missions"));
72088
+ const missions = new MissionStore(join36(root, ".agent-valley", "missions"));
71679
72089
  return await runContinuousOperation(operation, {
71680
72090
  signal: controller.signal,
71681
72091
  ...dependencies.now ? { now: dependencies.now } : {},
@@ -71783,7 +72193,7 @@ class OperationApi {
71783
72193
  this.root = root;
71784
72194
  this.workspace = workspace;
71785
72195
  this.dependencies = dependencies;
71786
- this.store = new ContinuousOperationStore(join36(root, ".agent-valley/operations"));
72196
+ this.store = new ContinuousOperationStore(join37(root, ".agent-valley/operations"));
71787
72197
  this.jobs = new MissionJobs(root, "operation-jobs");
71788
72198
  }
71789
72199
  order(raw) {
@@ -72021,17 +72431,17 @@ class MissionApi {
72021
72431
  this.projectRoot = projectRoot;
72022
72432
  this.workspace = workspace;
72023
72433
  this.dependencies = dependencies;
72024
- this.store = new MissionStore(join37(projectRoot, ".agent-valley/missions"));
72434
+ this.store = new MissionStore(join38(projectRoot, ".agent-valley/missions"));
72025
72435
  this.jobs = new MissionJobs(projectRoot);
72026
72436
  this.operationApi = new OperationApi(projectRoot, workspace, dependencies);
72027
72437
  this.operationJobs = new MissionJobs(projectRoot, "operation-jobs");
72028
72438
  }
72029
72439
  static async create(workspace, dependencies = {}) {
72030
- if (!isAbsolute12(workspace))
72440
+ if (!isAbsolute13(workspace))
72031
72441
  throw new Error("Set an absolute Git repository path in av mcp --workspace <path>.");
72032
72442
  const projectRoot = await realpath21(workspace);
72033
72443
  const target = loadProjectConfig(projectRoot)?.workspace?.root ?? projectRoot;
72034
- if (!isAbsolute12(target))
72444
+ if (!isAbsolute13(target))
72035
72445
  throw new Error("Set workspace.root in av.yaml to an absolute Git repository path.");
72036
72446
  return new MissionApi(projectRoot, await realpath21(target), dependencies);
72037
72447
  }
@@ -72060,7 +72470,7 @@ class MissionApi {
72060
72470
  async order(raw) {
72061
72471
  assertNotManagedRun(this.dependencies.env);
72062
72472
  const input = mcpOrderSchema.parse(raw);
72063
- if (input.workspace && (!isAbsolute12(input.workspace) || await realpath21(input.workspace) !== this.workspace))
72473
+ if (input.workspace && (!isAbsolute13(input.workspace) || await realpath21(input.workspace) !== this.workspace))
72064
72474
  throw new Error("This AV server is bound to another workspace. Start av mcp --workspace for the target repository.");
72065
72475
  return this.serializeOrder(async () => {
72066
72476
  if (input.requestId) {
@@ -72083,7 +72493,7 @@ class MissionApi {
72083
72493
  async list() {
72084
72494
  this.assertOpen();
72085
72495
  await ensureAvDirectory(this.projectRoot, ["missions"]);
72086
- const ids = new Set((await readdir8(join37(this.projectRoot, ".agent-valley/missions"))).filter((name) => name.endsWith(".json")).map((name) => missionIdSchema.parse(name.slice(0, -5))));
72496
+ const ids = new Set((await readdir8(join38(this.projectRoot, ".agent-valley/missions"))).filter((name) => name.endsWith(".json")).map((name) => missionIdSchema.parse(name.slice(0, -5))));
72087
72497
  for (const job of await this.jobs.list())
72088
72498
  ids.add(job.missionId);
72089
72499
  return {
@@ -72237,7 +72647,7 @@ class MissionApi {
72237
72647
  async load(id) {
72238
72648
  await ensureAvDirectory(this.projectRoot, ["missions"]);
72239
72649
  try {
72240
- const path = join37(this.projectRoot, ".agent-valley/missions", `${missionIdSchema.parse(id)}.json`);
72650
+ const path = join38(this.projectRoot, ".agent-valley/missions", `${missionIdSchema.parse(id)}.json`);
72241
72651
  const stat = await lstat15(path);
72242
72652
  if (!stat.isFile() || stat.isSymbolicLink())
72243
72653
  throw new Error(`Mission record must be a regular file: ${path}. Remove the symlink before retrying.`);
@@ -72263,7 +72673,7 @@ class MissionApi {
72263
72673
  init_client_integrations_assets();
72264
72674
  init_client_integrations_files();
72265
72675
  import { lstat as lstat16, readdir as readdir9, realpath as realpath22 } from "node:fs/promises";
72266
- import { dirname as dirname6, join as join38, relative as relative11, resolve as resolve20 } from "node:path";
72676
+ import { dirname as dirname8, join as join39, relative as relative12, resolve as resolve21 } from "node:path";
72267
72677
 
72268
72678
  // src/plugin-assets.ts
72269
72679
  import { copyFile as copyFile2, mkdir as mkdir18, readFile as readFile13 } from "node:fs/promises";
@@ -72430,7 +72840,7 @@ async function projectDirectory(workspace) {
72430
72840
  if (typeof workspace !== "string" || !workspace.trim())
72431
72841
  throw new Error("Pass --workspace /absolute/AV-project to bind every exported MCP server to its AV configuration.");
72432
72842
  try {
72433
- const project = await realpath22(resolve20(workspace));
72843
+ const project = await realpath22(resolve21(workspace));
72434
72844
  if (!(await lstat16(project)).isDirectory())
72435
72845
  throw new Error("not a directory");
72436
72846
  return project;
@@ -72453,7 +72863,7 @@ function remoteEndpoint(value) {
72453
72863
  async function outputDirectory(output) {
72454
72864
  if (typeof output !== "string" || !output.trim())
72455
72865
  throw new Error("Pass --output /absolute/export-directory to write the generated AV plugin packages.");
72456
- const target = resolve20(output);
72866
+ const target = resolve21(output);
72457
72867
  let ancestor = target;
72458
72868
  for (;; ) {
72459
72869
  try {
@@ -72462,11 +72872,11 @@ async function outputDirectory(output) {
72462
72872
  throw exportConflict(ancestor, "symbolic link exports are not modified");
72463
72873
  if (!info.isDirectory())
72464
72874
  throw exportConflict(ancestor, "expected an output directory");
72465
- return join38(await realpath22(ancestor), relative11(ancestor, target));
72875
+ return join39(await realpath22(ancestor), relative12(ancestor, target));
72466
72876
  } catch (error) {
72467
72877
  if (error.code !== "ENOENT")
72468
72878
  throw error;
72469
- ancestor = dirname6(ancestor);
72879
+ ancestor = dirname8(ancestor);
72470
72880
  }
72471
72881
  }
72472
72882
  }
@@ -72481,13 +72891,13 @@ async function outputFiles(root, directory = root) {
72481
72891
  }
72482
72892
  const files = [];
72483
72893
  for (const entry of entries) {
72484
- const path = join38(directory, entry.name);
72894
+ const path = join39(directory, entry.name);
72485
72895
  if (entry.isSymbolicLink())
72486
72896
  throw exportConflict(path, "symbolic links are not modified");
72487
72897
  if (entry.isDirectory())
72488
72898
  files.push(...await outputFiles(root, path));
72489
72899
  else if (entry.isFile())
72490
- files.push(relative11(root, path).split("\\").join("/"));
72900
+ files.push(relative12(root, path).split("\\").join("/"));
72491
72901
  else
72492
72902
  throw exportConflict(path, "expected regular export files");
72493
72903
  }
@@ -72518,21 +72928,21 @@ async function exportPluginPackages(options) {
72518
72928
  if (output === workspace)
72519
72929
  throw exportConflict(output, "the output directory must be separate from the AV project root");
72520
72930
  const { manifest } = await loadPluginManifestAsset(options.sourceManifest ? [options.sourceManifest] : undefined);
72521
- const { content: skill } = await loadClientSkillAsset(options.sourceSkillRoot ? [join38(options.sourceSkillRoot, "SKILL.md")] : clientSkillAssetCandidates());
72931
+ const { content: skill } = await loadClientSkillAsset(options.sourceSkillRoot ? [join39(options.sourceSkillRoot, "SKILL.md")] : clientSkillAssetCandidates());
72522
72932
  const { content: license } = await loadPluginLicenseAsset(options.sourceLicense ? [options.sourceLicense] : undefined);
72523
72933
  const packageFiles = pluginPackageFiles(manifest, skill, license, { workspace, remoteUrl });
72524
- const receipt = await integrationFile(output, join38(output, receiptName2), "", 384);
72934
+ const receipt = await integrationFile(output, join39(output, receiptName2), "", 384);
72525
72935
  const hashes = ownedFileHashes(receipt.before, receipt.path);
72526
72936
  const existing = await outputFiles(output);
72527
72937
  for (const path of existing) {
72528
72938
  if (path === receiptName2)
72529
72939
  continue;
72530
72940
  if (!packageFiles.has(path) || hashes[path] === undefined)
72531
- throw exportConflict(join38(output, path), "unowned files are retained");
72941
+ throw exportConflict(join39(output, path), "unowned files are retained");
72532
72942
  }
72533
72943
  const files = [];
72534
72944
  for (const [path, content] of packageFiles) {
72535
- const file = await integrationFile(output, join38(output, path), content, 420);
72945
+ const file = await integrationFile(output, join39(output, path), content, 420);
72536
72946
  if (hashes[path] !== undefined && (file.before === null || contentHash(file.before) !== hashes[path]))
72537
72947
  throw exportConflict(file.path, "the exported file was changed or removed locally");
72538
72948
  if (hashes[path] === undefined && file.before !== null)
@@ -72551,11 +72961,11 @@ async function exportPluginPackages(options) {
72551
72961
  transport: remoteUrl ? "streamable-http" : "stdio",
72552
72962
  files: await applyIntegrationFiles(output, [...files, receipt]),
72553
72963
  packages: {
72554
- portable: join38(output, "portable/av"),
72555
- claude: join38(output, "claude/plugins/av"),
72556
- cursor: join38(output, "cursor/plugins/av"),
72557
- qwen: join38(output, "qwen/av"),
72558
- antigravity: join38(output, "antigravity/av")
72964
+ portable: join39(output, "portable/av"),
72965
+ claude: join39(output, "claude/plugins/av"),
72966
+ cursor: join39(output, "cursor/plugins/av"),
72967
+ qwen: join39(output, "qwen/av"),
72968
+ antigravity: join39(output, "antigravity/av")
72559
72969
  }
72560
72970
  };
72561
72971
  }
@@ -72588,7 +72998,7 @@ function registerAgentClientCommands(program) {
72588
72998
  ].some((value) => value !== undefined))
72589
72999
  throw new Error("OAuth gateway options require av mcp --http. Omit them to use local stdio.");
72590
73000
  const oauth = options.http ? resolveMcpOAuthOptions(options) : undefined;
72591
- const project = resolve21(options.workspace);
73001
+ const project = resolve22(options.workspace);
72592
73002
  const api = await MissionApi.create(project);
72593
73003
  const workspace = api.targetWorkspace;
72594
73004
  try {
@@ -72618,7 +73028,7 @@ function registerAgentClientCommands(program) {
72618
73028
  // src/chief.ts
72619
73029
  import { randomUUID as randomUUID19 } from "node:crypto";
72620
73030
  import { realpath as realpath23 } from "node:fs/promises";
72621
- import { join as join40 } from "node:path";
73031
+ import { join as join41 } from "node:path";
72622
73032
 
72623
73033
  // ../../packages/core/src/chief/coordinator-container.ts
72624
73034
  init_execution();
@@ -73135,7 +73545,7 @@ function selectTaskReviewer(mission, task, state) {
73135
73545
  }
73136
73546
 
73137
73547
  // ../../packages/core/src/chief/coordinator.ts
73138
- var bounded2 = (value) => value.slice(-32000);
73548
+ var bounded3 = (value) => value.slice(-32000);
73139
73549
  async function coordinate(mission, ports) {
73140
73550
  Object.assign(mission, validateMission(mission));
73141
73551
  const operatorGoal = mission.goal;
@@ -73199,7 +73609,7 @@ async function coordinate(mission, ports) {
73199
73609
  if (task.effectScope === "external" && state.effectState === "unknown")
73200
73610
  throw new MissionPause(`External effect ${task.id} has no established destination outcome and will not be repeated.`, "unknown-effect");
73201
73611
  if (task.effectScope !== "external" || state.effectState !== "completed") {
73202
- state.output = bounded2(await run(persona(task.personaId), workPrompt(mission, task, state, persona(task.personaId)), "work", task.id));
73612
+ state.output = bounded3(await run(persona(task.personaId), workPrompt(mission, task, state, persona(task.personaId)), "work", task.id));
73203
73613
  if (task.effectScope === "external")
73204
73614
  state.effectState = "completed";
73205
73615
  }
@@ -73373,7 +73783,7 @@ async function coordinate(mission, ports) {
73373
73783
  mission.fingerprint = await ports.fingerprint(mission);
73374
73784
  mission.verification = {
73375
73785
  ok: result.ok,
73376
- output: result.output ? bounded2(result.output) : undefined,
73786
+ output: result.output ? bounded3(result.output) : undefined,
73377
73787
  fingerprint: mission.fingerprint
73378
73788
  };
73379
73789
  if (mission.verificationMode === "chief" && !mission.goalVerification?.ok) {
@@ -73472,7 +73882,7 @@ async function coordinate(mission, ports) {
73472
73882
  return mission;
73473
73883
  }
73474
73884
  mission.status = "failed";
73475
- mission.error = bounded2(error instanceof Error ? error.message : String(error));
73885
+ mission.error = bounded3(error instanceof Error ? error.message : String(error));
73476
73886
  if (error instanceof ReadOnlyViolation || error instanceof ContractViolation || error instanceof CheckpointError)
73477
73887
  executionState(mission).failureKind = "integrity";
73478
73888
  if (error instanceof ReadOnlyViolation)
@@ -73489,7 +73899,7 @@ async function coordinate(mission, ports) {
73489
73899
  if (reportError instanceof ReadOnlyViolation) {
73490
73900
  executionState(mission).failureKind = "integrity";
73491
73901
  invalidate();
73492
- mission.error = bounded2(`${mission.error}
73902
+ mission.error = bounded3(`${mission.error}
73493
73903
  ${reportError.message}`);
73494
73904
  mission.report = fallbackReport(mission);
73495
73905
  }
@@ -73506,14 +73916,14 @@ init_execution();
73506
73916
 
73507
73917
  // ../../packages/core/src/workspace/delivery-strategy.ts
73508
73918
  init_logger();
73509
- import { lstatSync as lstatSync3 } from "node:fs";
73919
+ import { lstatSync as lstatSync4 } from "node:fs";
73510
73920
 
73511
73921
  // ../../packages/core/src/workspace/isolated-branch-import.ts
73512
73922
  init_worktree_lifecycle();
73513
73923
  import { randomUUID as randomUUID18 } from "node:crypto";
73514
73924
  import { mkdtemp, rm as rm5 } from "node:fs/promises";
73515
73925
  import { tmpdir as tmpdir3 } from "node:os";
73516
- import { join as join39 } from "node:path";
73926
+ import { join as join40 } from "node:path";
73517
73927
  async function importIsolatedBranch(workspace, root) {
73518
73928
  if (!isIsolatedGitWorkspace(workspace))
73519
73929
  return null;
@@ -73560,7 +73970,7 @@ async function importIsolatedBranch(workspace, root) {
73560
73970
  `).filter(Boolean);
73561
73971
  if (commits.length === 0)
73562
73972
  return null;
73563
- temporaryWorktree = await mkdtemp(join39(tmpdir3(), "av-branch-import-"));
73973
+ temporaryWorktree = await mkdtemp(join40(tmpdir3(), "av-branch-import-"));
73564
73974
  const added = await runCommand("git", ["worktree", "add", "--detach", temporaryWorktree, currentHead], {
73565
73975
  cwd: root
73566
73976
  });
@@ -73833,7 +74243,7 @@ function gitFailure(action, result, fix) {
73833
74243
  }
73834
74244
  function linkedWorktreePath(workspace) {
73835
74245
  try {
73836
- return lstatSync3(`${workspace.path}/.git`).isFile() ? workspace.path : null;
74246
+ return lstatSync4(`${workspace.path}/.git`).isFile() ? workspace.path : null;
73837
74247
  } catch {
73838
74248
  return null;
73839
74249
  }
@@ -74140,7 +74550,7 @@ async function runOrder(goal, options, root = process.cwd()) {
74140
74550
  assertNotManagedRun();
74141
74551
  if (!options.resume && [options.retry, options.resolveEffect, options.effectResult, options.accountRun, options.accountCost].some((value) => value !== undefined && value !== false))
74142
74552
  throw new Error("Use --resume <id> for retry, external-effect resolution or cost reconciliation.");
74143
- const store = new MissionStore(join40(root, ".agent-valley/missions"));
74553
+ const store = new MissionStore(join41(root, ".agent-valley/missions"));
74144
74554
  const id = options.resume ?? options.missionId ?? randomUUID19();
74145
74555
  const unlock = await store.lock(id);
74146
74556
  const abortController = new AbortController;
@@ -74318,7 +74728,7 @@ async function dispatchOrder(goal, options, root = process.cwd(), dependencies =
74318
74728
  };
74319
74729
  const [operation, mission] = await Promise.all([
74320
74730
  operationStore(root).load(options.resume).catch(missing),
74321
- new MissionStore(join40(root, ".agent-valley", "missions")).load(options.resume).catch(missing)
74731
+ new MissionStore(join41(root, ".agent-valley", "missions")).load(options.resume).catch(missing)
74322
74732
  ]);
74323
74733
  if (operation && mission)
74324
74734
  throw new Error(`Saved ID ${options.resume} names both an operation and a mission. Use --once to resume the mission; inspect av operations before resuming the operation.`);
@@ -74376,7 +74786,7 @@ function registerChiefCommands(program) {
74376
74786
  process.once("SIGTERM", stop);
74377
74787
  try {
74378
74788
  while (!controller.signal.aborted) {
74379
- const store = new MissionStore(join40(process.cwd(), ".agent-valley/missions"));
74789
+ const store = new MissionStore(join41(process.cwd(), ".agent-valley/missions"));
74380
74790
  for (const mission of await store.list()) {
74381
74791
  if (controller.signal.aborted)
74382
74792
  break;
@@ -74399,7 +74809,7 @@ function registerChiefCommands(program) {
74399
74809
  }
74400
74810
  return;
74401
74811
  }
74402
- const missions = await new MissionStore(join40(process.cwd(), ".agent-valley/missions")).list();
74812
+ const missions = await new MissionStore(join41(process.cwd(), ".agent-valley/missions")).list();
74403
74813
  if (!missions.length)
74404
74814
  console.log("No orders yet. Run bun av order --help.");
74405
74815
  for (const mission of missions) {
@@ -74412,17 +74822,17 @@ function registerChiefCommands(program) {
74412
74822
 
74413
74823
  // src/chief-organization.ts
74414
74824
  import { readFile as readFile15, stat as stat2 } from "node:fs/promises";
74415
- import { isAbsolute as isAbsolute13, join as join41, resolve as resolve22 } from "node:path";
74825
+ import { isAbsolute as isAbsolute14, join as join42, resolve as resolve23 } from "node:path";
74416
74826
  init_chief_schema();
74417
74827
  init_yaml_loader();
74418
74828
  function organizationRepository(root, workspace) {
74419
74829
  const repository = workspace ?? loadProjectConfig(root)?.workspace?.root ?? root;
74420
- if (!isAbsolute13(repository))
74830
+ if (!isAbsolute14(repository))
74421
74831
  throw new Error("Set workspace.root in av.yaml or --workspace to an absolute source repository path.");
74422
74832
  return repository;
74423
74833
  }
74424
74834
  async function inputFile(file) {
74425
- const path = resolve22(file);
74835
+ const path = resolve23(file);
74426
74836
  const info = await stat2(path);
74427
74837
  if (!info.isFile() || info.size > 2000000)
74428
74838
  throw new Error("Use a regular JSON input file no larger than 2 MB.");
@@ -74466,22 +74876,22 @@ function registerOrganizationCommands(program) {
74466
74876
  });
74467
74877
  const reports = program.command("reports").description("Inspect and retry third-party report attachments");
74468
74878
  reports.command("list").option("--workspace <path>", "Source repository").action(async (opts) => {
74469
- console.log(JSON.stringify(await listReportDeliveries(join41(organizationRepository(process.cwd(), opts.workspace), ".agent-valley")), null, 2));
74879
+ console.log(JSON.stringify(await listReportDeliveries(join42(organizationRepository(process.cwd(), opts.workspace), ".agent-valley")), null, 2));
74470
74880
  });
74471
74881
  reports.command("retry").option("--workspace <path>", "Source repository").action(async (opts) => {
74472
74882
  const config = mergeChiefConfig(loadGlobalConfig()?.chief, loadProjectConfig()?.chief);
74473
74883
  if (!config.reporting)
74474
74884
  throw new Error("Set chief.reporting.destinations in av.yaml before retrying reports.");
74475
- console.log(JSON.stringify(await retryPendingReports(config.reporting, join41(organizationRepository(process.cwd(), opts.workspace), ".agent-valley")), null, 2));
74885
+ console.log(JSON.stringify(await retryPendingReports(config.reporting, join42(organizationRepository(process.cwd(), opts.workspace), ".agent-valley")), null, 2));
74476
74886
  });
74477
74887
  }
74478
74888
 
74479
74889
  // src/config-watch.ts
74480
74890
  init_project_config_path();
74481
- import { resolve as resolve25 } from "node:path";
74891
+ import { resolve as resolve26 } from "node:path";
74482
74892
  async function watchConfig(root, globalPath, onChange) {
74483
74893
  await Promise.resolve().then(() => init_chokidar());
74484
- const watcher = watch([resolve25(root, PROJECT_CONFIG_FILENAME), globalPath], { ignoreInitial: true });
74894
+ const watcher = watch([resolve26(root, PROJECT_CONFIG_FILENAME), globalPath], { ignoreInitial: true });
74485
74895
  watcher.on("all", (event, path) => {
74486
74896
  if (["add", "change", "unlink"].includes(event))
74487
74897
  onChange(path);
@@ -74497,10 +74907,10 @@ var import_picocolors = __toESM(require_picocolors(), 1);
74497
74907
  init_project_config_path();
74498
74908
  init_yaml_loader();
74499
74909
  init_doctor_checks();
74500
- import { join as join45 } from "node:path";
74910
+ import { join as join46 } from "node:path";
74501
74911
 
74502
74912
  // src/doctor-oma-checks.ts
74503
- import { join as join44 } from "node:path";
74913
+ import { join as join45 } from "node:path";
74504
74914
  function checkOma(project, deps) {
74505
74915
  const strict = project?.oma?.mode === "strict";
74506
74916
  const order = !!project && !project.tracker && !project.linear && !project.github;
@@ -74588,7 +74998,7 @@ function checkOma(project, deps) {
74588
74998
  fix: "Set verify.command to a deterministic non-build check in av.yaml before using oma.mode: strict.",
74589
74999
  critical: true
74590
75000
  });
74591
- const triggerPath = join44(deps.cwd, ".agents", "hooks", "core", "triggers.json");
75001
+ const triggerPath = join45(deps.cwd, ".agents", "hooks", "core", "triggers.json");
74592
75002
  let table = null;
74593
75003
  try {
74594
75004
  table = parseTriggerTable(deps.readFileSync(triggerPath));
@@ -74605,7 +75015,7 @@ function checkOma(project, deps) {
74605
75015
  return results;
74606
75016
  }
74607
75017
  results.push({ id: "oma.triggers", name: "OMA trigger table", status: "pass", message: triggerPath, critical: false });
74608
- const missing = Object.entries(table.workflows).filter(([name, workflow]) => !workflow.persistent && !table.excludedWorkflows.includes(name)).map(([name]) => join44(deps.cwd, ".agents", "workflows", `${name}.md`)).filter((path) => !deps.existsSync(path));
75018
+ const missing = Object.entries(table.workflows).filter(([name, workflow]) => !workflow.persistent && !table.excludedWorkflows.includes(name)).map(([name]) => join45(deps.cwd, ".agents", "workflows", `${name}.md`)).filter((path) => !deps.existsSync(path));
74609
75019
  results.push(missing.length === 0 ? {
74610
75020
  id: "oma.workflows",
74611
75021
  name: "OMA workflow files",
@@ -74623,6 +75033,37 @@ function checkOma(project, deps) {
74623
75033
  return results;
74624
75034
  }
74625
75035
 
75036
+ // src/doctor-skill-matrix-checks.ts
75037
+ import { resolve as resolve27 } from "node:path";
75038
+ async function checkSkillMatrix(project, global2, deps) {
75039
+ const config = project?.oma?.skill_compatibility;
75040
+ if (!config)
75041
+ return [];
75042
+ const projectActor = project?.actor ?? project?.agent;
75043
+ const globalActor = global2?.actor ?? global2?.agent;
75044
+ const actorType = projectActor?.type ?? globalActor?.type ?? "claude";
75045
+ const model = projectActor?.model ?? (globalActor?.type === actorType ? globalActor.model : undefined);
75046
+ const inspection = await inspectSkillCompatibility({
75047
+ reportPath: resolve27(deps.cwd, config.report_path),
75048
+ maxAgeHours: config.max_age_hours,
75049
+ mode: config.mode
75050
+ }, resolve27(deps.cwd, project?.workspace?.root ?? "."), undefined, [{ actorType, model }], deps.skillMatrix);
75051
+ const route = inspection.routes[0];
75052
+ const status = route?.status ?? "unknown";
75053
+ return [
75054
+ {
75055
+ id: "oma.skill-compatibility",
75056
+ name: "OMA skill read-reference compatibility",
75057
+ status,
75058
+ message: `${config.mode}: ${actorType}/${model ?? "native default"}: ${route?.reason ?? "Evidence unavailable."} Scope: ${inspection.scope}. Work dispatch rechecks its own selected skills and candidates.`,
75059
+ ...status !== "pass" ? {
75060
+ fix: "Generate a completed installed injected matrix with explicit models and set oma.skill_compatibility.report_path in av.yaml. av doctor never runs a live matrix."
75061
+ } : {},
75062
+ critical: config.mode === "require"
75063
+ }
75064
+ ];
75065
+ }
75066
+
74626
75067
  // src/doctor-config-checks.ts
74627
75068
  function checkTunnel(project, deps) {
74628
75069
  const provider = project?.tunnel?.provider ?? "ngrok";
@@ -74649,7 +75090,7 @@ function checkTunnel(project, deps) {
74649
75090
  }
74650
75091
  const mode = project?.tunnel?.cloudflare?.mode ?? "quick";
74651
75092
  if (mode === "named") {
74652
- const certPath = join45(deps.home, ".cloudflared", "cert.pem");
75093
+ const certPath = join46(deps.home, ".cloudflared", "cert.pem");
74653
75094
  if (!deps.existsSync(certPath)) {
74654
75095
  return {
74655
75096
  id: "tunnel",
@@ -74689,7 +75130,7 @@ function checkTunnel(project, deps) {
74689
75130
  critical: false
74690
75131
  };
74691
75132
  }
74692
- const ngrokConfigPath = deps.platform === "darwin" ? join45(deps.home, "Library", "Application Support", "ngrok", "ngrok.yml") : join45(deps.home, ".config", "ngrok", "ngrok.yml");
75133
+ const ngrokConfigPath = deps.platform === "darwin" ? join46(deps.home, "Library", "Application Support", "ngrok", "ngrok.yml") : join46(deps.home, ".config", "ngrok", "ngrok.yml");
74693
75134
  if (!deps.existsSync(ngrokConfigPath)) {
74694
75135
  return {
74695
75136
  id: "tunnel",
@@ -74760,7 +75201,7 @@ function checkConfig(deps) {
74760
75201
  critical: true
74761
75202
  });
74762
75203
  }
74763
- const projectPath = join45(deps.cwd, PROJECT_CONFIG_FILENAME);
75204
+ const projectPath = join46(deps.cwd, PROJECT_CONFIG_FILENAME);
74764
75205
  try {
74765
75206
  project = deps.loadProjectConfig(deps.cwd);
74766
75207
  results.push(project ? {
@@ -74877,10 +75318,11 @@ async function runDoctorChecks(deps, options = {}) {
74877
75318
  results.push(checkTunnel(project, deps));
74878
75319
  results.push(checkWebhookSecret(project));
74879
75320
  results.push(...checkOma(project, deps));
75321
+ results.push(...await checkSkillMatrix(project, global2, deps));
74880
75322
  return results;
74881
75323
  }
74882
75324
  function computeExitCode(results) {
74883
- return results.some((r) => r.critical && r.status === "fail") ? 1 : 0;
75325
+ return results.some((r) => r.critical && (r.status === "fail" || r.status === "unknown")) ? 1 : 0;
74884
75326
  }
74885
75327
  function summarize(results) {
74886
75328
  return { passed: results.filter((r) => r.status === "pass").length, total: results.length };
@@ -74955,7 +75397,7 @@ async function registerLinearWebhook(root, tunnelUrl) {
74955
75397
  init_yaml_loader();
74956
75398
  import { existsSync as existsSync5, readFileSync as readFileSync10, writeFileSync as writeFileSync2 } from "node:fs";
74957
75399
  import { createServer as createServer3 } from "node:net";
74958
- import { resolve as resolve26 } from "node:path";
75400
+ import { resolve as resolve28 } from "node:path";
74959
75401
  import { setTimeout as delay } from "node:timers/promises";
74960
75402
 
74961
75403
  // src/webhook-proxy.ts
@@ -75070,12 +75512,12 @@ function resolveServerPort(root, runningPort) {
75070
75512
  return String(port);
75071
75513
  }
75072
75514
  function resolveRuntimePaths(root, cliDir) {
75073
- const dashboardCwd = resolve26(root, "apps/dashboard");
75074
- if (!existsSync5(resolve26(dashboardCwd, "package.json"))) {
75515
+ const dashboardCwd = resolve28(root, "apps/dashboard");
75516
+ if (!existsSync5(resolve28(dashboardCwd, "package.json"))) {
75075
75517
  throw new Error(`Dashboard source is missing at ${dashboardCwd}. Clone https://github.com/first-fluke/agent-valley, run bun install, then run bun av setup and bun av dev from that checkout. The standalone CLI does not include the dashboard.`);
75076
75518
  }
75077
- const bundled = resolve26(cliDir, "supervisor.js");
75078
- const supervisorScript = existsSync5(bundled) ? bundled : resolve26(cliDir, "supervisor.ts");
75519
+ const bundled = resolve28(cliDir, "supervisor.js");
75520
+ const supervisorScript = existsSync5(bundled) ? bundled : resolve28(cliDir, "supervisor.ts");
75079
75521
  if (!existsSync5(supervisorScript)) {
75080
75522
  throw new Error(`Supervisor is missing at ${supervisorScript}. Run bun av up from an intact Agent Valley checkout.`);
75081
75523
  }
@@ -75354,8 +75796,8 @@ function spawnTunnel(config, input) {
75354
75796
 
75355
75797
  // src/index.ts
75356
75798
  var ROOT = process.cwd();
75357
- var PID_FILE = resolve30(ROOT, ".av.pid");
75358
- var LOG_FILE = resolve30(ROOT, ".av.log");
75799
+ var PID_FILE = resolve32(ROOT, ".av.pid");
75800
+ var LOG_FILE = resolve32(ROOT, ".av.log");
75359
75801
  function ensureConfig() {
75360
75802
  if (!existsSync10(resolveProjectConfigPath(ROOT))) {
75361
75803
  console.log(import_picocolors15.default.red("No av.yaml found. Run `av setup` first."));