@nail00749/agent-gvozd 0.1.2 → 0.1.4

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
@@ -2462,6 +2462,14 @@ function cleanRegex(source) {
2462
2462
  const end = source.endsWith("$") ? source.length - 1 : source.length;
2463
2463
  return source.slice(start, end);
2464
2464
  }
2465
+ function floatSafeRemainder(val, step) {
2466
+ const ratio = val / step;
2467
+ const roundedRatio = Math.round(ratio);
2468
+ const tolerance = Number.EPSILON * Math.max(Math.abs(ratio), 1);
2469
+ if (Math.abs(ratio - roundedRatio) < tolerance)
2470
+ return 0;
2471
+ return ratio - roundedRatio;
2472
+ }
2465
2473
  var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
2466
2474
  function defineLazy(object, key, getter) {
2467
2475
  let value = undefined;
@@ -3020,6 +3028,7 @@ var string = (params) => {
3020
3028
  const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
3021
3029
  return new RegExp(`^${regex}$`);
3022
3030
  };
3031
+ var integer = /^-?\d+$/;
3023
3032
  var number = /^-?\d+(?:\.\d+)?$/;
3024
3033
  var boolean = /^(?:true|false)$/i;
3025
3034
  var lowercase = /^[^A-Z]*$/;
@@ -3032,6 +3041,168 @@ var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
3032
3041
  inst._zod.def = def;
3033
3042
  (_a = inst._zod).onattach ?? (_a.onattach = []);
3034
3043
  });
