agent-contracts 0.25.0 → 0.30.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/cli.js CHANGED
@@ -159,11 +159,11 @@ function __metadata(metadataKey, metadataValue) {
159
159
  }
160
160
  function __awaiter(thisArg, _arguments, P2, generator) {
161
161
  function adopt(value) {
162
- return value instanceof P2 ? value : new P2(function(resolve9) {
163
- resolve9(value);
162
+ return value instanceof P2 ? value : new P2(function(resolve10) {
163
+ resolve10(value);
164
164
  });
165
165
  }
166
- return new (P2 || (P2 = Promise))(function(resolve9, reject) {
166
+ return new (P2 || (P2 = Promise))(function(resolve10, reject) {
167
167
  function fulfilled(value) {
168
168
  try {
169
169
  step(generator.next(value));
@@ -179,7 +179,7 @@ function __awaiter(thisArg, _arguments, P2, generator) {
179
179
  }
180
180
  }
181
181
  function step(result) {
182
- result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
182
+ result.done ? resolve10(result.value) : adopt(result.value).then(fulfilled, rejected);
183
183
  }
184
184
  step((generator = generator.apply(thisArg, _arguments || [])).next());
185
185
  });
@@ -370,14 +370,14 @@ function __asyncValues(o3) {
370
370
  }, i3);
371
371
  function verb(n3) {
372
372
  i3[n3] = o3[n3] && function(v2) {
373
- return new Promise(function(resolve9, reject) {
374
- v2 = o3[n3](v2), settle(resolve9, reject, v2.done, v2.value);
373
+ return new Promise(function(resolve10, reject) {
374
+ v2 = o3[n3](v2), settle(resolve10, reject, v2.done, v2.value);
375
375
  });
376
376
  };
377
377
  }
378
- function settle(resolve9, reject, d2, v2) {
378
+ function settle(resolve10, reject, d2, v2) {
379
379
  Promise.resolve(v2).then(function(v3) {
380
- resolve9({ value: v3, done: d2 });
380
+ resolve10({ value: v3, done: d2 });
381
381
  }, reject);
382
382
  }
383
383
  }
@@ -12937,13 +12937,13 @@ var require_yaml2 = __commonJS({
12937
12937
  function getLocationForJsonPath(result, path) {
12938
12938
  return (0, yaml_1.getLocationForJsonPath)(result, path);
12939
12939
  }
12940
- var parseYaml5 = (input) => (0, yaml_1.parseWithPointers)(input, {
12940
+ var parseYaml6 = (input) => (0, yaml_1.parseWithPointers)(input, {
12941
12941
  ignoreDuplicateKeys: false,
12942
12942
  mergeKeys: true,
12943
12943
  preserveKeyOrder: true,
12944
12944
  attachComments: false
12945
12945
  });
12946
- exports.parseYaml = parseYaml5;
12946
+ exports.parseYaml = parseYaml6;
12947
12947
  exports.Yaml = {
12948
12948
  parse: exports.parseYaml,
12949
12949
  getLocationForJsonPath,
@@ -13033,11 +13033,11 @@ function __metadata2(metadataKey, metadataValue) {
13033
13033
  }
13034
13034
  function __awaiter2(thisArg, _arguments, P2, generator) {
13035
13035
  function adopt(value) {
13036
- return value instanceof P2 ? value : new P2(function(resolve9) {
13037
- resolve9(value);
13036
+ return value instanceof P2 ? value : new P2(function(resolve10) {
13037
+ resolve10(value);
13038
13038
  });
13039
13039
  }
13040
- return new (P2 || (P2 = Promise))(function(resolve9, reject) {
13040
+ return new (P2 || (P2 = Promise))(function(resolve10, reject) {
13041
13041
  function fulfilled(value) {
13042
13042
  try {
13043
13043
  step(generator.next(value));
@@ -13053,7 +13053,7 @@ function __awaiter2(thisArg, _arguments, P2, generator) {
13053
13053
  }
13054
13054
  }
13055
13055
  function step(result) {
13056
- result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
13056
+ result.done ? resolve10(result.value) : adopt(result.value).then(fulfilled, rejected);
13057
13057
  }
13058
13058
  step((generator = generator.apply(thisArg, _arguments || [])).next());
13059
13059
  });
@@ -13231,14 +13231,14 @@ function __asyncValues2(o3) {
13231
13231
  }, i3);
13232
13232
  function verb(n3) {
13233
13233
  i3[n3] = o3[n3] && function(v2) {
13234
- return new Promise(function(resolve9, reject) {
13235
- v2 = o3[n3](v2), settle(resolve9, reject, v2.done, v2.value);
13234
+ return new Promise(function(resolve10, reject) {
13235
+ v2 = o3[n3](v2), settle(resolve10, reject, v2.done, v2.value);
13236
13236
  });
13237
13237
  };
13238
13238
  }
13239
- function settle(resolve9, reject, d2, v2) {
13239
+ function settle(resolve10, reject, d2, v2) {
13240
13240
  Promise.resolve(v2).then(function(v3) {
13241
- resolve9({ value: v3, done: d2 });
13241
+ resolve10({ value: v3, done: d2 });
13242
13242
  }, reject);
13243
13243
  }
13244
13244
  }
@@ -18836,7 +18836,7 @@ function consumeBody() {
18836
18836
  let accum = [];
18837
18837
  let accumBytes = 0;
18838
18838
  let abort = false;
18839
- return new Body.Promise(function(resolve9, reject) {
18839
+ return new Body.Promise(function(resolve10, reject) {
18840
18840
  let resTimeout;
18841
18841
  if (_this4.timeout) {
18842
18842
  resTimeout = setTimeout(function() {
@@ -18870,7 +18870,7 @@ function consumeBody() {
18870
18870
  }
18871
18871
  clearTimeout(resTimeout);
18872
18872
  try {
18873
- resolve9(Buffer.concat(accum, accumBytes));
18873
+ resolve10(Buffer.concat(accum, accumBytes));
18874
18874
  } catch (err) {
18875
18875
  reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, "system", err));
18876
18876
  }
@@ -19133,7 +19133,7 @@ function fetch(url, opts) {
19133
19133
  throw new Error("native promise missing, set fetch.Promise to your favorite alternative");
19134
19134
  }
19135
19135
  Body.Promise = fetch.Promise;
19136
- return new fetch.Promise(function(resolve9, reject) {
19136
+ return new fetch.Promise(function(resolve10, reject) {
19137
19137
  const request = new Request(url, opts);
19138
19138
  const options = getNodeRequestOptions(request);
19139
19139
  const send = (options.protocol === "https:" ? https : http).request;
@@ -19266,7 +19266,7 @@ function fetch(url, opts) {
19266
19266
  requestOpts.body = void 0;
19267
19267
  requestOpts.headers.delete("content-length");
19268
19268
  }
19269
- resolve9(fetch(new Request(locationURL, requestOpts)));
19269
+ resolve10(fetch(new Request(locationURL, requestOpts)));
19270
19270
  finalize();
19271
19271
  return;
19272
19272
  }
@@ -19287,7 +19287,7 @@ function fetch(url, opts) {
19287
19287
  const codings = headers.get("Content-Encoding");
19288
19288
  if (!request.compress || request.method === "HEAD" || codings === null || res.statusCode === 204 || res.statusCode === 304) {
19289
19289
  response = new Response(body, response_options);
19290
- resolve9(response);
19290
+ resolve10(response);
19291
19291
  return;
19292
19292
  }
19293
19293
  const zlibOptions = {
@@ -19297,7 +19297,7 @@ function fetch(url, opts) {
19297
19297
  if (codings == "gzip" || codings == "x-gzip") {
19298
19298
  body = body.pipe(zlib.createGunzip(zlibOptions));
19299
19299
  response = new Response(body, response_options);
19300
- resolve9(response);
19300
+ resolve10(response);
19301
19301
  return;
19302
19302
  }
19303
19303
  if (codings == "deflate" || codings == "x-deflate") {
@@ -19309,12 +19309,12 @@ function fetch(url, opts) {
19309
19309
  body = body.pipe(zlib.createInflateRaw());
19310
19310
  }
19311
19311
  response = new Response(body, response_options);
19312
- resolve9(response);
19312
+ resolve10(response);
19313
19313
  });
19314
19314
  raw.on("end", function() {
19315
19315
  if (!response) {
19316
19316
  response = new Response(body, response_options);
19317
- resolve9(response);
19317
+ resolve10(response);
19318
19318
  }
19319
19319
  });
19320
19320
  return;
@@ -19322,11 +19322,11 @@ function fetch(url, opts) {
19322
19322
  if (codings == "br" && typeof zlib.createBrotliDecompress === "function") {
19323
19323
  body = body.pipe(zlib.createBrotliDecompress());
19324
19324
  response = new Response(body, response_options);
19325
- resolve9(response);
19325
+ resolve10(response);
19326
19326
  return;
19327
19327
  }
19328
19328
  response = new Response(body, response_options);
19329
- resolve9(response);
19329
+ resolve10(response);
19330
19330
  });
19331
19331
  writeToStream(req, request);
19332
19332
  });
@@ -20039,13 +20039,13 @@ var require_file = __commonJS({
20039
20039
  Object.defineProperty(exports, "__esModule", { value: true });
20040
20040
  var fs_1 = __require("fs");
20041
20041
  function resolveFile(ref) {
20042
- return new Promise((resolve9, reject) => {
20042
+ return new Promise((resolve10, reject) => {
20043
20043
  const path = ref.href();
20044
20044
  fs_1.readFile(path, "utf8", (err, data) => {
20045
20045
  if (err) {
20046
20046
  reject(err);
20047
20047
  } else {
20048
- resolve9(data);
20048
+ resolve10(data);
20049
20049
  }
20050
20050
  });
20051
20051
  });
@@ -27648,12 +27648,12 @@ var require_reader = __commonJS({
27648
27648
  }
27649
27649
  } else {
27650
27650
  try {
27651
- return await new Promise((resolve9, reject) => {
27651
+ return await new Promise((resolve10, reject) => {
27652
27652
  fs.readFile(name, opts.encoding, (err, data) => {
27653
27653
  if (err !== null) {
27654
27654
  reject(err);
27655
27655
  } else {
27656
- resolve9(data);
27656
+ resolve10(data);
27657
27657
  }
27658
27658
  });
27659
27659
  });
@@ -40342,17 +40342,19 @@ var require_errors = __commonJS({
40342
40342
  exports.convertAjvErrors = exports.RulesetValidationError = void 0;
40343
40343
  var isAggregateError_1 = require_isAggregateError();
40344
40344
  var RulesetValidationError = class extends Error {
40345
- constructor(code, message, path) {
40345
+ constructor(code, message, path, location2) {
40346
40346
  super(message);
40347
40347
  this.code = code;
40348
40348
  this.message = message;
40349
40349
  this.path = path;
40350
+ this.range = location2 === null || location2 === void 0 ? void 0 : location2.range;
40351
+ this.source = location2 === null || location2 === void 0 ? void 0 : location2.source;
40350
40352
  }
40351
40353
  };
40352
40354
  exports.RulesetValidationError = RulesetValidationError;
40353
40355
  var RULE_INSTANCE_PATH = /^\/rules\/[^/]+/;
40354
40356
  var GENERIC_INSTANCE_PATH = /^\/(?:aliases|extends|overrides(?:\/\d+\/extends)?)/;
40355
- function convertAjvErrors(errors) {
40357
+ function convertAjvErrors(errors, sourceContext) {
40356
40358
  const sortedErrors = [...errors].sort((errorA, errorB) => {
40357
40359
  const diff = errorA.instancePath.length - errorB.instancePath.length;
40358
40360
  return diff === 0 ? errorA.keyword === "errorMessage" && errorB.keyword !== "errorMessage" ? -1 : 0 : diff;
@@ -40385,10 +40387,12 @@ var require_errors = __commonJS({
40385
40387
  return filteredErrors.flatMap((error) => {
40386
40388
  var _a;
40387
40389
  if (error.keyword === "x-spectral-runtime") {
40388
- return flatErrors(error.params.errors);
40390
+ const flat = flatErrors(error.params.errors);
40391
+ const list = Array.isArray(flat) ? flat : [flat];
40392
+ return list.map((e3) => enrichWithLocation(e3, sourceContext));
40389
40393
  }
40390
40394
  const path = error.instancePath.slice(1).split("/");
40391
- return new RulesetValidationError(inferErrorCode(path, error.keyword), (_a = error.message) !== null && _a !== void 0 ? _a : "unknown error", path);
40395
+ return new RulesetValidationError(inferErrorCode(path, error.keyword), (_a = error.message) !== null && _a !== void 0 ? _a : "unknown error", path, resolveLocation(path, sourceContext));
40392
40396
  });
40393
40397
  }
40394
40398
  exports.convertAjvErrors = convertAjvErrors;
@@ -40398,6 +40402,22 @@ var require_errors = __commonJS({
40398
40402
  }
40399
40403
  return error;
40400
40404
  }
40405
+ function resolveLocation(path, sourceContext) {
40406
+ var _a;
40407
+ if (sourceContext === void 0) {
40408
+ return void 0;
40409
+ }
40410
+ return {
40411
+ source: sourceContext.source,
40412
+ range: (_a = sourceContext.getLocationForJsonPath(path)) === null || _a === void 0 ? void 0 : _a.range
40413
+ };
40414
+ }
40415
+ function enrichWithLocation(error, sourceContext) {
40416
+ if (sourceContext === void 0 || error.source !== void 0 || error.range !== void 0) {
40417
+ return error;
40418
+ }
40419
+ return new RulesetValidationError(error.code, error.message, error.path, resolveLocation(error.path, sourceContext));
40420
+ }
40401
40421
  function inferErrorCode(path, keyword) {
40402
40422
  if (path.length === 0) {
40403
40423
  return "generic-validation-error";
@@ -44538,14 +44558,14 @@ var require_AsyncFromSyncIteratorContinuation = __commonJS({
44538
44558
  if (!$Promise) {
44539
44559
  throw new $SyntaxError("This environment does not support Promises.");
44540
44560
  }
44541
- return new $Promise(function(resolve9) {
44561
+ return new $Promise(function(resolve10) {
44542
44562
  var done = IteratorComplete(result);
44543
44563
  var value = IteratorValue(result);
44544
44564
  var valueWrapper = PromiseResolve($Promise, value);
44545
44565
  var onFulfilled = function(value2) {
44546
44566
  return CreateIteratorResultObject(value2, done);
44547
44567
  };
44548
- resolve9($then(valueWrapper, onFulfilled));
44568
+ resolve10($then(valueWrapper, onFulfilled));
44549
44569
  });
44550
44570
  };
44551
44571
  }
@@ -45093,7 +45113,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
45093
45113
  var O2 = this;
45094
45114
  SLOT.assert(O2, "[[SyncIteratorRecord]]");
45095
45115
  var argsLength = arguments.length;
45096
- return new $Promise(function(resolve9) {
45116
+ return new $Promise(function(resolve10) {
45097
45117
  var syncIteratorRecord = SLOT.get(O2, "[[SyncIteratorRecord]]");
45098
45118
  var result;
45099
45119
  if (argsLength > 0) {
@@ -45101,7 +45121,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
45101
45121
  } else {
45102
45122
  result = IteratorNext(syncIteratorRecord);
45103
45123
  }
45104
- resolve9(AsyncFromSyncIteratorContinuation(result));
45124
+ resolve10(AsyncFromSyncIteratorContinuation(result));
45105
45125
  });
45106
45126
  },
45107
45127
  "return": function() {
@@ -45112,12 +45132,12 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
45112
45132
  SLOT.assert(O2, "[[SyncIteratorRecord]]");
45113
45133
  var valueIsPresent = arguments.length > 0;
45114
45134
  var value = valueIsPresent ? arguments[0] : void 0;
45115
- return new $Promise(function(resolve9, reject) {
45135
+ return new $Promise(function(resolve10, reject) {
45116
45136
  var syncIterator = SLOT.get(O2, "[[SyncIteratorRecord]]")["[[Iterator]]"];
45117
45137
  var iteratorReturn = GetMethod(syncIterator, "return");
45118
45138
  if (typeof iteratorReturn === "undefined") {
45119
45139
  var iterResult = CreateIteratorResultObject(value, true);
45120
- Call(resolve9, void 0, [iterResult]);
45140
+ Call(resolve10, void 0, [iterResult]);
45121
45141
  return;
45122
45142
  }
45123
45143
  var result;
@@ -45130,7 +45150,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
45130
45150
  Call(reject, void 0, [new $TypeError("Iterator `return` method returned a non-object value.")]);
45131
45151
  return;
45132
45152
  }
45133
- resolve9(AsyncFromSyncIteratorContinuation(result));
45153
+ resolve10(AsyncFromSyncIteratorContinuation(result));
45134
45154
  });
45135
45155
  },
45136
45156
  "throw": function() {
@@ -45141,7 +45161,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
45141
45161
  SLOT.assert(O2, "[[SyncIteratorRecord]]");
45142
45162
  var valueIsPresent = arguments.length > 0;
45143
45163
  var value = valueIsPresent ? arguments[0] : void 0;
45144
- return new $Promise(function(resolve9, reject) {
45164
+ return new $Promise(function(resolve10, reject) {
45145
45165
  var syncIterator = SLOT.get(O2, "[[SyncIteratorRecord]]")["[[Iterator]]"];
45146
45166
  var throwMethod = GetMethod(syncIterator, "throw");
45147
45167
  if (typeof throwMethod === "undefined") {
@@ -45158,7 +45178,7 @@ var require_CreateAsyncFromSyncIterator = __commonJS({
45158
45178
  Call(reject, void 0, [new $TypeError("Iterator `throw` method returned a non-object value.")]);
45159
45179
  return;
45160
45180
  }
45161
- resolve9(AsyncFromSyncIteratorContinuation(
45181
+ resolve10(AsyncFromSyncIteratorContinuation(
45162
45182
  result
45163
45183
  /* , promiseCapability */
45164
45184
  ));
@@ -45918,17 +45938,17 @@ var require_assertions = __commonJS({
45918
45938
  var ajv_1 = require_ajv();
45919
45939
  var errors_1 = require_errors();
45920
45940
  var es_aggregate_error_1 = (0, tslib_1.__importDefault)(require_es_aggregate_error());
45921
- function assertValidRuleset(ruleset2, format2 = "js") {
45922
- var _a;
45941
+ function assertValidRuleset(ruleset2, format2 = "js", sourceContext) {
45942
+ var _a, _b;
45923
45943
  if (!(0, json_1.isPlainObject)(ruleset2)) {
45924
- throw new errors_1.RulesetValidationError("invalid-ruleset-definition", "Provided ruleset is not an object", []);
45944
+ throw new errors_1.RulesetValidationError("invalid-ruleset-definition", "Provided ruleset is not an object", [], sourceContext === void 0 ? void 0 : { source: sourceContext.source });
45925
45945
  }
45926
45946
  if (!("rules" in ruleset2) && !("extends" in ruleset2) && !("overrides" in ruleset2)) {
45927
- throw new errors_1.RulesetValidationError("invalid-ruleset-definition", "Ruleset must have rules or extends or overrides defined", []);
45947
+ throw new errors_1.RulesetValidationError("invalid-ruleset-definition", "Ruleset must have rules or extends or overrides defined", [], sourceContext === void 0 ? void 0 : { source: sourceContext.source, range: (_a = sourceContext.getLocationForJsonPath([])) === null || _a === void 0 ? void 0 : _a.range });
45928
45948
  }
45929
45949
  const validate = (0, ajv_1.createValidator)(format2);
45930
45950
  if (!validate(ruleset2)) {
45931
- throw new es_aggregate_error_1.default((0, errors_1.convertAjvErrors)((_a = validate.errors) !== null && _a !== void 0 ? _a : []));
45951
+ throw new es_aggregate_error_1.default((0, errors_1.convertAjvErrors)((_b = validate.errors) !== null && _b !== void 0 ? _b : [], sourceContext));
45932
45952
  }
45933
45953
  }
45934
45954
  exports.assertValidRuleset = assertValidRuleset;
@@ -46098,10 +46118,10 @@ var require_ruleset = __commonJS({
46098
46118
  let definition;
46099
46119
  if ((0, json_1.isPlainObject)(maybeDefinition) && "extends" in maybeDefinition) {
46100
46120
  const { extends: _2, ...def } = maybeDefinition;
46101
- (0, index_1.assertValidRuleset)({ extends: [], ...def }, "js");
46121
+ (0, index_1.assertValidRuleset)({ extends: [], ...def }, "js", context === null || context === void 0 ? void 0 : context.sourceContext);
46102
46122
  definition = maybeDefinition;
46103
46123
  } else {
46104
- (0, index_1.assertValidRuleset)(maybeDefinition, "js");
46124
+ (0, index_1.assertValidRuleset)(maybeDefinition, "js", context === null || context === void 0 ? void 0 : context.sourceContext);
46105
46125
  definition = maybeDefinition;
46106
46126
  }
46107
46127
  this.definition = definition;
@@ -48889,9 +48909,9 @@ var require_dist14 = __commonJS({
48889
48909
  });
48890
48910
 
48891
48911
  // src/cli/cli.ts
48892
- import { readFileSync as readFileSync2 } from "fs";
48912
+ import { readFileSync as readFileSync3 } from "fs";
48893
48913
  import { fileURLToPath } from "url";
48894
- import { resolve as resolve8, dirname as dirname8 } from "path";
48914
+ import { resolve as resolve9, dirname as dirname8 } from "path";
48895
48915
 
48896
48916
  // src/generated/cli-contract/program.ts
48897
48917
  import { Command } from "commander";
@@ -48930,9 +48950,9 @@ function derivePolicy(input) {
48930
48950
  const riskLevels = [];
48931
48951
  let executionMode;
48932
48952
  let explicitConfirmation;
48933
- if (input.commandEffects) {
48934
- const ce2 = input.commandEffects;
48935
- riskLevels.push(ce2.riskLevel ?? "low");
48953
+ if (input.command_effects) {
48954
+ const ce2 = input.command_effects;
48955
+ riskLevels.push(ce2.risk_level ?? "low");
48936
48956
  if (ce2.writes) {
48937
48957
  sideEffects.add("file_write");
48938
48958
  for (const w2 of ce2.writes) {
@@ -48943,9 +48963,9 @@ function derivePolicy(input) {
48943
48963
  overwrite: w2.overwrite,
48944
48964
  destructive: w2.destructive,
48945
48965
  ...w2.idempotent !== void 0 ? { idempotent: w2.idempotent } : {},
48946
- ...w2.idempotencyKey ? { idempotencyKey: w2.idempotencyKey } : {},
48947
- ...w2.idempotentNote ? { idempotentNote: w2.idempotentNote } : {},
48948
- source: `command:${input.commandId}`
48966
+ ...w2.idempotency_key ? { idempotency_key: w2.idempotency_key } : {},
48967
+ ...w2.idempotent_note ? { idempotent_note: w2.idempotent_note } : {},
48968
+ source: `command:${input.command_id}`
48949
48969
  });
48950
48970
  }
48951
48971
  }
@@ -48955,7 +48975,7 @@ function derivePolicy(input) {
48955
48975
  kind: "semantic",
48956
48976
  target: r3.target,
48957
48977
  description: r3.description,
48958
- source: `command:${input.commandId}`
48978
+ source: `command:${input.command_id}`
48959
48979
  });
48960
48980
  }
48961
48981
  }
@@ -48966,17 +48986,17 @@ function derivePolicy(input) {
48966
48986
  ...ce2.network.description ? { description: ce2.network.description } : {},
48967
48987
  ...ce2.network.domains ? { domains: ce2.network.domains } : {},
48968
48988
  ...ce2.network.idempotent !== void 0 ? { idempotent: ce2.network.idempotent } : {},
48969
- ...ce2.network.idempotencyKey ? { idempotencyKey: ce2.network.idempotencyKey } : {},
48970
- ...ce2.network.idempotentNote ? { idempotentNote: ce2.network.idempotentNote } : {},
48971
- source: `command:${input.commandId}`
48989
+ ...ce2.network.idempotency_key ? { idempotency_key: ce2.network.idempotency_key } : {},
48990
+ ...ce2.network.idempotent_note ? { idempotent_note: ce2.network.idempotent_note } : {},
48991
+ source: `command:${input.command_id}`
48972
48992
  });
48973
48993
  }
48974
48994
  }
48975
- if (ce2.executionMode) {
48976
- executionMode = ce2.executionMode;
48995
+ if (ce2.execution_mode) {
48996
+ executionMode = ce2.execution_mode;
48977
48997
  }
48978
- if (ce2.requiresConfirmation !== void 0) {
48979
- explicitConfirmation = ce2.requiresConfirmation;
48998
+ if (ce2.requires_confirmation !== void 0) {
48999
+ explicitConfirmation = ce2.requires_confirmation;
48980
49000
  }
48981
49001
  }
48982
49002
  for (const [optName, optInput] of Object.entries(input.options)) {
@@ -49007,7 +49027,7 @@ function derivePolicy(input) {
49007
49027
  }
49008
49028
  if (definition.effects) {
49009
49029
  const eff = definition.effects;
49010
- riskLevels.push(eff.riskLevel ?? "low");
49030
+ riskLevels.push(eff.risk_level ?? "low");
49011
49031
  if (eff.writes) {
49012
49032
  sideEffects.add("file_write");
49013
49033
  for (const w2 of eff.writes) {
@@ -49018,8 +49038,8 @@ function derivePolicy(input) {
49018
49038
  overwrite: w2.overwrite,
49019
49039
  destructive: w2.destructive,
49020
49040
  ...w2.idempotent !== void 0 ? { idempotent: w2.idempotent } : {},
49021
- ...w2.idempotencyKey ? { idempotencyKey: w2.idempotencyKey } : {},
49022
- ...w2.idempotentNote ? { idempotentNote: w2.idempotentNote } : {},
49041
+ ...w2.idempotency_key ? { idempotency_key: w2.idempotency_key } : {},
49042
+ ...w2.idempotent_note ? { idempotent_note: w2.idempotent_note } : {},
49023
49043
  source: `option:${optName}`
49024
49044
  });
49025
49045
  }
@@ -49041,17 +49061,17 @@ function derivePolicy(input) {
49041
49061
  ...eff.network.description ? { description: eff.network.description } : {},
49042
49062
  ...eff.network.domains ? { domains: eff.network.domains } : {},
49043
49063
  ...eff.network.idempotent !== void 0 ? { idempotent: eff.network.idempotent } : {},
49044
- ...eff.network.idempotencyKey ? { idempotencyKey: eff.network.idempotencyKey } : {},
49045
- ...eff.network.idempotentNote ? { idempotentNote: eff.network.idempotentNote } : {},
49064
+ ...eff.network.idempotency_key ? { idempotency_key: eff.network.idempotency_key } : {},
49065
+ ...eff.network.idempotent_note ? { idempotent_note: eff.network.idempotent_note } : {},
49046
49066
  source: `option:${optName}`
49047
49067
  });
49048
49068
  }
49049
49069
  }
49050
- if (eff.executionMode && !executionMode) {
49051
- executionMode = eff.executionMode;
49070
+ if (eff.execution_mode && !executionMode) {
49071
+ executionMode = eff.execution_mode;
49052
49072
  }
49053
- if (eff.requiresConfirmation !== void 0 && explicitConfirmation === void 0) {
49054
- explicitConfirmation = eff.requiresConfirmation;
49073
+ if (eff.requires_confirmation !== void 0 && explicitConfirmation === void 0) {
49074
+ explicitConfirmation = eff.requires_confirmation;
49055
49075
  }
49056
49076
  }
49057
49077
  }
@@ -49072,15 +49092,15 @@ function derivePolicy(input) {
49072
49092
  const semanticWrites = writes.filter((w2) => w2.kind === "semantic");
49073
49093
  const idempotent = semanticWrites.every((w2) => w2.idempotent === true) && networkEffects.every((n3) => n3.idempotent === true);
49074
49094
  return {
49075
- riskLevel: finalRiskLevel,
49076
- requiresConfirmation,
49095
+ risk_level: finalRiskLevel,
49096
+ requires_confirmation: requiresConfirmation,
49077
49097
  idempotent,
49078
- sideEffects: [...sideEffects],
49098
+ side_effects: [...sideEffects],
49079
49099
  reads,
49080
49100
  writes,
49081
49101
  ...networkEffects.length > 0 ? { network: networkEffects } : {},
49082
- ...executionMode ? { executionMode } : {},
49083
- ...requiresSecrets ? { requiresSecrets } : {}
49102
+ ...executionMode ? { execution_mode: executionMode } : {},
49103
+ ...requiresSecrets ? { requires_secrets: requiresSecrets } : {}
49084
49104
  };
49085
49105
  }
49086
49106
 
@@ -49096,7 +49116,7 @@ var commandDefinitions = {
49096
49116
  "file": {
49097
49117
  "mode": "read",
49098
49118
  "exists": false,
49099
- "mediaType": "application/yaml",
49119
+ "media_type": "application/yaml",
49100
49120
  "encoding": "utf-8"
49101
49121
  }
49102
49122
  },
@@ -49136,7 +49156,7 @@ var commandDefinitions = {
49136
49156
  "file": {
49137
49157
  "mode": "read",
49138
49158
  "exists": false,
49139
- "mediaType": "application/yaml",
49159
+ "media_type": "application/yaml",
49140
49160
  "encoding": "utf-8"
49141
49161
  }
49142
49162
  },
@@ -49183,7 +49203,7 @@ var commandDefinitions = {
49183
49203
  "file": {
49184
49204
  "mode": "read",
49185
49205
  "exists": false,
49186
- "mediaType": "application/yaml",
49206
+ "media_type": "application/yaml",
49187
49207
  "encoding": "utf-8"
49188
49208
  }
49189
49209
  },
@@ -49222,15 +49242,9 @@ var commandDefinitions = {
49222
49242
  },
49223
49243
  "render": {
49224
49244
  "effects": {
49225
- "riskLevel": "medium",
49245
+ "risk_level": "medium",
49226
49246
  "writes": [
49227
- {
49228
- "target": "configured render output paths",
49229
- "description": "rendered template files from DSL input",
49230
- "overwrite": true,
49231
- "idempotent": true,
49232
- "idempotentNote": "Output is deterministic from DSL input and templates. Repeated runs produce identical files."
49233
- }
49247
+ "generated-templates"
49234
49248
  ]
49235
49249
  },
49236
49250
  "options": [
@@ -49242,7 +49256,7 @@ var commandDefinitions = {
49242
49256
  "file": {
49243
49257
  "mode": "read",
49244
49258
  "exists": false,
49245
- "mediaType": "application/yaml",
49259
+ "media_type": "application/yaml",
49246
49260
  "encoding": "utf-8"
49247
49261
  }
49248
49262
  },
@@ -49278,7 +49292,7 @@ var commandDefinitions = {
49278
49292
  "file": {
49279
49293
  "mode": "read",
49280
49294
  "exists": false,
49281
- "mediaType": "application/yaml",
49295
+ "media_type": "application/yaml",
49282
49296
  "encoding": "utf-8"
49283
49297
  }
49284
49298
  },
@@ -49325,7 +49339,7 @@ var commandDefinitions = {
49325
49339
  "file": {
49326
49340
  "mode": "read",
49327
49341
  "exists": false,
49328
- "mediaType": "application/yaml",
49342
+ "media_type": "application/yaml",
49329
49343
  "encoding": "utf-8"
49330
49344
  }
49331
49345
  },
@@ -49356,11 +49370,18 @@ var commandDefinitions = {
49356
49370
  },
49357
49371
  "audit": {
49358
49372
  "effects": {
49359
- "riskLevel": "medium",
49373
+ "risk_level": "medium",
49374
+ "reads": [
49375
+ "dsl-definitions",
49376
+ "config"
49377
+ ],
49378
+ "writes": [
49379
+ "audit-report"
49380
+ ],
49360
49381
  "network": {
49361
49382
  "description": "LLM API calls to configured adapter (e.g. OpenAI, Gemini, Cursor). Incurs token cost and sends DSL content to the LLM provider.",
49362
49383
  "idempotent": false,
49363
- "idempotentNote": "LLM inference is non-deterministic \u2014 identical inputs may produce different findings across runs."
49384
+ "idempotent_note": "LLM inference is non-deterministic \u2014 identical inputs may produce different findings across runs."
49364
49385
  }
49365
49386
  },
49366
49387
  "options": [
@@ -49372,7 +49393,7 @@ var commandDefinitions = {
49372
49393
  "file": {
49373
49394
  "mode": "read",
49374
49395
  "exists": false,
49375
- "mediaType": "application/yaml",
49396
+ "media_type": "application/yaml",
49376
49397
  "encoding": "utf-8"
49377
49398
  }
49378
49399
  },
@@ -49458,15 +49479,11 @@ var commandDefinitions = {
49458
49479
  },
49459
49480
  "generate": {
49460
49481
  "effects": {
49461
- "riskLevel": "low",
49482
+ "risk_level": "low",
49462
49483
  "writes": [
49463
- {
49464
- "target": "configured render, guardrail, and interface output paths",
49465
- "description": "template files, guardrail binding files, and/or team interface files generated from DSL input",
49466
- "overwrite": true,
49467
- "idempotent": true,
49468
- "idempotentNote": "Output is deterministic from DSL input, templates, policies, and bindings. Repeated runs produce identical files."
49469
- }
49484
+ "generated-templates",
49485
+ "generated-guardrails",
49486
+ "generated-interface"
49470
49487
  ]
49471
49488
  },
49472
49489
  "options": [
@@ -49478,7 +49495,7 @@ var commandDefinitions = {
49478
49495
  "file": {
49479
49496
  "mode": "read",
49480
49497
  "exists": false,
49481
- "mediaType": "application/yaml",
49498
+ "media_type": "application/yaml",
49482
49499
  "encoding": "utf-8"
49483
49500
  }
49484
49501
  },
@@ -49509,7 +49526,7 @@ var commandDefinitions = {
49509
49526
  },
49510
49527
  "file": {
49511
49528
  "mode": "write",
49512
- "mediaType": "application/yaml",
49529
+ "media_type": "application/yaml",
49513
49530
  "encoding": "utf-8"
49514
49531
  }
49515
49532
  },
@@ -49539,29 +49556,75 @@ var commandDefinitions = {
49539
49556
  }
49540
49557
  }
49541
49558
  ]
49559
+ },
49560
+ "navigation-index": {
49561
+ "options": [
49562
+ {
49563
+ "name": "config",
49564
+ "schema": {
49565
+ "type": "string"
49566
+ },
49567
+ "file": {
49568
+ "mode": "read",
49569
+ "exists": false,
49570
+ "media_type": "application/yaml",
49571
+ "encoding": "utf-8"
49572
+ }
49573
+ },
49574
+ {
49575
+ "name": "team",
49576
+ "schema": {
49577
+ "type": "string"
49578
+ }
49579
+ },
49580
+ {
49581
+ "name": "format",
49582
+ "schema": {
49583
+ "type": "string",
49584
+ "enum": [
49585
+ "json",
49586
+ "yaml"
49587
+ ],
49588
+ "default": "json"
49589
+ }
49590
+ },
49591
+ {
49592
+ "name": "artifact",
49593
+ "schema": {
49594
+ "type": "string"
49595
+ }
49596
+ },
49597
+ {
49598
+ "name": "quiet",
49599
+ "schema": {
49600
+ "type": "boolean",
49601
+ "default": false
49602
+ }
49603
+ }
49604
+ ]
49542
49605
  }
49543
49606
  };
49544
- function deriveCommandPolicy(commandId, optionValues) {
49545
- const def = commandDefinitions[commandId];
49546
- if (!def) throw new Error(`Unknown command: ${commandId}`);
49607
+ function deriveCommandPolicy(command_id, optionValues) {
49608
+ const def = commandDefinitions[command_id];
49609
+ if (!def) throw new Error(`Unknown command: ${command_id}`);
49547
49610
  const cmdDef = def;
49548
49611
  const options = {};
49549
- const activeOptions = [];
49612
+ const active_options = [];
49550
49613
  for (const optDef of cmdDef.options ?? []) {
49551
49614
  const value = optionValues[optDef.name];
49552
49615
  const specified = optDef.name in optionValues && value !== void 0;
49553
49616
  options[optDef.name] = { value, specified, definition: optDef };
49554
49617
  if (isOptionActive(optDef, value, specified)) {
49555
- activeOptions.push(optDef.name);
49618
+ active_options.push(optDef.name);
49556
49619
  }
49557
49620
  }
49558
49621
  const policy = derivePolicy({
49559
- commandId,
49560
- commandEffects: cmdDef.effects,
49622
+ command_id,
49623
+ command_effects: cmdDef.effects,
49561
49624
  options,
49562
49625
  env: cmdDef.env
49563
49626
  });
49564
- return { command: commandId, activeOptions, policy };
49627
+ return { command: command_id, active_options, policy };
49565
49628
  }
49566
49629
 
49567
49630
  // src/generated/cli-contract/program.ts
@@ -49641,16 +49704,25 @@ function createProgram(handlers2, version) {
49641
49704
  }
49642
49705
  await handlers2.generate(type, opts, globalOpts);
49643
49706
  });
49707
+ program2.command("navigation-index").description("Build artifact-centric navigation index from resolved DSL.").argument("[dir]", "Path to agent-contracts.yaml.").option("-c, --config <path>", "Path to agent-contracts.config.yaml.").option("--team <id>", "Limit to one team (multi-team config only).").option("--format <format>", "Output format.", "json").option("--artifact <id>", "Filter output to a single artifact by ID.").option("--quiet", "Suppress informational output.", false).action(async (dir, opts, cmd) => {
49708
+ const globalOpts = cmd.optsWithGlobals();
49709
+ if (globalOpts.introspect) {
49710
+ const policy = deriveCommandPolicy("navigation-index", opts);
49711
+ console.log(JSON.stringify(policy, null, 2));
49712
+ return;
49713
+ }
49714
+ await handlers2.navigationIndex(dir, opts, globalOpts);
49715
+ });
49644
49716
  return program2;
49645
49717
  }
49646
49718
 
49647
49719
  // src/cli/handlers.ts
49648
49720
  import { writeFileSync as writeFileSync2 } from "fs";
49649
- import { existsSync, readFileSync } from "fs";
49721
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
49650
49722
  import { join as join3, dirname as dirname7 } from "path";
49651
49723
  import { resolve as pathResolve } from "path";
49652
49724
  import { access as access2 } from "fs/promises";
49653
- import { stringify as stringify3, parse as parseYaml4 } from "yaml";
49725
+ import { stringify as stringify3, parse as parseYaml5 } from "yaml";
49654
49726
 
49655
49727
  // src/config/binding-loader.ts
49656
49728
  import { readFile as readFile3 } from "fs/promises";
@@ -49746,11 +49818,12 @@ var CONTEXT_TYPES = [
49746
49818
  "policy",
49747
49819
  "guardrail",
49748
49820
  "guardrail_policy",
49749
- "system"
49821
+ "system",
49822
+ "navigation_index"
49750
49823
  ];
49751
49824
  var ContextTypeSchema = z3.enum(CONTEXT_TYPES);
49752
49825
  var ITERABLE_CONTEXT_TYPES = CONTEXT_TYPES.filter(
49753
- (t3) => t3 !== "system"
49826
+ (t3) => t3 !== "system" && t3 !== "navigation_index"
49754
49827
  );
49755
49828
 
49756
49829
  // src/schema/binding.ts
@@ -49988,7 +50061,9 @@ var CommandSchema = z12.object({
49988
50061
  purpose: z12.string().optional()
49989
50062
  });
49990
50063
  var ToolSchema = z12.object({
49991
- kind: z12.string(),
50064
+ kind: z12.string().optional(),
50065
+ extends: z12.string().optional(),
50066
+ command: z12.string().optional(),
49992
50067
  description: z12.string().optional(),
49993
50068
  input_artifacts: z12.array(z12.string()).default([]),
49994
50069
  output_artifacts: z12.array(z12.string()).default([]),
@@ -51139,6 +51214,123 @@ function mergeDsl(base, project) {
51139
51214
 
51140
51215
  // src/resolver/resolve.ts
51141
51216
  import { dirname as dirname3, resolve as resolvePath } from "path";
51217
+
51218
+ // src/resolver/tool-extends.ts
51219
+ var ToolExtendsError = class extends Error {
51220
+ constructor(message) {
51221
+ super(message);
51222
+ this.name = "ToolExtendsError";
51223
+ }
51224
+ };
51225
+ function asStringArray(value) {
51226
+ return Array.isArray(value) ? value : [];
51227
+ }
51228
+ function asRecord(value) {
51229
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
51230
+ return value;
51231
+ }
51232
+ return {};
51233
+ }
51234
+ function asCommands(value) {
51235
+ return Array.isArray(value) ? value : [];
51236
+ }
51237
+ function isUnset(value) {
51238
+ return value === void 0 || value === null;
51239
+ }
51240
+ function mergeToolFields(base, child) {
51241
+ const merged = { ...child };
51242
+ merged.artifact_bindings = {
51243
+ ...asRecord(base.artifact_bindings),
51244
+ ...asRecord(child.artifact_bindings)
51245
+ };
51246
+ if (isUnset(child.kind) && !isUnset(base.kind)) {
51247
+ merged.kind = base.kind;
51248
+ }
51249
+ if (isUnset(child.cli_contract) && !isUnset(base.cli_contract)) {
51250
+ merged.cli_contract = base.cli_contract;
51251
+ }
51252
+ if (isUnset(child.description) && !isUnset(base.description)) {
51253
+ merged.description = base.description;
51254
+ }
51255
+ const childInvokableBy = asStringArray(child.invokable_by);
51256
+ const baseInvokableBy = asStringArray(base.invokable_by);
51257
+ if (childInvokableBy.length === 0 && baseInvokableBy.length > 0) {
51258
+ merged.invokable_by = [...baseInvokableBy];
51259
+ }
51260
+ const childInputArtifacts = asStringArray(child.input_artifacts);
51261
+ const baseInputArtifacts = asStringArray(base.input_artifacts);
51262
+ if (childInputArtifacts.length === 0 && baseInputArtifacts.length > 0) {
51263
+ merged.input_artifacts = [...baseInputArtifacts];
51264
+ }
51265
+ const childOutputArtifacts = asStringArray(child.output_artifacts);
51266
+ const baseOutputArtifacts = asStringArray(base.output_artifacts);
51267
+ if (childOutputArtifacts.length === 0 && baseOutputArtifacts.length > 0) {
51268
+ merged.output_artifacts = [...baseOutputArtifacts];
51269
+ }
51270
+ const childSideEffects = asStringArray(child.side_effects);
51271
+ const baseSideEffects = asStringArray(base.side_effects);
51272
+ if (childSideEffects.length === 0 && baseSideEffects.length > 0) {
51273
+ merged.side_effects = [...baseSideEffects];
51274
+ }
51275
+ const childCommands = asCommands(child.commands);
51276
+ const baseCommands = asCommands(base.commands);
51277
+ if (childCommands.length === 0 && baseCommands.length > 0) {
51278
+ merged.commands = [...baseCommands];
51279
+ }
51280
+ if (isUnset(child.guardrails) && !isUnset(base.guardrails)) {
51281
+ merged.guardrails = base.guardrails;
51282
+ }
51283
+ return merged;
51284
+ }
51285
+ function resolveToolChain(id, tools, resolving, resolved) {
51286
+ const cached = resolved.get(id);
51287
+ if (cached !== void 0) {
51288
+ return cached;
51289
+ }
51290
+ const tool = tools[id];
51291
+ if (tool === void 0) {
51292
+ throw new ToolExtendsError(`Tool "${id}" not found`);
51293
+ }
51294
+ const extendsId = tool.extends;
51295
+ if (extendsId === void 0) {
51296
+ resolved.set(id, tool);
51297
+ return tool;
51298
+ }
51299
+ if (resolving.has(id)) {
51300
+ throw new ToolExtendsError(
51301
+ `Circular tool extends detected involving "${id}"`
51302
+ );
51303
+ }
51304
+ const baseTool = tools[extendsId];
51305
+ if (baseTool === void 0) {
51306
+ resolved.set(id, tool);
51307
+ return tool;
51308
+ }
51309
+ resolving.add(id);
51310
+ try {
51311
+ const resolvedBase = resolveToolChain(
51312
+ extendsId,
51313
+ tools,
51314
+ resolving,
51315
+ resolved
51316
+ );
51317
+ const merged = mergeToolFields(resolvedBase, tool);
51318
+ resolved.set(id, merged);
51319
+ return merged;
51320
+ } finally {
51321
+ resolving.delete(id);
51322
+ }
51323
+ }
51324
+ function resolveToolExtends(tools) {
51325
+ const resolved = /* @__PURE__ */ new Map();
51326
+ const result = {};
51327
+ for (const id of Object.keys(tools)) {
51328
+ result[id] = resolveToolChain(id, tools, /* @__PURE__ */ new Set(), resolved);
51329
+ }
51330
+ return result;
51331
+ }
51332
+
51333
+ // src/resolver/resolve.ts
51142
51334
  async function resolveExtendsChain(data, filePath, seen) {
51143
51335
  const extendsValue = data["extends"];
51144
51336
  if (typeof extendsValue !== "string") {
@@ -51168,6 +51360,10 @@ async function resolve4(projectDirOrFile) {
51168
51360
  projectResult.filePath,
51169
51361
  /* @__PURE__ */ new Set()
51170
51362
  );
51363
+ const tools = data["tools"];
51364
+ if (tools !== void 0 && tools !== null && typeof tools === "object" && !Array.isArray(tools)) {
51365
+ data["tools"] = resolveToolExtends(tools);
51366
+ }
51171
51367
  return {
51172
51368
  data,
51173
51369
  projectPath: projectResult.filePath,
@@ -52156,7 +52352,7 @@ function checkReferences(dsl) {
52156
52352
  for (const [id, art] of Object.entries(dsl.artifacts)) {
52157
52353
  if (art.owner) {
52158
52354
  const ownerAgent = dsl.agents[art.owner];
52159
- if (ownerAgent && !ownerAgent.can_read_artifacts.includes(id)) {
52355
+ if (ownerAgent && ownerAgent.can_read_artifacts.length > 0 && !ownerAgent.can_read_artifacts.includes(id)) {
52160
52356
  diagnostics.push({
52161
52357
  path: `artifacts.${id}.owner`,
52162
52358
  message: `Agent "${art.owner}" owns artifact "${id}" but cannot read it (missing from can_read_artifacts)`,
@@ -52179,6 +52375,15 @@ function checkReferences(dsl) {
52179
52375
  }
52180
52376
  }
52181
52377
  for (const [id, tool] of Object.entries(dsl.tools)) {
52378
+ if (tool.extends) {
52379
+ checkExists(
52380
+ tool.extends,
52381
+ toolIds,
52382
+ "tools",
52383
+ `tools.${id}.extends`,
52384
+ "tool-extends-not-found"
52385
+ );
52386
+ }
52182
52387
  if (tool.invokable_by.length > 0) {
52183
52388
  for (const ref of tool.invokable_by) {
52184
52389
  checkExists(ref, agentIds, "agents", `tools.${id}.invokable_by`);
@@ -52261,14 +52466,16 @@ function checkReferences(dsl) {
52261
52466
  code: "result-handoff-not-returnable"
52262
52467
  });
52263
52468
  }
52264
- for (let j2 = 0; j2 < task.input_artifacts.length; j2++) {
52265
- const inputId = task.input_artifacts[j2];
52266
- if (!targetAgent.can_read_artifacts.includes(inputId)) {
52267
- diagnostics.push({
52268
- path: `tasks.${id}.input_artifacts[${j2}]`,
52269
- message: `Input artifact "${inputId}" is not in target agent "${task.target_agent}" can_read_artifacts`,
52270
- code: "input-artifact-not-readable"
52271
- });
52469
+ if (targetAgent.can_read_artifacts.length > 0) {
52470
+ for (let j2 = 0; j2 < task.input_artifacts.length; j2++) {
52471
+ const inputId = task.input_artifacts[j2];
52472
+ if (!targetAgent.can_read_artifacts.includes(inputId)) {
52473
+ diagnostics.push({
52474
+ path: `tasks.${id}.input_artifacts[${j2}]`,
52475
+ message: `Input artifact "${inputId}" is not in target agent "${task.target_agent}" can_read_artifacts`,
52476
+ code: "input-artifact-not-readable"
52477
+ });
52478
+ }
52272
52479
  }
52273
52480
  }
52274
52481
  }
@@ -52284,7 +52491,7 @@ function checkReferences(dsl) {
52284
52491
  if (agent.prerequisites) {
52285
52492
  for (let j2 = 0; j2 < agent.prerequisites.length; j2++) {
52286
52493
  const pre = agent.prerequisites[j2];
52287
- if (!agent.can_read_artifacts.includes(pre.target)) {
52494
+ if (agent.can_read_artifacts.length > 0 && !agent.can_read_artifacts.includes(pre.target)) {
52288
52495
  diagnostics.push({
52289
52496
  path: `agents.${id}.prerequisites[${j2}].target`,
52290
52497
  message: `Prerequisite target "${pre.target}" is not in agent "${id}" can_read_artifacts`,
@@ -52675,14 +52882,16 @@ var taskAgentBindingRule = {
52675
52882
  for (const [taskId, task] of Object.entries(dsl.tasks)) {
52676
52883
  const targetAgent = dsl.agents[task.target_agent];
52677
52884
  if (!targetAgent) continue;
52678
- for (const ref of task.input_artifacts) {
52679
- if (!targetAgent.can_read_artifacts.includes(ref)) {
52680
- diagnostics.push({
52681
- ruleId: "task-agent-binding",
52682
- severity: "error",
52683
- path: `tasks.${taskId}.input_artifacts`,
52684
- message: `Task "${taskId}" input_artifact "${ref}" not in target agent "${task.target_agent}" can_read_artifacts`
52685
- });
52885
+ if (targetAgent.can_read_artifacts.length > 0) {
52886
+ for (const ref of task.input_artifacts) {
52887
+ if (!targetAgent.can_read_artifacts.includes(ref)) {
52888
+ diagnostics.push({
52889
+ ruleId: "task-agent-binding",
52890
+ severity: "error",
52891
+ path: `tasks.${taskId}.input_artifacts`,
52892
+ message: `Task "${taskId}" input_artifact "${ref}" not in target agent "${task.target_agent}" can_read_artifacts`
52893
+ });
52894
+ }
52686
52895
  }
52687
52896
  }
52688
52897
  if (!targetAgent.can_return_handoffs.includes(task.result_handoff)) {
@@ -52718,7 +52927,7 @@ var taskAgentBindingRule = {
52718
52927
  });
52719
52928
  }
52720
52929
  }
52721
- if (step.produces_artifact) {
52930
+ if (step.produces_artifact && targetAgent.can_write_artifacts.length > 0) {
52722
52931
  if (!targetAgent.can_write_artifacts.includes(step.produces_artifact)) {
52723
52932
  diagnostics.push({
52724
52933
  ruleId: "task-agent-binding",
@@ -52728,7 +52937,7 @@ var taskAgentBindingRule = {
52728
52937
  });
52729
52938
  }
52730
52939
  }
52731
- if (step.reads_artifact) {
52940
+ if (step.reads_artifact && targetAgent.can_read_artifacts.length > 0) {
52732
52941
  if (!targetAgent.can_read_artifacts.includes(step.reads_artifact)) {
52733
52942
  diagnostics.push({
52734
52943
  ruleId: "task-agent-binding",
@@ -52793,7 +53002,8 @@ var artifactOwnershipRule = {
52793
53002
  }
52794
53003
  if (step.reads_artifact) {
52795
53004
  const artifact = dsl.artifacts[step.reads_artifact];
52796
- if (artifact && (artifact.consumers.length > 0 || artifact.producers.length > 0 || artifact.editors.length > 0)) {
53005
+ const hasDeprecatedOwnership = !!artifact?.owner || (artifact?.producers.length ?? 0) > 0 || (artifact?.editors.length ?? 0) > 0 || (artifact?.consumers.length ?? 0) > 0;
53006
+ if (artifact && hasDeprecatedOwnership) {
52797
53007
  const canRead = artifact.consumers.includes(agentId) || artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
52798
53008
  if (!canRead) {
52799
53009
  diagnostics.push({
@@ -53231,6 +53441,7 @@ var artifactOwnershipConsistencyRule = {
53231
53441
  run(dsl) {
53232
53442
  const diagnostics = [];
53233
53443
  for (const [agentId, agent] of Object.entries(dsl.agents)) {
53444
+ if (agent.own_artifacts.length === 0) continue;
53234
53445
  for (const artId of agent.own_artifacts) {
53235
53446
  if (!agent.can_read_artifacts.includes(artId)) {
53236
53447
  diagnostics.push({
@@ -53258,6 +53469,68 @@ var artifactOwnershipConsistencyRule = {
53258
53469
  }
53259
53470
  };
53260
53471
 
53472
+ // src/linter/rules/deprecated-ownership-fields.ts
53473
+ var ARTIFACT_FIELDS = ["owner", "producers", "editors", "consumers"];
53474
+ var AGENT_FIELDS = [
53475
+ "own_artifacts",
53476
+ "can_read_artifacts",
53477
+ "can_write_artifacts"
53478
+ ];
53479
+ function isArtifactFieldUsed(artifact, field) {
53480
+ switch (field) {
53481
+ case "owner":
53482
+ return !!artifact.owner;
53483
+ case "producers":
53484
+ return artifact.producers.length > 0;
53485
+ case "editors":
53486
+ return artifact.editors.length > 0;
53487
+ case "consumers":
53488
+ return artifact.consumers.length > 0;
53489
+ }
53490
+ }
53491
+ function isAgentFieldUsed(agent, field) {
53492
+ switch (field) {
53493
+ case "own_artifacts":
53494
+ return agent.own_artifacts.length > 0;
53495
+ case "can_read_artifacts":
53496
+ return agent.can_read_artifacts.length > 0;
53497
+ case "can_write_artifacts":
53498
+ return agent.can_write_artifacts.length > 0;
53499
+ }
53500
+ }
53501
+ var deprecatedOwnershipFieldsRule = {
53502
+ id: "deprecated-ownership-fields",
53503
+ description: "Warn when deprecated ownership/permission fields are used instead of artifact_bindings + artifact_slots",
53504
+ run(dsl) {
53505
+ const diagnostics = [];
53506
+ for (const [artId, artifact] of Object.entries(dsl.artifacts)) {
53507
+ for (const field of ARTIFACT_FIELDS) {
53508
+ if (isArtifactFieldUsed(artifact, field)) {
53509
+ diagnostics.push({
53510
+ ruleId: "deprecated-ownership-fields",
53511
+ severity: "warning",
53512
+ path: `artifacts.${artId}.${field}`,
53513
+ message: `Artifact "${artId}" uses deprecated field "${field}". Ownership is derived from artifact_bindings + artifact_slots in the binding model.`
53514
+ });
53515
+ }
53516
+ }
53517
+ }
53518
+ for (const [agentId, agent] of Object.entries(dsl.agents)) {
53519
+ for (const field of AGENT_FIELDS) {
53520
+ if (isAgentFieldUsed(agent, field)) {
53521
+ diagnostics.push({
53522
+ ruleId: "deprecated-ownership-fields",
53523
+ severity: "warning",
53524
+ path: `agents.${agentId}.${field}`,
53525
+ message: `Agent "${agentId}" uses deprecated field "${field}". Artifact permissions are derived from artifact_bindings + artifact_slots in the binding model.`
53526
+ });
53527
+ }
53528
+ }
53529
+ }
53530
+ return diagnostics;
53531
+ }
53532
+ };
53533
+
53261
53534
  // src/linter/rules/extension-consumption.ts
53262
53535
  function isRecord4(v2) {
53263
53536
  return typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
@@ -53428,6 +53701,194 @@ var extensionUndeclaredUsageRule = {
53428
53701
  }
53429
53702
  };
53430
53703
 
53704
+ // src/navigation-index/cli-contract-loader.ts
53705
+ import { existsSync, readFileSync } from "fs";
53706
+ import { isAbsolute, resolve as resolve6 } from "path";
53707
+ import { parse as parseYaml4 } from "yaml";
53708
+ function extractStringArray(value) {
53709
+ if (!Array.isArray(value)) return [];
53710
+ return value.filter((item) => typeof item === "string");
53711
+ }
53712
+ function extractArtifactSlots(doc) {
53713
+ const slots = doc.artifact_slots;
53714
+ if (!slots || typeof slots !== "object") return null;
53715
+ const result = {};
53716
+ for (const [name, slotDef] of Object.entries(slots)) {
53717
+ if (!slotDef || typeof slotDef !== "object") continue;
53718
+ const direction = slotDef.direction;
53719
+ if (direction === "read" || direction === "write" || direction === "readwrite") {
53720
+ result[name] = { direction };
53721
+ }
53722
+ }
53723
+ return Object.keys(result).length > 0 ? result : null;
53724
+ }
53725
+ function extractCommandEffects(doc) {
53726
+ const result = {};
53727
+ const commandSets = doc.command_sets;
53728
+ if (!commandSets || typeof commandSets !== "object") return result;
53729
+ for (const setDef of Object.values(commandSets)) {
53730
+ if (!setDef || typeof setDef !== "object") continue;
53731
+ const commands = setDef.commands;
53732
+ if (!commands || typeof commands !== "object") continue;
53733
+ for (const [cmdName, cmdDef] of Object.entries(commands)) {
53734
+ if (!cmdDef || typeof cmdDef !== "object") continue;
53735
+ const effects = cmdDef.effects;
53736
+ if (!effects || typeof effects !== "object") continue;
53737
+ result[cmdName] = {
53738
+ reads: extractStringArray(effects.reads),
53739
+ writes: extractStringArray(effects.writes)
53740
+ };
53741
+ }
53742
+ }
53743
+ return result;
53744
+ }
53745
+ function resolveCliContractPath(cliContractPath) {
53746
+ return isAbsolute(cliContractPath) ? cliContractPath : resolve6(process.cwd(), cliContractPath);
53747
+ }
53748
+ function loadCliContractSlots(cliContractPath) {
53749
+ const filePath = resolveCliContractPath(cliContractPath);
53750
+ if (!existsSync(filePath)) return null;
53751
+ let doc;
53752
+ try {
53753
+ doc = parseYaml4(readFileSync(filePath, "utf8"));
53754
+ } catch {
53755
+ return null;
53756
+ }
53757
+ if (!doc || typeof doc !== "object") return null;
53758
+ const artifactSlots = extractArtifactSlots(doc);
53759
+ if (!artifactSlots) return null;
53760
+ return {
53761
+ artifactSlots,
53762
+ commandEffects: extractCommandEffects(doc)
53763
+ };
53764
+ }
53765
+ function resolveSlotDirection(slot, command, slotInfo) {
53766
+ const cmdEffects = slotInfo.commandEffects[command];
53767
+ if (cmdEffects) {
53768
+ if (cmdEffects.writes.includes(slot)) return "write";
53769
+ if (cmdEffects.reads.includes(slot)) return "read";
53770
+ }
53771
+ const slotDecl = slotInfo.artifactSlots[slot];
53772
+ if (slotDecl) {
53773
+ if (slotDecl.direction === "write" || slotDecl.direction === "readwrite") {
53774
+ return "write";
53775
+ }
53776
+ return "read";
53777
+ }
53778
+ return "read";
53779
+ }
53780
+
53781
+ // src/linter/rules/binding-completeness.ts
53782
+ var bindingCompletenessRule = {
53783
+ id: "binding-completeness",
53784
+ description: "Check that artifact_bindings cover all slots referenced in the cli-contract command effects",
53785
+ run(dsl) {
53786
+ const diagnostics = [];
53787
+ for (const [toolId, tool] of Object.entries(dsl.tools)) {
53788
+ if (!tool.cli_contract || !tool.artifact_bindings) continue;
53789
+ const slotInfo = loadCliContractSlots(tool.cli_contract);
53790
+ if (!slotInfo?.artifactSlots) continue;
53791
+ const command = tool.command ?? "";
53792
+ const effects = slotInfo.commandEffects[command];
53793
+ if (!effects) continue;
53794
+ const referencedSlots = [...effects.reads, ...effects.writes];
53795
+ const boundSlots = new Set(Object.keys(tool.artifact_bindings));
53796
+ for (const slot of referencedSlots) {
53797
+ if (boundSlots.has(slot)) continue;
53798
+ diagnostics.push({
53799
+ ruleId: "binding-completeness",
53800
+ severity: "warning",
53801
+ path: `tools.${toolId}.artifact_bindings`,
53802
+ message: `Command "${command}" references slot "${slot}" but tool has no artifact_bindings entry for it`
53803
+ });
53804
+ }
53805
+ }
53806
+ return diagnostics;
53807
+ }
53808
+ };
53809
+
53810
+ // src/linter/rules/binding-direction-match.ts
53811
+ function agentCanWriteArtifact(agentId, artifactId, dsl) {
53812
+ const agent = dsl.agents[agentId];
53813
+ if (!agent) return false;
53814
+ return agent.can_write_artifacts.includes(artifactId) || agent.own_artifacts.includes(artifactId);
53815
+ }
53816
+ var bindingDirectionMatchRule = {
53817
+ id: "binding-direction-match",
53818
+ description: "Check that agents invoking a tool can write artifacts bound via write slots",
53819
+ run(dsl) {
53820
+ const diagnostics = [];
53821
+ for (const [toolId, tool] of Object.entries(dsl.tools)) {
53822
+ if (!tool.cli_contract || !tool.artifact_bindings) continue;
53823
+ const slotInfo = loadCliContractSlots(tool.cli_contract);
53824
+ if (!slotInfo) continue;
53825
+ const command = tool.command ?? "";
53826
+ for (const [slot, artifactId] of Object.entries(tool.artifact_bindings)) {
53827
+ const direction = resolveSlotDirection(slot, command, slotInfo);
53828
+ if (direction !== "write") continue;
53829
+ for (const agentId of tool.invokable_by) {
53830
+ if (agentCanWriteArtifact(agentId, artifactId, dsl)) continue;
53831
+ diagnostics.push({
53832
+ ruleId: "binding-direction-match",
53833
+ severity: "warning",
53834
+ path: `tools.${toolId}.artifact_bindings.${slot}`,
53835
+ message: `Agent "${agentId}" invokes tool "${toolId}" which writes to artifact "${artifactId}" via slot "${slot}", but agent lacks can_write_artifacts or own_artifacts for it`
53836
+ });
53837
+ }
53838
+ }
53839
+ }
53840
+ return diagnostics;
53841
+ }
53842
+ };
53843
+
53844
+ // src/linter/rules/slot-declaration-exists.ts
53845
+ var slotDeclarationExistsRule = {
53846
+ id: "slot-declaration-exists",
53847
+ description: "Check that artifact_bindings keys reference slot names declared in the cli-contract",
53848
+ run(dsl) {
53849
+ const diagnostics = [];
53850
+ for (const [toolId, tool] of Object.entries(dsl.tools)) {
53851
+ if (!tool.cli_contract || !tool.artifact_bindings) continue;
53852
+ const slotInfo = loadCliContractSlots(tool.cli_contract);
53853
+ if (!slotInfo?.artifactSlots) continue;
53854
+ for (const slot of Object.keys(tool.artifact_bindings)) {
53855
+ if (slot in slotInfo.artifactSlots) continue;
53856
+ diagnostics.push({
53857
+ ruleId: "slot-declaration-exists",
53858
+ severity: "warning",
53859
+ path: `tools.${toolId}.artifact_bindings.${slot}`,
53860
+ message: `artifact_bindings key "${slot}" is not declared in cli-contract artifactSlots`
53861
+ });
53862
+ }
53863
+ }
53864
+ return diagnostics;
53865
+ }
53866
+ };
53867
+
53868
+ // src/linter/rules/config-path-consistency.ts
53869
+ var configPathConsistencyRule = {
53870
+ id: "config-path-consistency",
53871
+ description: "Check that control-authority artifacts bound by tools have path_patterns defined",
53872
+ run(dsl) {
53873
+ const diagnostics = [];
53874
+ for (const [toolId, tool] of Object.entries(dsl.tools)) {
53875
+ if (!tool.artifact_bindings) continue;
53876
+ for (const [slot, artifactId] of Object.entries(tool.artifact_bindings)) {
53877
+ const artifact = dsl.artifacts[artifactId];
53878
+ if (!artifact || artifact.authority !== "control") continue;
53879
+ if (artifact.path_patterns && artifact.path_patterns.length > 0) continue;
53880
+ diagnostics.push({
53881
+ ruleId: "config-path-consistency",
53882
+ severity: "info",
53883
+ path: `tools.${toolId}.artifact_bindings.${slot}`,
53884
+ message: `Config artifact "${artifactId}" has no path_patterns; consider adding them for path-based lookup`
53885
+ });
53886
+ }
53887
+ }
53888
+ return diagnostics;
53889
+ }
53890
+ };
53891
+
53431
53892
  // src/linter/linter.ts
53432
53893
  var builtinRules = [
53433
53894
  validationCoverageRule,
@@ -53446,9 +53907,14 @@ var builtinRules = [
53446
53907
  guardrailOrphanedRule,
53447
53908
  validationExecutorNoContextRule,
53448
53909
  artifactOwnershipConsistencyRule,
53910
+ deprecatedOwnershipFieldsRule,
53449
53911
  extensionDeclaredButUnusedRule,
53450
53912
  extensionScopeMismatchRule,
53451
- extensionUndeclaredUsageRule
53913
+ extensionUndeclaredUsageRule,
53914
+ bindingCompletenessRule,
53915
+ bindingDirectionMatchRule,
53916
+ slotDeclarationExistsRule,
53917
+ configPathConsistencyRule
53452
53918
  ];
53453
53919
  function lint(dsl, rules = builtinRules) {
53454
53920
  const diagnostics = [];
@@ -53502,9 +53968,18 @@ var ref_exists_default = (0, import_spectral_core.createRulesetFunction)(
53502
53968
 
53503
53969
  // src/linter/spectral/functions/editors-not-empty.ts
53504
53970
  var import_spectral_core2 = __toESM(require_dist9(), 1);
53971
+ function allDeprecatedOwnershipFieldsEmpty(art) {
53972
+ return !art.owner && (art.producers?.length ?? 0) === 0 && (art.editors?.length ?? 0) === 0 && (art.consumers?.length ?? 0) === 0;
53973
+ }
53505
53974
  var editors_not_empty_default = (0, import_spectral_core2.createRulesetFunction)(
53506
53975
  { input: { type: "array" }, options: null },
53507
- (targetVal, _options, _context) => {
53976
+ (targetVal, _options, context) => {
53977
+ const root = context.document.data;
53978
+ const artId = context.path.length >= 2 ? String(context.path[1]) : void 0;
53979
+ const artifact = artId && root.artifacts ? root.artifacts[artId] : void 0;
53980
+ if (artifact && allDeprecatedOwnershipFieldsEmpty(artifact)) {
53981
+ return [];
53982
+ }
53508
53983
  if (targetVal.length === 0) {
53509
53984
  return [{ message: "editors must not be empty" }];
53510
53985
  }
@@ -53536,6 +54011,7 @@ var prerequisite_readable_default = (0, import_spectral_core4.createRulesetFunct
53536
54011
  (targetVal, _options, context) => {
53537
54012
  const readable = new Set(targetVal.can_read_artifacts ?? []);
53538
54013
  const prereqs = targetVal.prerequisites ?? [];
54014
+ if (readable.size === 0) return [];
53539
54015
  const results = [];
53540
54016
  for (let i3 = 0; i3 < prereqs.length; i3++) {
53541
54017
  const p2 = prereqs[i3];
@@ -53937,7 +54413,7 @@ var ruleset = {
53937
54413
  },
53938
54414
  "artifact-owner-exists": {
53939
54415
  description: "(deprecated) Every artifact must have an owner",
53940
- severity: "warn",
54416
+ severity: "off",
53941
54417
  given: "$.artifacts.*",
53942
54418
  then: {
53943
54419
  field: "owner",
@@ -54796,7 +55272,7 @@ function emitExecutionStep(es, agentAlias2, participants, lines, indent) {
54796
55272
  }
54797
55273
  function emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent) {
54798
55274
  const val = dsl.validations[step.validation];
54799
- if (!val) return;
55275
+ if (!val || !val.executor) return;
54800
55276
  const executorAlias = participantAlias(participants, val.executor);
54801
55277
  const artifactAlias = participantAlias(participants, val.target_artifact);
54802
55278
  const fromAlias = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
@@ -55099,6 +55575,299 @@ function generateOverviewFlowchart(dsl) {
55099
55575
  return sections.join("\n\n");
55100
55576
  }
55101
55577
 
55578
+ // src/navigation-index/builder.ts
55579
+ var VALIDATOR_KINDS = /* @__PURE__ */ new Set(["linter", "checker", "validator", "test"]);
55580
+ var VALIDATION_TERMS = ["lint", "check", "validate", "test", "verify", "audit"];
55581
+ function sortUnique(values) {
55582
+ return [...new Set(values)].sort();
55583
+ }
55584
+ function matchesValidationTerm(value) {
55585
+ const lower = value.toLowerCase();
55586
+ return VALIDATION_TERMS.some((term) => lower.includes(term));
55587
+ }
55588
+ function isValidatorTool(tool) {
55589
+ if (tool.kind && VALIDATOR_KINDS.has(tool.kind)) {
55590
+ return true;
55591
+ }
55592
+ if (tool.command && matchesValidationTerm(tool.command)) {
55593
+ return true;
55594
+ }
55595
+ for (const cmd of tool.commands ?? []) {
55596
+ if (matchesValidationTerm(cmd.category) || matchesValidationTerm(cmd.command)) {
55597
+ return true;
55598
+ }
55599
+ }
55600
+ return false;
55601
+ }
55602
+ function extractToolArtifactLinks(toolId, tool) {
55603
+ const links = [];
55604
+ if (tool.cli_contract) {
55605
+ const command = tool.command ?? "";
55606
+ const slotInfo = loadCliContractSlots(tool.cli_contract);
55607
+ for (const [slot, artifactId] of Object.entries(tool.artifact_bindings ?? {})) {
55608
+ const direction = slotInfo ? resolveSlotDirection(slot, command, slotInfo) : "read";
55609
+ links.push({
55610
+ toolId,
55611
+ artifactId,
55612
+ direction,
55613
+ slot,
55614
+ command
55615
+ });
55616
+ }
55617
+ return links;
55618
+ }
55619
+ for (const cmd of tool.commands ?? []) {
55620
+ for (const artifactId of cmd.reads ?? []) {
55621
+ links.push({
55622
+ toolId,
55623
+ artifactId,
55624
+ direction: "read",
55625
+ slot: "",
55626
+ command: cmd.command
55627
+ });
55628
+ }
55629
+ for (const artifactId of cmd.writes ?? []) {
55630
+ links.push({
55631
+ toolId,
55632
+ artifactId,
55633
+ direction: "write",
55634
+ slot: "",
55635
+ command: cmd.command
55636
+ });
55637
+ }
55638
+ }
55639
+ return links;
55640
+ }
55641
+ function buildOperation(toolId, tool, link) {
55642
+ return {
55643
+ tool: toolId,
55644
+ cli_contract: tool.cli_contract ?? "",
55645
+ command: link.command || tool.command || "",
55646
+ slot: link.slot,
55647
+ invokable_by: [...tool.invokable_by ?? []]
55648
+ };
55649
+ }
55650
+ function operationKey(op) {
55651
+ return `${op.tool}:${op.command}:${op.slot}`;
55652
+ }
55653
+ function dedupeOperations(operations) {
55654
+ const seen = /* @__PURE__ */ new Set();
55655
+ const result = [];
55656
+ for (const op of operations) {
55657
+ const key = operationKey(op);
55658
+ if (seen.has(key)) continue;
55659
+ seen.add(key);
55660
+ result.push(op);
55661
+ }
55662
+ return result.sort((a3, b3) => a3.tool.localeCompare(b3.tool) || a3.slot.localeCompare(b3.slot));
55663
+ }
55664
+ function buildAgentMapping(dsl, artifactId) {
55665
+ const owners = [];
55666
+ const editors = [];
55667
+ const readers = [];
55668
+ for (const [agentId, agent] of Object.entries(dsl.agents)) {
55669
+ if (agent.own_artifacts?.includes(artifactId)) owners.push(agentId);
55670
+ if (agent.can_write_artifacts?.includes(artifactId)) editors.push(agentId);
55671
+ if (agent.can_read_artifacts?.includes(artifactId)) readers.push(agentId);
55672
+ }
55673
+ return {
55674
+ owners: sortUnique(owners),
55675
+ editors: sortUnique(editors),
55676
+ readers: sortUnique(readers)
55677
+ };
55678
+ }
55679
+ function buildRelations(artifactId, authority, linksByArtifact, allLinks) {
55680
+ const sourceArtifacts = /* @__PURE__ */ new Set();
55681
+ const derivedArtifacts = /* @__PURE__ */ new Set();
55682
+ const writesToThis = allLinks.filter(
55683
+ (link) => link.artifactId === artifactId && link.direction === "write"
55684
+ );
55685
+ if (authority === "generated" || authority === "derived") {
55686
+ for (const writeLink of writesToThis) {
55687
+ for (const readLink of allLinks) {
55688
+ if (readLink.toolId === writeLink.toolId && readLink.direction === "read") {
55689
+ sourceArtifacts.add(readLink.artifactId);
55690
+ }
55691
+ }
55692
+ }
55693
+ }
55694
+ const readsThis = allLinks.filter(
55695
+ (link) => link.artifactId === artifactId && link.direction === "read"
55696
+ );
55697
+ for (const readLink of readsThis) {
55698
+ for (const writeLink of allLinks) {
55699
+ if (writeLink.toolId === readLink.toolId && writeLink.direction === "write") {
55700
+ derivedArtifacts.add(writeLink.artifactId);
55701
+ }
55702
+ }
55703
+ }
55704
+ const knownArtifacts = new Set(linksByArtifact.keys());
55705
+ return {
55706
+ source_artifacts: sortUnique(
55707
+ [...sourceArtifacts].filter((id) => id !== artifactId && knownArtifacts.has(id))
55708
+ ),
55709
+ derived_artifacts: sortUnique(
55710
+ [...derivedArtifacts].filter((id) => id !== artifactId && knownArtifacts.has(id))
55711
+ )
55712
+ };
55713
+ }
55714
+ function buildValidateRoutes(validators) {
55715
+ return validators.map((validator) => ({
55716
+ purpose: "validate",
55717
+ steps: [
55718
+ {
55719
+ type: "run_operation",
55720
+ operation: validator.tool,
55721
+ candidate_agents: [...validator.invokable_by]
55722
+ }
55723
+ ]
55724
+ }));
55725
+ }
55726
+ function buildRegenerateRoutes(sourceArtifacts, producers, agentsByArtifact) {
55727
+ if (producers.length === 0) return [];
55728
+ const editSteps = sourceArtifacts.map((artifactId) => ({
55729
+ type: "edit_artifact",
55730
+ artifact: artifactId,
55731
+ candidate_agents: agentsByArtifact.get(artifactId)?.editors ?? []
55732
+ }));
55733
+ const runSteps = producers.map((producer) => ({
55734
+ type: "run_operation",
55735
+ operation: producer.tool,
55736
+ candidate_agents: [...producer.invokable_by]
55737
+ }));
55738
+ return [
55739
+ {
55740
+ purpose: "regenerate",
55741
+ steps: [...editSteps, ...runSteps]
55742
+ }
55743
+ ];
55744
+ }
55745
+ function buildUpdateRoutes(artifactId, validators, editors) {
55746
+ const steps = [
55747
+ {
55748
+ type: "edit_artifact",
55749
+ artifact: artifactId,
55750
+ candidate_agents: [...editors]
55751
+ }
55752
+ ];
55753
+ for (const validator of validators) {
55754
+ steps.push({
55755
+ type: "run_operation",
55756
+ operation: validator.tool,
55757
+ candidate_agents: [...validator.invokable_by]
55758
+ });
55759
+ }
55760
+ return [
55761
+ {
55762
+ purpose: "update",
55763
+ steps
55764
+ }
55765
+ ];
55766
+ }
55767
+ function defaultProperties(artifact) {
55768
+ return {
55769
+ type: artifact.type,
55770
+ authority: artifact.authority ?? "canonical",
55771
+ manual_edit: artifact.manual_edit ?? "allowed",
55772
+ change_control: artifact.change_control ?? "none"
55773
+ };
55774
+ }
55775
+ function buildNavigationIndex(dsl) {
55776
+ const resolvedTools = resolveToolExtends(dsl.tools);
55777
+ const allLinks = [];
55778
+ for (const [toolId, tool] of Object.entries(resolvedTools)) {
55779
+ allLinks.push(...extractToolArtifactLinks(toolId, tool));
55780
+ }
55781
+ const linksByArtifact = /* @__PURE__ */ new Map();
55782
+ for (const link of allLinks) {
55783
+ const existing = linksByArtifact.get(link.artifactId) ?? [];
55784
+ existing.push(link);
55785
+ linksByArtifact.set(link.artifactId, existing);
55786
+ }
55787
+ const toolWrites = /* @__PURE__ */ new Map();
55788
+ for (const link of allLinks) {
55789
+ if (link.direction !== "write") continue;
55790
+ const writes = toolWrites.get(link.toolId) ?? /* @__PURE__ */ new Set();
55791
+ writes.add(link.artifactId);
55792
+ toolWrites.set(link.toolId, writes);
55793
+ }
55794
+ const artifacts = {};
55795
+ const agentsByArtifact = /* @__PURE__ */ new Map();
55796
+ for (const [artifactId, artifactDef] of Object.entries(dsl.artifacts)) {
55797
+ const properties = defaultProperties(artifactDef);
55798
+ const agents = buildAgentMapping(dsl, artifactId);
55799
+ agentsByArtifact.set(artifactId, agents);
55800
+ const artifactLinks = linksByArtifact.get(artifactId) ?? [];
55801
+ const producers = [];
55802
+ const validators = [];
55803
+ const consumers = [];
55804
+ const processedPairs = /* @__PURE__ */ new Set();
55805
+ for (const link of artifactLinks) {
55806
+ const tool = resolvedTools[link.toolId];
55807
+ if (!tool) continue;
55808
+ const pairKey = `${link.toolId}:${link.direction}:${link.slot}:${link.command}`;
55809
+ if (processedPairs.has(pairKey)) continue;
55810
+ processedPairs.add(pairKey);
55811
+ const operation = buildOperation(link.toolId, tool, link);
55812
+ const toolWritesArtifacts = toolWrites.get(link.toolId) ?? /* @__PURE__ */ new Set();
55813
+ if (link.direction === "write" || toolWritesArtifacts.has(artifactId)) {
55814
+ producers.push(operation);
55815
+ } else if (isValidatorTool(tool)) {
55816
+ validators.push(operation);
55817
+ } else if (link.direction === "read") {
55818
+ consumers.push(operation);
55819
+ }
55820
+ }
55821
+ const relations = buildRelations(
55822
+ artifactId,
55823
+ properties.authority,
55824
+ linksByArtifact,
55825
+ allLinks
55826
+ );
55827
+ const routes = {};
55828
+ const dedupedValidators = dedupeOperations(validators);
55829
+ const dedupedProducers = dedupeOperations(producers);
55830
+ if (dedupedValidators.length > 0) {
55831
+ routes.validate = buildValidateRoutes(dedupedValidators);
55832
+ }
55833
+ if (properties.authority === "generated" && dedupedProducers.length > 0 && relations.source_artifacts.length > 0) {
55834
+ routes.regenerate = buildRegenerateRoutes(
55835
+ relations.source_artifacts,
55836
+ dedupedProducers,
55837
+ agentsByArtifact
55838
+ );
55839
+ }
55840
+ if (properties.authority === "canonical") {
55841
+ routes.update = buildUpdateRoutes(artifactId, dedupedValidators, agents.editors);
55842
+ }
55843
+ artifacts[artifactId] = {
55844
+ id: artifactId,
55845
+ files: {
55846
+ path_patterns: artifactDef.path_patterns ?? [],
55847
+ exclude_patterns: artifactDef.exclude_patterns ?? []
55848
+ },
55849
+ properties,
55850
+ relations,
55851
+ operations: {
55852
+ producers: dedupeOperations(producers),
55853
+ validators: dedupedValidators,
55854
+ consumers: dedupeOperations(consumers)
55855
+ },
55856
+ agents,
55857
+ routes
55858
+ };
55859
+ }
55860
+ return {
55861
+ version: "1.0.0",
55862
+ generated_at: (/* @__PURE__ */ new Date()).toISOString(),
55863
+ system: {
55864
+ id: dsl.system.id,
55865
+ name: dsl.system.name
55866
+ },
55867
+ artifacts
55868
+ };
55869
+ }
55870
+
55102
55871
  // src/renderer/renderer.ts
55103
55872
  Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
55104
55873
  Handlebars.registerHelper("notEmpty", (obj) => {
@@ -55408,6 +56177,8 @@ function buildEntityContext(dsl, context, entityId) {
55408
56177
  return buildGuardrailPolicyContext(dsl, entityId);
55409
56178
  case "system":
55410
56179
  return buildSystemContext(dsl);
56180
+ case "navigation_index":
56181
+ return buildNavigationIndex(dsl);
55411
56182
  }
55412
56183
  }
55413
56184
  async function loadTemplate(templatePath) {
@@ -55427,8 +56198,8 @@ async function renderFromConfig(dsl, renderTargets, options) {
55427
56198
  for (const target of renderTargets) {
55428
56199
  const templateContent = await loadTemplate(target.template);
55429
56200
  const compiled = Handlebars.compile(templateContent, { noEscape: false });
55430
- if (target.context === "system") {
55431
- const ctx = buildSystemContext(dsl, options);
56201
+ if (target.context === "system" || target.context === "navigation_index") {
56202
+ const ctx = target.context === "system" ? buildSystemContext(dsl, options) : buildNavigationIndex(dsl);
55432
56203
  const output = compiled(ctx);
55433
56204
  if (target.skip_empty && isEffectivelyEmpty(output)) {
55434
56205
  await removeIfExists(target.output);
@@ -55484,8 +56255,8 @@ async function checkDriftFromConfig(dsl, renderTargets, options) {
55484
56255
  for (const target of renderTargets) {
55485
56256
  const templateContent = await loadTemplate(target.template);
55486
56257
  const compiled = Handlebars.compile(templateContent, { noEscape: false });
55487
- if (target.context === "system") {
55488
- const ctx = buildSystemContext(dsl, options);
56258
+ if (target.context === "system" || target.context === "navigation_index") {
56259
+ const ctx = target.context === "system" ? buildSystemContext(dsl, options) : buildNavigationIndex(dsl);
55489
56260
  const expected = compiled(ctx);
55490
56261
  await checkExpectedVsExisting(expected, target.output, target.skip_empty, diffs);
55491
56262
  } else {
@@ -55764,7 +56535,7 @@ function score(dsl) {
55764
56535
 
55765
56536
  // src/guardrail-generator/generator.ts
55766
56537
  import { readFile as readFile5, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink as unlink2, copyFile } from "fs/promises";
55767
- import { resolve as resolve6, dirname as dirname6 } from "path";
56538
+ import { resolve as resolve7, dirname as dirname6 } from "path";
55768
56539
  import Handlebars2 from "handlebars";
55769
56540
  import YAML from "yaml";
55770
56541
 
@@ -55986,9 +56757,9 @@ async function generateGuardrails(options) {
55986
56757
  if (pathResult.diagnostics.some((d2) => d2.severity === "error")) {
55987
56758
  continue;
55988
56759
  }
55989
- const targetPath = resolve6(config.configDir, pathResult.resolved);
56760
+ const targetPath = resolve7(config.configDir, pathResult.resolved);
55990
56761
  if (outputDef.source) {
55991
- const sourcePath = resolve6(config.configDir, outputDef.source);
56762
+ const sourcePath = resolve7(config.configDir, outputDef.source);
55992
56763
  if (!dryRun) {
55993
56764
  try {
55994
56765
  await mkdir2(dirname6(targetPath), { recursive: true });
@@ -56024,7 +56795,7 @@ async function generateGuardrails(options) {
56024
56795
  });
56025
56796
  continue;
56026
56797
  }
56027
- const templatePath = resolve6(config.configDir, outputDef.template);
56798
+ const templatePath = resolve7(config.configDir, outputDef.template);
56028
56799
  try {
56029
56800
  templateContent = await readFile5(templatePath, "utf8");
56030
56801
  } catch {
@@ -56063,7 +56834,7 @@ async function generateGuardrails(options) {
56063
56834
  };
56064
56835
  const compiled = Handlebars2.compile(templateContent, { noEscape: true });
56065
56836
  const rendered = compiled(groupCtx);
56066
- const groupTarget = resolve6(targetPath, groupKey);
56837
+ const groupTarget = resolve7(targetPath, groupKey);
56067
56838
  if (shouldSkipEmpty && rendered.trim().length === 0) {
56068
56839
  if (!dryRun) {
56069
56840
  try {
@@ -56111,7 +56882,7 @@ async function generateGuardrails(options) {
56111
56882
  if (renderTarget.inline_template) {
56112
56883
  templateContent = renderTarget.inline_template;
56113
56884
  } else if (renderTarget.template) {
56114
- const templatePath = resolve6(config.configDir, renderTarget.template);
56885
+ const templatePath = resolve7(config.configDir, renderTarget.template);
56115
56886
  try {
56116
56887
  templateContent = await readFile5(templatePath, "utf8");
56117
56888
  } catch {
@@ -56133,12 +56904,12 @@ async function generateGuardrails(options) {
56133
56904
  const compiled = Handlebars2.compile(templateContent, { noEscape: true });
56134
56905
  const shouldSkipEmpty = renderTarget.skip_empty === true;
56135
56906
  const context = renderTarget.context;
56136
- if (context === "system") {
56137
- const sysCtx = buildSystemContext(dsl);
56138
- const mergedCtx = { ...sysCtx, vars, paths, binding, resolved_checks: checkResult.resolved };
56907
+ if (context === "system" || context === "navigation_index") {
56908
+ const baseCtx = context === "system" ? buildSystemContext(dsl) : buildNavigationIndex(dsl);
56909
+ const mergedCtx = { ...baseCtx, vars, paths, binding, resolved_checks: checkResult.resolved };
56139
56910
  const rendered = compiled(mergedCtx);
56140
56911
  const resolvedOutput = resolveBindingRenderOutputPath(renderTarget.output, paths);
56141
- const outputPath = resolve6(config.configDir, resolvedOutput);
56912
+ const outputPath = resolve7(config.configDir, resolvedOutput);
56142
56913
  if (shouldSkipEmpty && rendered.trim().length === 0) {
56143
56914
  if (!dryRun) {
56144
56915
  try {
@@ -56168,7 +56939,7 @@ async function generateGuardrails(options) {
56168
56939
  const expandedOutput = expandOutputPath(renderTarget.output, context, entityId, entity);
56169
56940
  if (hasUnresolvedPathVars(expandedOutput)) continue;
56170
56941
  const resolvedOutput = resolveBindingRenderOutputPath(expandedOutput, paths);
56171
- const outputPath = resolve6(config.configDir, resolvedOutput);
56942
+ const outputPath = resolve7(config.configDir, resolvedOutput);
56172
56943
  if (shouldSkipEmpty && rendered.trim().length === 0) {
56173
56944
  if (!dryRun) {
56174
56945
  try {
@@ -56384,10 +57155,10 @@ function collectAllXUsages(dsl) {
56384
57155
  function extractTemplateXReferences(config) {
56385
57156
  const refs = [];
56386
57157
  try {
56387
- const { readFileSync: readFileSync3 } = __require("fs");
57158
+ const { readFileSync: readFileSync4 } = __require("fs");
56388
57159
  for (const target of config.renders) {
56389
57160
  try {
56390
- const content = readFileSync3(target.template, "utf8");
57161
+ const content = readFileSync4(target.template, "utf8");
56391
57162
  const matches = content.matchAll(/\{\{[^}]*?(x-[\w-]+)[^}]*?\}\}/g);
56392
57163
  for (const m2 of matches) refs.push(m2[1]);
56393
57164
  } catch {
@@ -56912,7 +57683,7 @@ var DslTaskResultSchema = z20.object({
56912
57683
  });
56913
57684
  var AuditResultSchema = z20.object({
56914
57685
  summary: z20.string(),
56915
- riskLevel: z20.enum(["low", "medium", "high", "critical"]),
57686
+ risk_level: z20.enum(["low", "medium", "high", "critical"]),
56916
57687
  findings: z20.array(z20.object({
56917
57688
  id: z20.string().optional(),
56918
57689
  severity: z20.enum(["info", "warning", "error", "critical"]),
@@ -56930,7 +57701,7 @@ var AuditResultSchema = z20.object({
56930
57701
  })).optional(),
56931
57702
  details: z20.record(z20.string(), z20.unknown()).optional()
56932
57703
  })),
56933
- recommendedActions: z20.array(z20.object({
57704
+ recommended_actions: z20.array(z20.object({
56934
57705
  kind: z20.enum(["run_command", "edit_file", "review", "confirm", "block", "ignore"]),
56935
57706
  title: z20.string(),
56936
57707
  command: z20.string().optional(),
@@ -56941,7 +57712,7 @@ var AuditResultSchema = z20.object({
56941
57712
  tool: z20.string().optional(),
56942
57713
  command: z20.string().optional(),
56943
57714
  version: z20.string().optional(),
56944
- generatedAt: z20.string().optional(),
57715
+ generated_at: z20.string().optional(),
56945
57716
  adapter: z20.string().optional(),
56946
57717
  model: z20.string().optional()
56947
57718
  }).optional()
@@ -57252,13 +58023,13 @@ function getTeamEntries(config, teamFilter) {
57252
58023
 
57253
58024
  // src/cli/commands/generate-interface.ts
57254
58025
  import { writeFileSync } from "fs";
57255
- import { resolve as resolve7 } from "path";
58026
+ import { resolve as resolve8 } from "path";
57256
58027
  function runGenerateInterfaceCli(opts) {
57257
58028
  if (!opts.dsl.team_interface) {
57258
58029
  process.stderr.write("Error: DSL has no team_interface section.\n");
57259
58030
  process.exit(1);
57260
58031
  }
57261
- const outputPath = resolve7(process.cwd(), opts.output ?? "team-interface.yaml");
58032
+ const outputPath = resolve8(process.cwd(), opts.output ?? "team-interface.yaml");
57262
58033
  const result = generateInterface({
57263
58034
  dsl: opts.dsl,
57264
58035
  output: outputPath,
@@ -57654,12 +58425,12 @@ var handleCheck = async (opts) => {
57654
58425
  }
57655
58426
  if (schemaResult.data.team_interface) {
57656
58427
  const interfacePath = join3(config.configDir, "team-interface.yaml");
57657
- if (existsSync(interfacePath)) {
58428
+ if (existsSync2(interfacePath)) {
57658
58429
  const result = generateInterface({ dsl: schemaResult.data, dryRun: true, format: "yaml" });
57659
- const existing = readFileSync(interfacePath, "utf8");
58430
+ const existing = readFileSync2(interfacePath, "utf8");
57660
58431
  const normalize = (raw) => {
57661
58432
  try {
57662
- const parsed = parseYaml4(raw);
58433
+ const parsed = parseYaml5(raw);
57663
58434
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
57664
58435
  const { generated_at: _t, ...rest } = parsed;
57665
58436
  return `${stringify3(rest, { sortMapEntries: true })}
@@ -58071,6 +58842,105 @@ var handleGenerate = async (type, opts) => {
58071
58842
  process.exit(1);
58072
58843
  }
58073
58844
  };
58845
+ function filterIndexByArtifact(index3, artifactId) {
58846
+ const node = index3.artifacts[artifactId];
58847
+ if (!node) {
58848
+ throw new Error(`Artifact not found: ${artifactId}`);
58849
+ }
58850
+ return {
58851
+ ...index3,
58852
+ artifacts: { [artifactId]: node }
58853
+ };
58854
+ }
58855
+ function writeNavigationIndex(index3, format2) {
58856
+ if (format2 === "json") {
58857
+ process.stdout.write(JSON.stringify(index3, null, 2) + "\n");
58858
+ } else {
58859
+ process.stdout.write(stringify3(index3));
58860
+ }
58861
+ }
58862
+ async function buildNavigationIndexForDsl(dslPath, vars, artifactFilter) {
58863
+ const resolved = await resolve4(dslPath);
58864
+ const data = vars ? substituteVars(resolved.data, vars) : resolved.data;
58865
+ const schemaResult = validateSchema(data);
58866
+ if (!schemaResult.success) {
58867
+ const issues = schemaResult.diagnostics.map((d2) => ` ${d2.path}: ${d2.message}`).join("\n");
58868
+ process.stderr.write(`Schema validation failed:
58869
+ ${issues}
58870
+ `);
58871
+ throw new Error("schema validation failed");
58872
+ }
58873
+ let index3 = buildNavigationIndex(schemaResult.data);
58874
+ if (artifactFilter) {
58875
+ index3 = filterIndexByArtifact(index3, artifactFilter);
58876
+ }
58877
+ return index3;
58878
+ }
58879
+ var handleNavigationIndex = async (dir, opts) => {
58880
+ const fmt = opts.format ?? "json";
58881
+ if (fmt !== "json" && fmt !== "yaml") {
58882
+ process.stderr.write(`Invalid --format: expected json or yaml, got ${fmt}
58883
+ `);
58884
+ process.exit(1);
58885
+ }
58886
+ try {
58887
+ const config = await loadConfig(opts.config);
58888
+ if (config !== null && isMultiTeamConfig(config)) {
58889
+ const teamEntries = getTeamEntries(config, opts.team);
58890
+ let hasErrors = false;
58891
+ if (fmt === "json") {
58892
+ const out = {};
58893
+ for (const [teamId, teamConfig] of teamEntries) {
58894
+ try {
58895
+ out[teamId] = await buildNavigationIndexForDsl(
58896
+ teamConfig.dsl,
58897
+ teamConfig.vars,
58898
+ opts.artifact
58899
+ );
58900
+ } catch (err) {
58901
+ if (err instanceof Error && err.message === "schema validation failed") {
58902
+ hasErrors = true;
58903
+ continue;
58904
+ }
58905
+ throw err;
58906
+ }
58907
+ }
58908
+ if (hasErrors) process.exit(1);
58909
+ process.stdout.write(JSON.stringify(out, null, 2) + "\n");
58910
+ } else {
58911
+ for (const [teamId, teamConfig] of teamEntries) {
58912
+ if (!opts.quiet) process.stdout.write(`
58913
+ --- Team: ${teamId} ---
58914
+ `);
58915
+ try {
58916
+ const index4 = await buildNavigationIndexForDsl(
58917
+ teamConfig.dsl,
58918
+ teamConfig.vars,
58919
+ opts.artifact
58920
+ );
58921
+ process.stdout.write(stringify3(index4));
58922
+ } catch (err) {
58923
+ if (err instanceof Error && err.message === "schema validation failed") {
58924
+ hasErrors = true;
58925
+ continue;
58926
+ }
58927
+ throw err;
58928
+ }
58929
+ }
58930
+ if (hasErrors) process.exit(1);
58931
+ }
58932
+ return;
58933
+ }
58934
+ const dslPath = resolveDslPath(dir ?? DIR_DEFAULT, DIR_DEFAULT, config);
58935
+ const index3 = await buildNavigationIndexForDsl(dslPath, config?.vars, opts.artifact);
58936
+ writeNavigationIndex(index3, fmt);
58937
+ } catch (err) {
58938
+ const msg = err instanceof Error ? err.message : String(err);
58939
+ process.stderr.write(`Error: ${msg}
58940
+ `);
58941
+ process.exit(1);
58942
+ }
58943
+ };
58074
58944
  var handlers = {
58075
58945
  resolve: handleResolve,
58076
58946
  validate: handleValidate,
@@ -58079,12 +58949,13 @@ var handlers = {
58079
58949
  check: handleCheck,
58080
58950
  score: handleScore,
58081
58951
  audit: handleAudit,
58082
- generate: handleGenerate
58952
+ generate: handleGenerate,
58953
+ navigationIndex: handleNavigationIndex
58083
58954
  };
58084
58955
 
58085
58956
  // src/cli/cli.ts
58086
58957
  var __dirname = dirname8(fileURLToPath(import.meta.url));
58087
- var pkg = JSON.parse(readFileSync2(resolve8(__dirname, "../package.json"), "utf8"));
58958
+ var pkg = JSON.parse(readFileSync3(resolve9(__dirname, "../package.json"), "utf8"));
58088
58959
  var program = createProgram(handlers, pkg.version);
58089
58960
  program.parse();
58090
58961
  /*! Bundled license information: