mustflow 2.115.16 → 2.115.17

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.
@@ -8,6 +8,7 @@ import { inspectActiveRunLocks, } from '../../core/active-run-locks.js';
8
8
  import { isRecord, readPositiveInteger, readString, readStringArray, } from '../../core/config-loading.js';
9
9
  import { DEFAULT_COMMAND_MAX_OUTPUT_BYTES, COMMAND_OUTPUT_LIMIT_SCOPE, } from '../../core/command-output-limits.js';
10
10
  import { checkRepoApprovalGate } from '../../core/repo-approval-gate.js';
11
+ import { inferCommandApprovalActions } from '../../core/approval-actions.js';
11
12
  import { normalizeSuccessExitCodes } from '../../core/success-exit-codes.js';
12
13
  import { normalizeSafeTestTargetPath, TEST_TARGET_PATH_ERROR } from '../../core/test-target-paths.js';
13
14
  import { evaluateCommandPreconditions, } from '../../core/command-preconditions.js';
@@ -134,7 +135,10 @@ function readRunIntentMetadata(contract, intent) {
134
135
  };
135
136
  }
136
137
  function createApprovalBlock(projectRoot, metadata, approvedActions) {
137
- const actionTypes = [...metadata.approvalActions];
138
+ const actionTypes = [
139
+ ...metadata.approvalActions,
140
+ ...inferCommandApprovalActions(metadata.commandArgv ?? []),
141
+ ];
138
142
  if (metadata.network === true) {
139
143
  actionTypes.push('network_access');
140
144
  }
@@ -11,3 +11,31 @@ export const APPROVAL_ACTION_TYPES = [
11
11
  'cross_repository_change',
12
12
  ];
13
13
  export const APPROVAL_ACTION_TYPE_SET = new Set(APPROVAL_ACTION_TYPES);
14
+ function readGitSubcommand(argv) {
15
+ if ((argv[0] ?? '').split(/[\\/]/u).at(-1)?.replace(/\.(?:cmd|exe|ps1)$/iu, '').toLowerCase() !== 'git') {
16
+ return null;
17
+ }
18
+ const optionsWithSeparateValue = new Set(['-C', '-c', '--exec-path', '--git-dir', '--work-tree', '--namespace']);
19
+ for (let index = 1; index < argv.length; index += 1) {
20
+ const argument = argv[index] ?? '';
21
+ if (optionsWithSeparateValue.has(argument)) {
22
+ index += 1;
23
+ continue;
24
+ }
25
+ if (argument.startsWith('-')) {
26
+ continue;
27
+ }
28
+ return argument;
29
+ }
30
+ return null;
31
+ }
32
+ export function inferCommandApprovalActions(argv) {
33
+ const gitSubcommand = readGitSubcommand(argv);
34
+ if (gitSubcommand === 'add' || gitSubcommand === 'commit') {
35
+ return ['git_commit'];
36
+ }
37
+ if (gitSubcommand === 'push') {
38
+ return ['git_push'];
39
+ }
40
+ return [];
41
+ }
@@ -71,46 +71,6 @@ function validateApprovalActions(intentName, intent, issues) {
71
71
  issues.push(commandContractIssue(`[commands.intents.${intentName}].approval_actions contains unsupported action types: ${unsupported.join(', ')}`));
72
72
  }
73
73
  }
74
- function readGitSubcommand(argv) {
75
- if (normalizeCommandExecutableName(argv[0] ?? '') !== 'git') {
76
- return null;
77
- }
78
- const optionsWithSeparateValue = new Set(['-C', '-c', '--exec-path', '--git-dir', '--work-tree', '--namespace']);
79
- for (let index = 1; index < argv.length; index += 1) {
80
- const argument = argv[index] ?? '';
81
- if (optionsWithSeparateValue.has(argument)) {
82
- index += 1;
83
- continue;
84
- }
85
- if (argument.startsWith('-')) {
86
- continue;
87
- }
88
- return argument;
89
- }
90
- return null;
91
- }
92
- function validateSensitiveGitApprovalActions(intentName, intent, issues) {
93
- if (intent.status !== 'configured' || intent.run_policy !== 'agent_allowed') {
94
- return;
95
- }
96
- const argv = readStringArray(intent, 'argv');
97
- if (!argv) {
98
- return;
99
- }
100
- const gitSubcommand = readGitSubcommand(argv);
101
- const requiredAction = gitSubcommand === 'add' || gitSubcommand === 'commit'
102
- ? 'git_commit'
103
- : gitSubcommand === 'push'
104
- ? 'git_push'
105
- : null;
106
- if (!requiredAction) {
107
- return;
108
- }
109
- const approvalActions = readStringArray(intent, 'approval_actions') ?? [];
110
- if (!approvalActions.includes(requiredAction)) {
111
- issues.push(commandContractIssue(`Agent-runnable git ${gitSubcommand} intent ${intentName} must include approval_actions = ["${requiredAction}"]`));
112
- }
113
- }
114
74
  function validatePositiveIntegerField(table, key, label, issues) {
115
75
  if (hasOwn(table, key) && !isPositiveInteger(table[key])) {
116
76
  issues.push(commandContractIssue(`${label} must be a positive integer`));
@@ -392,7 +352,6 @@ function validateCommandIntent(intentName, intent, allIntents, issues) {
392
352
  validateBooleanField(intent, 'allow_shell', `[commands.intents.${intentName}].allow_shell`, issues);
393
353
  validateStringArrayField(intent, 'env_allowlist', `[commands.intents.${intentName}].env_allowlist`, issues);
394
354
  validateApprovalActions(intentName, intent, issues);
395
- validateSensitiveGitApprovalActions(intentName, intent, issues);
396
355
  validateBooleanField(intent, ALLOW_ENV_INHERITANCE_RISKS_KEY, `[commands.intents.${intentName}].${ALLOW_ENV_INHERITANCE_RISKS_KEY}`, issues);
397
356
  validateBooleanField(intent, ALLOW_LONG_RUNNING_COMMAND_PATTERNS_KEY, `[commands.intents.${intentName}].${ALLOW_LONG_RUNNING_COMMAND_PATTERNS_KEY}`, issues);
398
357
  validateMaxOutputBytesField(intent, 'max_output_bytes', `[commands.intents.${intentName}].max_output_bytes`, issues);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mustflow",
3
- "version": "2.115.16",
3
+ "version": "2.115.17",
4
4
  "description": "Agent workflow documents and CLI for mustflow repository roots.",
5
5
  "type": "module",
6
6
  "license": "MIT-0",
@@ -1,6 +1,6 @@
1
1
  id = "default"
2
2
  name = "default"
3
- version = "2.115.16"
3
+ version = "2.115.17"
4
4
  description = "Minimal workflow for LLM agents to read, edit, and verify their work in a repository."
5
5
  common_root = "common"
6
6
  locales_root = "locales"