3044
+ var numericOriginMap = {
3045
+ number: "number",
3046
+ bigint: "bigint",
3047
+ object: "date"
3048
+ };
3049
+ var $ZodCheckLessThan = /* @__PURE__ */ $constructor("$ZodCheckLessThan", (inst, def) => {
3050
+ $ZodCheck.init(inst, def);
3051
+ const origin = numericOriginMap[typeof def.value];
3052
+ inst._zod.onattach.push((inst) => {
3053
+ const bag = inst._zod.bag;
3054
+ const curr = (def.inclusive ? bag.maximum : bag.exclusiveMaximum) ?? Number.POSITIVE_INFINITY;
3055
+ if (def.value < curr) {
3056
+ if (def.inclusive)
3057
+ bag.maximum = def.value;
3058
+ else
3059
+ bag.exclusiveMaximum = def.value;
3060
+ }
3061
+ });
3062
+ inst._zod.check = (payload) => {
3063
+ if (def.inclusive ? payload.value <= def.value : payload.value < def.value) {
3064
+ return;
3065
+ }
3066
+ payload.issues.push({
3067
+ origin,
3068
+ code: "too_big",
3069
+ maximum: typeof def.value === "object" ? def.value.getTime() : def.value,
3070
+ input: payload.value,
3071
+ inclusive: def.inclusive,
3072
+ inst,
3073
+ continue: !def.abort
3074
+ });
3075
+ };
3076
+ });
3077
+ var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan", (inst, def) => {
3078
+ $ZodCheck.init(inst, def);
3079
+ const origin = numericOriginMap[typeof def.value];
3080
+ inst._zod.onattach.push((inst) => {
3081
+ const bag = inst._zod.bag;
3082
+ const curr = (def.inclusive ? bag.minimum : bag.exclusiveMinimum) ?? Number.NEGATIVE_INFINITY;
3083
+ if (def.value > curr) {
3084
+ if (def.inclusive)
3085
+ bag.minimum = def.value;
3086
+ else
3087
+ bag.exclusiveMinimum = def.value;
3088
+ }
3089
+ });
3090
+ inst._zod.check = (payload) => {
3091
+ if (def.inclusive ? payload.value >= def.value : payload.value > def.value) {
3092
+ return;
3093
+ }
3094
+ payload.issues.push({
3095
+ origin,
3096
+ code: "too_small",
3097
+ minimum: typeof def.value === "object" ? def.value.getTime() : def.value,
3098
+ input: payload.value,
3099
+ inclusive: def.inclusive,
3100
+ inst,
3101
+ continue: !def.abort
3102
+ });
3103
+ };
3104
+ });
3105
+ var $ZodCheckMultipleOf = /* @__PURE__ */ $constructor("$ZodCheckMultipleOf", (inst, def) => {
3106
+ $ZodCheck.init(inst, def);
3107
+ inst._zod.onattach.push((inst) => {
3108
+ var _a;
3109
+ (_a = inst._zod.bag).multipleOf ?? (_a.multipleOf = def.value);
3110
+ });
3111
+ inst._zod.check = (payload) => {
3112
+ if (typeof payload.value !== typeof def.value)
3113
+ throw new Error("Cannot mix number and bigint in multiple_of check.");
3114
+ const isMultiple = typeof payload.value === "bigint" ? payload.value % def.value === BigInt(0) : floatSafeRemainder(payload.value, def.value) === 0;
3115
+ if (isMultiple)
3116
+ return;
3117
+ payload.issues.push({
3118
+ origin: typeof payload.value,
3119
+ code: "not_multiple_of",
3120
+ divisor: def.value,
3121
+ input: payload.value,
3122
+ inst,
3123
+ continue: !def.abort
3124
+ });
3125
+ };
3126
+ });
3127
+ var $ZodCheckNumberFormat = /* @__PURE__ */ $constructor("$ZodCheckNumberFormat", (inst, def) => {
3128
+ $ZodCheck.init(inst, def);
3129
+ def.format = def.format || "float64";
3130
+ const isInt = def.format?.includes("int");
3131
+ const origin = isInt ? "int" : "number";
3132
+ const [minimum, maximum] = NUMBER_FORMAT_RANGES[def.format];
3133
+ inst._zod.onattach.push((inst) => {
3134
+ const bag = inst._zod.bag;
3135
+ bag.format = def.format;
3136
+ bag.minimum = minimum;
3137
+ bag.maximum = maximum;
3138
+ if (isInt)
3139
+ bag.pattern = integer;
3140
+ });
3141
+ inst._zod.check = (payload) => {
3142
+ const input = payload.value;
3143
+ if (isInt) {
3144
+ if (!Number.isInteger(input)) {
3145
+ payload.issues.push({
3146
+ expected: origin,
3147
+ format: def.format,
3148
+ code: "invalid_type",
3149
+ continue: false,
3150
+ input,
3151
+ inst
3152
+ });
3153
+ return;
3154
+ }
3155
+ if (!Number.isSafeInteger(input)) {
3156
+ if (input > 0) {
3157
+ payload.issues.push({
3158
+ input,
3159
+ code: "too_big",
3160
+ maximum: Number.MAX_SAFE_INTEGER,
3161
+ note: "Integers must be within the safe integer range.",
3162
+ inst,
3163
+ origin,
3164
+ inclusive: true,
3165
+ continue: !def.abort
3166
+ });
3167
+ } else {
3168
+ payload.issues.push({
3169
+ input,
3170
+ code: "too_small",
3171
+ minimum: Number.MIN_SAFE_INTEGER,
3172
+ note: "Integers must be within the safe integer range.",
3173
+ inst,
3174
+ origin,
3175
+ inclusive: true,
3176
+ continue: !def.abort
3177
+ });
3178
+ }
3179
+ return;
3180
+ }
3181
+ }
3182
+ if (input < minimum) {
3183
+ payload.issues.push({
3184
+ origin: "number",
3185
+ input,
3186
+ code: "too_small",
3187
+ minimum,
3188
+ inclusive: true,
3189
+ inst,
3190
+ continue: !def.abort
3191
+ });
3192
+ }
3193
+ if (input > maximum) {
3194
+ payload.issues.push({
3195
+ origin: "number",
3196
+ input,
3197
+ code: "too_big",
3198
+ maximum,
3199
+ inclusive: true,
3200
+ inst,
3201
+ continue: !def.abort
3202
+ });
3203
+ }
3204
+ };
3205
+ });
3035
3206
  var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (inst, def) => {
3036
3207
  var _a;
3037
3208
  $ZodCheck.init(inst, def);
@@ -3714,6 +3885,33 @@ var $ZodJWT = /* @__PURE__ */ $constructor("$ZodJWT", (inst, def) => {
3714
3885
  });
3715
3886
  };
3716
3887
  });
3888
+ var $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
3889
+ $ZodType.init(inst, def);
3890
+ inst._zod.pattern = inst._zod.bag.pattern ?? number;
3891
+ inst._zod.parse = (payload, _ctx) => {
3892
+ if (def.coerce)
3893
+ try {
3894
+ payload.value = Number(payload.value);
3895
+ } catch (_) {}
3896
+ const input = payload.value;
3897
+ if (typeof input === "number" && !Number.isNaN(input) && Number.isFinite(input)) {
3898
+ return payload;
3899
+ }
3900
+ const received = typeof input === "number" ? Number.isNaN(input) ? "NaN" : !Number.isFinite(input) ? "Infinity" : undefined : undefined;
3901
+ payload.issues.push({
3902
+ expected: "number",
3903
+ code: "invalid_type",
3904
+ input,
3905
+ inst,
3906
+ ...received ? { received } : {}
3907
+ });
3908
+ return payload;
3909
+ };
3910
+ });
3911
+ var $ZodNumberFormat = /* @__PURE__ */ $constructor("$ZodNumberFormat", (inst, def) => {
3912
+ $ZodCheckNumberFormat.init(inst, def);
3913
+ $ZodNumber.init(inst, def);
3914
+ });
3717
3915
  var $ZodBoolean = /* @__PURE__ */ $constructor("$ZodBoolean", (inst, def) => {
3718
3916
  $ZodType.init(inst, def);
3719
3917
  inst._zod.pattern = boolean;
@@ -4928,6 +5126,22 @@ function _isoDuration(Class, params) {
4928
5126
  ...normalizeParams(params)
4929
5127
  });
4930
5128
  }
5129
+ function _number(Class, params) {
5130
+ return new Class({
5131
+ type: "number",
5132
+ checks: [],
5133
+ ...normalizeParams(params)
5134
+ });
5135
+ }
5136
+ function _int(Class, params) {
5137
+ return new Class({
5138
+ type: "number",
5139
+ check: "number_format",
5140
+ abort: false,
5141
+ format: "safeint",
5142
+ ...normalizeParams(params)
5143
+ });
5144
+ }
4931
5145
  function _boolean(Class, params) {
4932
5146
  return new Class({
4933
5147
  type: "boolean",
@@ -4945,6 +5159,45 @@ function _never(Class, params) {
4945
5159
  ...normalizeParams(params)
4946
5160
  });
4947
5161
  }
5162
+ function _lt(value, params) {
5163
+ return new $ZodCheckLessThan({
5164
+ check: "less_than",
5165
+ ...normalizeParams(params),
5166
+ value,
5167
+ inclusive: false
5168
+ });
5169
+ }
5170
+ function _lte(value, params) {
5171
+ return new $ZodCheckLessThan({
5172
+ check: "less_than",
5173
+ ...normalizeParams(params),
5174
+ value,
5175
+ inclusive: true
5176
+ });
5177
+ }
5178
+ function _gt(value, params) {
5179
+ return new $ZodCheckGreaterThan({
5180
+ check: "greater_than",
5181
+ ...normalizeParams(params),
5182
+ value,
5183
+ inclusive: false
5184
+ });
5185
+ }
5186
+ function _gte(value, params) {
5187
+ return new $ZodCheckGreaterThan({
5188
+ check: "greater_than",
5189
+ ...normalizeParams(params),
5190
+ value,
5191
+ inclusive: true
5192
+ });
5193
+ }
5194
+ function _multipleOf(value, params) {
5195
+ return new $ZodCheckMultipleOf({
5196
+ check: "multiple_of",
5197
+ ...normalizeParams(params),
5198
+ value
5199
+ });
5200
+ }
4948
5201
  function _maxLength(maximum, params) {
4949
5202
  const ch = new $ZodCheckMaxLength({
4950
5203
  check: "max_length",
@@ -5470,6 +5723,39 @@ var stringProcessor = (schema, ctx, _json, _params) => {
5470
5723
  }
5471
5724
  }
5472
5725
  };
5726
+ var numberProcessor = (schema, ctx, _json, _params) => {
5727
+ const json = _json;
5728
+ const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag;
5729
+ if (typeof format === "string" && format.includes("int"))
5730
+ json.type = "integer";
5731
+ else
5732
+ json.type = "number";
5733
+ const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
5734
+ const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
5735
+ const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
5736
+ if (exMin) {
5737
+ if (legacy) {
5738
+ json.minimum = exclusiveMinimum;
5739
+ json.exclusiveMinimum = true;
5740
+ } else {
5741
+ json.exclusiveMinimum = exclusiveMinimum;
5742
+ }
5743
+ } else if (typeof minimum === "number") {
5744
+ json.minimum = minimum;
5745
+ }
5746
+ if (exMax) {
5747
+ if (legacy) {
5748
+ json.maximum = exclusiveMaximum;
5749
+ json.exclusiveMaximum = true;
5750
+ } else {
5751
+ json.exclusiveMaximum = exclusiveMaximum;
5752
+ }
5753
+ } else if (typeof maximum === "number") {
5754
+ json.maximum = maximum;
5755
+ }
5756
+ if (typeof multipleOf === "number")
5757
+ json.multipleOf = multipleOf;
5758
+ };
5473
5759
  var booleanProcessor = (_schema, _ctx, json, _params) => {
5474
5760
  json.type = "boolean";
5475
5761
  };
@@ -6093,6 +6379,74 @@ var ZodJWT = /* @__PURE__ */ $constructor("ZodJWT", (inst, def) => {
6093
6379
  $ZodJWT.init(inst, def);
6094
6380
  ZodStringFormat.init(inst, def);
6095
6381
  });
6382
+ var ZodNumber = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
6383
+ $ZodNumber.init(inst, def);
6384
+ ZodType.init(inst, def);
6385
+ inst._zod.processJSONSchema = (ctx, json, params) => numberProcessor(inst, ctx, json, params);
6386
+ _installLazyMethods(inst, "ZodNumber", {
6387
+ gt(value, params) {
6388
+ return this.check(_gt(value, params));
6389
+ },
6390
+ gte(value, params) {
6391
+ return this.check(_gte(value, params));
6392
+ },
6393
+ min(value, params) {
6394
+ return this.check(_gte(value, params));
6395
+ },
6396
+ lt(value, params) {
6397
+ return this.check(_lt(value, params));
6398
+ },
6399
+ lte(value, params) {
6400
+ return this.check(_lte(value, params));
6401
+ },
6402
+ max(value, params) {
6403
+ return this.check(_lte(value, params));
6404
+ },
6405
+ int(params) {
6406
+ return this.check(int(params));
6407
+ },
6408
+ safe(params) {
6409
+ return this.check(int(params));
6410
+ },
6411
+ positive(params) {
6412
+ return this.check(_gt(0, params));
6413
+ },
6414
+ nonnegative(params) {
6415
+ return this.check(_gte(0, params));
6416
+ },
6417
+ negative(params) {
6418
+ return this.check(_lt(0, params));
6419
+ },
6420
+ nonpositive(params) {
6421
+ return this.check(_lte(0, params));
6422
+ },
6423
+ multipleOf(value, params) {
6424
+ return this.check(_multipleOf(value, params));
6425
+ },
6426
+ step(value, params) {
6427
+ return this.check(_multipleOf(value, params));
6428
+ },
6429
+ finite() {
6430
+ return this;
6431
+ }
6432
+ });
6433
+ const bag = inst._zod.bag;
6434
+ inst.minValue = Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null;
6435
+ inst.maxValue = Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null;
6436
+ inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5);
6437
+ inst.isFinite = true;
6438
+ inst.format = bag.format ?? null;
6439
+ });
6440
+ function number2(params) {
6441
+ return _number(ZodNumber, params);
6442
+ }
6443
+ var ZodNumberFormat = /* @__PURE__ */ $constructor("ZodNumberFormat", (inst, def) => {
6444
+ $ZodNumberFormat.init(inst, def);
6445
+ ZodNumber.init(inst, def);
6446
+ });
6447
+ function int(params) {
6448
+ return _int(ZodNumberFormat, params);
6449
+ }
6096
6450
  var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
6097
6451
  $ZodBoolean.init(inst, def);
6098
6452
  ZodType.init(inst, def);
@@ -6633,6 +6987,10 @@ function computeProjectTrustToken(projectDirectory) {
6633
6987
  return `sha256:${hash.digest("hex")}`;
6634
6988
  }
6635
6989
 
6990
+ // src/file-leases.ts
6991
+ var DEFAULT_RESERVATION_TTL_MS = 5 * 60 * 1000;
6992
+ var DEFAULT_ACTIVE_TTL_MS = 30 * 60 * 1000;
6993
+
6636
6994
  // src/config.ts
6637
6995
  var permissionSchema = object({
6638
6996
  action: string2().min(1),
@@ -6653,11 +7011,16 @@ var agentPatchSchema = object({
6653
7011
  fileLease: fileLeaseRoleSchema.optional(),
6654
7012
  disabled: boolean2().optional()
6655
7013
  }).strict();
7014
+ var leaseSchema = object({
7015
+ reservationTtlMinutes: number2().int().positive().max(24 * 60).optional(),
7016
+ activeTtlMinutes: number2().int().positive().max(24 * 60).optional()
7017
+ }).strict();
6656
7018
  var rootPatchSchema = object({
6657
7019
  $schema: string2().min(1).optional(),
6658
7020
  defaultAgent: agentIdSchema.optional(),
6659
7021
  agentsDirectory: string2().min(1).optional(),
6660
- agents: record(agentIdSchema, agentPatchSchema).optional()
7022
+ agents: record(agentIdSchema, agentPatchSchema).optional(),
7023
+ lease: leaseSchema.optional()
6661
7024
  }).strict();
6662
7025
  var resolvedAgentSchema = agentPatchSchema.extend({
6663
7026
  description: string2().min(1),
@@ -6721,7 +7084,7 @@ function loadLayer(directory, rootFileName, required, projectPolicy) {
6721
7084
  }
6722
7085
  const root = rootPatchSchema.parse(readJsonc2(rootPath));
6723
7086
  if (projectPolicy && !projectPolicy.trusted) {
6724
- const restricted = ["defaultAgent", "agentsDirectory"].filter((field) => Object.prototype.hasOwnProperty.call(root, field));
7087
+ const restricted = ["defaultAgent", "agentsDirectory", "lease"].filter((field) => Object.prototype.hasOwnProperty.call(root, field));
6725
7088
  if (restricted.length > 0)
6726
7089
  throw new Error(`Untrusted project config ${rootPath} cannot override ${restricted.join(", ")}`);
6727
7090
  }
@@ -6754,6 +7117,7 @@ function loadLayer(directory, rootFileName, required, projectPolicy) {
6754
7117
  return {
6755
7118
  defaultAgent: root.defaultAgent,
6756
7119
  agents,
7120
+ lease: root.lease,
6757
7121
  sources: [rootPath]
6758
7122
  };
6759
7123
  }
@@ -6815,6 +7179,20 @@ function loadConfig(projectDirectory, options = {}) {
6815
7179
  throw new Error("Project configuration changed while its trust token was being validated; review it and compute a new token");
6816
7180
  }
6817
7181
  const layers = [...baseLayers, ...projectLayer ? [projectLayer] : []];
7182
+ const lease = {
7183
+ reservationTtlMs: DEFAULT_RESERVATION_TTL_MS,
7184
+ activeTtlMs: DEFAULT_ACTIVE_TTL_MS
7185
+ };
7186
+ for (const layer of layers) {
7187
+ if (!layer.lease)
7188
+ continue;
7189
+ if (layer.lease.reservationTtlMinutes !== undefined) {
7190
+ lease.reservationTtlMs = layer.lease.reservationTtlMinutes * 60000;
7191
+ }
7192
+ if (layer.lease.activeTtlMinutes !== undefined) {
7193
+ lease.activeTtlMs = layer.lease.activeTtlMinutes * 60000;
7194
+ }
7195
+ }
6818
7196
  let defaultAgent;
6819
7197
  const agents = {};
6820
7198
  for (const layer of layers) {
@@ -6841,6 +7219,7 @@ function loadConfig(projectDirectory, options = {}) {
6841
7219
  return {
6842
7220
  defaultAgent,
6843
7221
  agents: resolvedAgents,
7222
+ lease,
6844
7223
  packageRoot,
6845
7224
  projectRoot,
6846
7225
  projectConfigDirectory,
@@ -6853,6 +7232,77 @@ function loadConfig(projectDirectory, options = {}) {
6853
7232
  import { existsSync as existsSync3, lstatSync as lstatSync3, readFileSync as readFileSync3, readdirSync as readdirSync3 } from "node:fs";
6854
7233
  import { join as join4, resolve as resolve4 } from "node:path";
6855
7234
 
7235
+ // src/tool-permissions.ts
7236
+ function family(command, ...variants) {
7237
+ return [command, ...variants].map((entry) => ({
7238
+ exact: entry,
7239
+ wildcard: `${entry} *`
7240
+ }));
7241
+ }
7242
+ function exactOnly(command, ...variants) {
7243
+ return [command, ...variants].map((entry) => ({ exact: entry, wildcard: entry }));
7244
+ }
7245
+ var INSPECTION_COMMANDS = [
7246
+ ...family("pwd", "true", "test"),
7247
+ ...family("cat", "head", "tail", "wc", "sort", "uniq"),
7248
+ ...family("grep", "rg", "find", "diff", "cmp"),
7249
+ ...family("ls", "du", "df", "stat", "file", "realpath", "basename", "dirname"),
7250
+ ...family("shasum", "sha256sum", "md5sum"),
7251
+ ...family("uname", "whoami", "hostname", "date", "printenv"),
7252
+ ...family("which", "command -v"),
7253
+ ...family("mktemp"),
7254
+ ...family("tr", "cut", "paste", "column"),
7255
+ ...family("node --version", "python3 --version", "python --version", "deno --version")
7256
+ ];
7257
+ var TOOLCHAIN_COMMANDS = [
7258
+ ...family("bun test", "bun run test", "bun --version"),
7259
+ ...family("bun run typecheck", "bun run lint", "bun run build", "bun run check"),
7260
+ ...family("tsc --noEmit", "npx tsc --noEmit"),
7261
+ ...family("eslint", "biome check", "prettier --check"),
7262
+ ...family("npm test", "npm run test", "npm run typecheck", "npm run lint", "npm run build"),
7263
+ ...family("pnpm test", "pnpm run test", "pnpm run build"),
7264
+ ...family("yarn test", "yarn build"),
7265
+ ...family("vitest run", "jest", "playwright test"),
7266
+ ...family("cargo check", "cargo test", "cargo build", "cargo clippy", "cargo fmt --check", "cargo --version"),
7267
+ ...family("go build ./...", "go test ./...", "go vet ./...", "go version"),
7268
+ ...family("pytest", "python3 -m pytest", "python -m pytest"),
7269
+ ...family("ruff check", "mypy", "pyright"),
7270
+ ...family("mvn test", "mvn verify", "gradle test", "gradle check", "./gradlew test", "./gradlew check"),
7271
+ ...family("make test", "make check", "make build", "make --version"),
7272
+ ...family("just --list")
7273
+ ];
7274
+ var GIT_READONLY_COMMANDS = [
7275
+ ...family("git status", "git status --short", "git status --short --branch", "git status --porcelain", "git status --porcelain=v1 --branch"),
7276
+ ...family("git diff", "git diff --stat", "git diff --cached", "git diff --check"),
7277
+ ...family("git log", "git show"),
7278
+ ...family("git rev-parse", "git rev-list", "git show-ref", "git cat-file"),
7279
+ ...exactOnly("git symbolic-ref HEAD", "git symbolic-ref --short HEAD"),
7280
+ ...family("git ls-files", "git ls-remote", "git grep"),
7281
+ ...exactOnly("git branch", "git tag", "git remote", "git reflog"),
7282
+ ...family("git branch --list", "git branch -l", "git branch -a", "git branch -r", "git branch -v", "git branch -vv", "git branch --all", "git branch --remotes", "git branch --show-current", "git branch --contains"),
7283
+ ...family("git tag --list", "git tag -l", "git tag -n"),
7284
+ ...family("git remote -v", "git remote --verbose", "git remote show", "git remote get-url"),
7285
+ ...family("git reflog show"),
7286
+ ...family("git stash list", "git describe", "git worktree list"),
7287
+ ...family("git config --get", "git config --get-regexp")
7288
+ ];
7289
+ var GIT_MUTATING_COMMANDS = [
7290
+ ...family("git add", "git rm --cached"),
7291
+ ...family("git commit", "git merge --ff-only", "git merge --no-ff"),
7292
+ ...family("git push", "git fetch", "git pull --ff-only"),
7293
+ ...family("git stash", "git cherry-pick", "git revert"),
7294
+ ...family("git switch", "git checkout -b", "git worktree add"),
7295
+ ...exactOnly("git branch *", "git tag *", "git remote *", "git symbolic-ref *", "git reflog *")
7296
+ ];
7297
+ var GIT_ENV_PREFIXES = ["GIT_OPTIONAL_LOCKS=0"];
7298
+ function withEnvPrefixes(rule, prefixes = GIT_ENV_PREFIXES) {
7299
+ return prefixes.map((prefix) => ({
7300
+ action: rule.action,
7301
+ resource: `${prefix} ${rule.resource}`,
7302
+ effect: rule.effect
7303
+ }));
7304
+ }
7305
+
6856
7306
  // src/agent-permissions.ts
6857
7307
  function normalizeMcpName(name) {
6858
7308
  return name.replaceAll(/[^A-Za-z0-9_-]/g, "_");
@@ -6872,15 +7322,24 @@ function buildAgentPermissions(agent, mcpServers) {
6872
7322
  });
6873
7323
  result.push(...agent.permissions.filter((rule) => rule.action.startsWith(prefix)));
6874
7324
  }
7325
+ for (const rule of agent.permissions) {
7326
+ if (rule.action !== "shell")
7327
+ continue;
7328
+ if (!/(^|\s|["'])git(?:$|\s)/.test(rule.resource))
7329
+ continue;
7330
+ if (rule.resource.startsWith("GIT_"))
7331
+ continue;
7332
+ result.push(...withEnvPrefixes(rule));
7333
+ }
6875
7334
  return result;
6876
7335
  }
6877
7336
 
6878
7337
  // src/release-metadata.ts
6879
7338
  var PACKAGE_NAME = "@nail00749/agent-gvozd";
6880
- var PACKAGE_VERSION = "0.1.2";
7339
+ var PACKAGE_VERSION = "0.1.4";
6881
7340
  var PACKAGE_SPEC = `${PACKAGE_NAME}@${PACKAGE_VERSION}`;
6882
7341
  var SUPPORTED_OPENCODE_VERSION = "0.0.0-beta-19425";
6883
- var CONFIG_SCHEMA_VERSION = 1;
7342
+ var CONFIG_SCHEMA_VERSION = 2;
6884
7343
 
6885
7344
  // src/constants.ts
6886
7345
  var GENERATED_MARKER = "# Generated by agent-gvozd sync. Do not edit this file directly.";
@@ -6897,7 +7356,13 @@ function hasGeneratedPluginMarker(content) {
6897
7356
  function hasGeneratedSchemaMarker(content) {
6898
7357
  const errors = [];
6899
7358
  const value = parse2(content, errors, { allowTrailingComma: true, disallowComments: false });
6900
- return errors.length === 0 && value !== null && typeof value === "object" && !Array.isArray(value) && value.$comment === GENERATED_PLUGIN_MARKER && value["x-agent-gvozd-schema-version"] === CONFIG_SCHEMA_VERSION;
7359
+ if (errors.length > 0 || value === null || typeof value !== "object" || Array.isArray(value)) {
7360
+ return false;
7361
+ }
7362
+ if (value.$comment !== GENERATED_PLUGIN_MARKER)
7363
+ return false;
7364
+ const version = value["x-agent-gvozd-schema-version"];
7365
+ return typeof version === "number" && Number.isSafeInteger(version) && version >= 1 && version <= CONFIG_SCHEMA_VERSION;
6901
7366
  }
6902
7367
  function stable(value) {
6903
7368
  if (Array.isArray(value))
@@ -7363,7 +7828,7 @@ async function runDoctor(input) {
7363
7828
  checks.push({ id: "runtime-agents", status: "fail", summary: `runtime agent check failed: ${redactDiagnostic(error)}`, remediation: `${input.client.executable} service restart` });
7364
7829
  }
7365
7830
  checks.push(config ? checkLegacy(config) : { id: "legacy-local", status: "warn", summary: "legacy duplicates could not be checked" });
7366
- return { schemaVersion: 1, status: aggregate(checks), checks };
7831
+ return { schemaVersion: CONFIG_SCHEMA_VERSION, status: aggregate(checks), checks };
7367
7832
  }
7368
7833
  function doctorExitCode(report) {
7369
7834
  return report.status === "fail" ? 1 : 0;
@@ -7388,7 +7853,7 @@ function doctorOperationalFailure(error) {
7388
7853
  summary: `OpenCode discovery failed: ${redactDiagnostic(error)}`,
7389
7854
  remediation: `Install OpenCode ${SUPPORTED_OPENCODE_VERSION} and run gvozd doctor again`
7390
7855
  }];
7391
- return { schemaVersion: 1, status: "fail", checks };
7856
+ return { schemaVersion: CONFIG_SCHEMA_VERSION, status: "fail", checks };
7392
7857
  }
7393
7858
 
7394
7859
  // src/cli/setup.ts
@@ -7550,8 +8015,10 @@ function assertWriteable(path, label) {
7550
8015
  function legacySchemaMatches(source, generated) {
7551
8016
  try {
7552
8017
  const previous = JSON.parse(source);
7553
- if (previous.$comment !== undefined || ![undefined, 1].includes(previous["x-agent-gvozd-schema-version"]))
8018
+ const previousVersion = previous["x-agent-gvozd-schema-version"];
8019
+ if (previous.$comment !== undefined || previousVersion !== undefined && previousVersion !== CONFIG_SCHEMA_VERSION) {
7554
8020
  return false;
8021
+ }
7555
8022
  if (previous.$id !== "https://example.invalid/agent-gvozd.schema.json")
7556
8023
  return false;
7557
8024
  return generated ? isEquivalentLegacySchema(source, generated) : true;