@tsuzuku/arise 1.0.1 → 1.1.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/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ const pkg = require('./package.json');
1
2
  const { parseArgs, showUsage } = require('./lib/cli');
2
3
  const { resolveConfiguration } = require('./lib/config');
3
4
  const { executeCreate } = require('./lib/lifecycle/create');
@@ -12,7 +13,7 @@ async function run(argv = process.argv.slice(2), cwd = process.cwd()) {
12
13
  }
13
14
 
14
15
  if (flags.showVersion) {
15
- console.log('arise v1.0.0');
16
+ console.log(`arise v${pkg.version}`);
16
17
  process.exit(0);
17
18
  }
18
19
 
package/lib/cli.js CHANGED
@@ -33,6 +33,7 @@ Agent Skill Arguments:
33
33
  --local, --workspace Install skill locally to current workspace (.agents/skills).
34
34
 
35
35
  General Arguments:
36
+ --yes, -y (Optional) Automatically answer yes to confirmation prompts (e.g. installing Herdr).
36
37
  --help, -h Show this help message.
37
38
  --version, -v Show version information.
38
39
  `);
@@ -45,6 +46,7 @@ function parseArgs(argv = process.argv.slice(2)) {
45
46
  dirOnly: false,
46
47
  keepRemote: false,
47
48
  force: false,
49
+ yes: false,
48
50
  branch: null,
49
51
  dirname: null,
50
52
  workspaceName: null,
@@ -84,6 +86,8 @@ function parseArgs(argv = process.argv.slice(2)) {
84
86
  flags.keepRemote = true;
85
87
  } else if (arg === '--force' || arg === '-f') {
86
88
  flags.force = true;
89
+ } else if (arg === '--yes' || arg === '-y') {
90
+ flags.yes = true;
87
91
  } else if (arg === '--branch' || arg === '-b') {
88
92
  flags.branch = argv[i + 1];
89
93
  i++;
package/lib/config.js CHANGED
@@ -70,7 +70,56 @@ function loadConfigFile(filePath) {
70
70
 
71
71
  function resolveConfiguration(flags = {}, cwd = process.cwd()) {
72
72
  const repoRoot = git.getRepoRootDir(cwd);
73
- const configFile = findConfigFile([cwd, repoRoot]);
73
+ const searchDirs = [];
74
+
75
+ const addSearchDir = (dir) => {
76
+ if (dir && !searchDirs.includes(dir)) {
77
+ searchDirs.push(dir);
78
+ }
79
+ };
80
+
81
+ let worktrees = [];
82
+ try {
83
+ worktrees = git.getWorktrees({ repoDir: repoRoot });
84
+ } catch (e) {}
85
+
86
+ // 1. Explicit directory if --dirname / -d is passed
87
+ if (flags.dirname) {
88
+ const resolvedDir = path.isAbsolute(flags.dirname)
89
+ ? flags.dirname
90
+ : path.resolve(repoRoot || cwd, flags.dirname);
91
+ addSearchDir(resolvedDir);
92
+ }
93
+
94
+ // 2. Directory for the specified branch (--branch / -b)
95
+ if (flags.branch) {
96
+ const matchingWt = worktrees.find((wt) => wt.branch === flags.branch);
97
+ if (matchingWt && matchingWt.path) {
98
+ addSearchDir(matchingWt.path);
99
+ }
100
+ const branchDir = path.resolve(repoRoot || cwd, flags.branch.replace(/\//g, '-'));
101
+ addSearchDir(branchDir);
102
+ }
103
+
104
+ // 3. Current working directory
105
+ addSearchDir(cwd);
106
+
107
+ // 4. Repository root directory
108
+ if (repoRoot) {
109
+ addSearchDir(repoRoot);
110
+ }
111
+
112
+ // 5. Fallback to existing worktrees (prioritizing primary branches like main, master, develop)
113
+ const primaryBranches = ['main', 'master', 'develop', 'prod', 'staging'];
114
+ const primaryWts = worktrees.filter((wt) => !wt.isBare && wt.branch && primaryBranches.includes(wt.branch));
115
+ for (const wt of primaryWts) {
116
+ if (wt.path) addSearchDir(wt.path);
117
+ }
118
+ for (const wt of worktrees) {
119
+ if (wt.path && !wt.isBare) addSearchDir(wt.path);
120
+ }
121
+
122
+ const configFile = findConfigFile(searchDirs);
74
123
  const fileConfig = loadConfigFile(configFile);
75
124
 
76
125
  // 1. Resolve Preset
@@ -80,7 +129,11 @@ function resolveConfiguration(flags = {}, cwd = process.cwd()) {
80
129
  preset = getPreset(presetName);
81
130
  }
82
131
  if (!preset) {
83
- preset = detectPreset(cwd);
132
+ const detectDir = (configFile && path.dirname(configFile)) || cwd;
133
+ preset = detectPreset(detectDir);
134
+ if (preset.name === 'generic' && detectDir !== cwd) {
135
+ preset = detectPreset(cwd);
136
+ }
84
137
  }
85
138
 
86
139
  // 2. Merge Repo Settings
package/lib/git.js CHANGED
@@ -7,6 +7,10 @@ function getGitPrefix(options = {}) {
7
7
  return `git --git-dir="${options.bareRepo}"`;
8
8
  }
9
9
  if (options.repoDir) {
10
+ const dotBare = path.join(options.repoDir, '.bare');
11
+ if (fs.existsSync(dotBare)) {
12
+ return `git --git-dir="${dotBare}"`;
13
+ }
10
14
  return `git -C "${options.repoDir}"`;
11
15
  }
12
16
  return 'git';
@@ -16,6 +20,10 @@ function getRepoRootDir(cwd = process.cwd(), bareRepo = null) {
16
20
  if (bareRepo && fs.existsSync(bareRepo)) {
17
21
  return bareRepo;
18
22
  }
23
+ const dotBare = path.join(cwd, '.bare');
24
+ if (fs.existsSync(dotBare)) {
25
+ return cwd;
26
+ }
19
27
  try {
20
28
  const commonDir = execSync('git rev-parse --git-common-dir', { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
21
29
  const absoluteCommonDir = path.isAbsolute(commonDir) ? commonDir : path.resolve(cwd, commonDir);
package/lib/herdr.js CHANGED
@@ -1,4 +1,101 @@
1
1
  const { execSync, spawnSync } = require('child_process');
2
+ const path = require('path');
3
+ const os = require('os');
4
+ const readline = require('readline');
5
+
6
+ function isCommandAvailable(cmd) {
7
+ try {
8
+ const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `command -v ${cmd}`;
9
+ execSync(checkCmd, { stdio: 'ignore' });
10
+ return true;
11
+ } catch {
12
+ return false;
13
+ }
14
+ }
15
+
16
+ function isHerdrInstalled() {
17
+ const localBin = path.join(os.homedir(), '.local', 'bin');
18
+ if (process.env.PATH && !process.env.PATH.split(path.delimiter).includes(localBin)) {
19
+ process.env.PATH = `${localBin}${path.delimiter}${process.env.PATH}`;
20
+ }
21
+ return isCommandAvailable('herdr');
22
+ }
23
+
24
+ function getRecommendedInstallCommand() {
25
+ if (process.platform === 'darwin' && isCommandAvailable('brew')) {
26
+ return {
27
+ name: 'Homebrew',
28
+ cmd: 'brew install herdr',
29
+ docsUrl: 'https://herdr.dev/docs/install/#install-with-homebrew',
30
+ };
31
+ }
32
+ if (isCommandAvailable('mise')) {
33
+ return {
34
+ name: 'mise',
35
+ cmd: 'mise use -g herdr',
36
+ docsUrl: 'https://herdr.dev/docs/install/#install-with-mise',
37
+ };
38
+ }
39
+ if (process.platform === 'win32') {
40
+ return {
41
+ name: 'PowerShell Installer',
42
+ cmd: 'powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex"',
43
+ docsUrl: 'https://herdr.dev/docs/install/',
44
+ };
45
+ }
46
+ return {
47
+ name: 'Official Install Script',
48
+ cmd: 'curl -fsSL https://herdr.dev/install.sh | sh',
49
+ docsUrl: 'https://herdr.dev/docs/install/',
50
+ };
51
+ }
52
+
53
+ function promptUser(question) {
54
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
55
+ return new Promise((resolve) => {
56
+ rl.question(question, (answer) => {
57
+ rl.close();
58
+ resolve(answer.trim());
59
+ });
60
+ });
61
+ }
62
+
63
+ async function ensureHerdrInstalled(options = {}) {
64
+ if (isHerdrInstalled()) {
65
+ return true;
66
+ }
67
+
68
+ const { name, cmd, docsUrl } = getRecommendedInstallCommand();
69
+ const autoConfirm = Boolean(options.yes);
70
+
71
+ if (!autoConfirm && (!process.stdin.isTTY || process.env.CI)) {
72
+ console.error(`\n[arise] Error: "herdr" is required to manage terminal workspaces but was not found in PATH.`);
73
+ console.error(`Please install Herdr before running arise:\n ${cmd}\n`);
74
+ console.error(`Docs: ${docsUrl || 'https://herdr.dev/docs/install/'}`);
75
+ process.exit(1);
76
+ }
77
+
78
+ if (!autoConfirm) {
79
+ console.log(`\n[arise] "herdr" is required to manage terminal workspaces but was not found in PATH.`);
80
+ const answer = await promptUser(`Would you like arise to install Herdr now via ${name} (\`${cmd}\`)? [Y/n]: `);
81
+ if (answer && !/^(y|yes)$/i.test(answer)) {
82
+ console.error('\nCannot proceed without Herdr. Aborting.');
83
+ process.exit(1);
84
+ }
85
+ }
86
+
87
+ console.log(`\n==> Installing Herdr via ${name}...`);
88
+ const result = spawnSync(cmd, { stdio: 'inherit', shell: true });
89
+
90
+ if (result.status !== 0 || !isHerdrInstalled()) {
91
+ console.error(`\n[arise] Failed to automatically install Herdr.`);
92
+ console.error(`Please visit https://herdr.dev/docs/install/ to install manually.`);
93
+ process.exit(1);
94
+ }
95
+
96
+ console.log(`[arise] Herdr installed successfully!\n`);
97
+ return true;
98
+ }
2
99
 
3
100
  function parseJsonFromOutput(output) {
4
101
  if (!output) return null;
@@ -105,6 +202,9 @@ function attachOrSwitchSession(sessionName) {
105
202
  }
106
203
 
107
204
  module.exports = {
205
+ isHerdrInstalled,
206
+ getRecommendedInstallCommand,
207
+ ensureHerdrInstalled,
108
208
  listWorkspaces,
109
209
  createWorkspace,
110
210
  closeWorkspace,
@@ -4,6 +4,7 @@ const git = require('../git');
4
4
  const herdr = require('../herdr');
5
5
  const layout = require('../layout');
6
6
  const { createContext } = require('../context');
7
+ const { resolveConfiguration } = require('../config');
7
8
  const { showUsage } = require('../cli');
8
9
 
9
10
  async function executeCreate(flags, config, cwd = process.cwd()) {
@@ -24,8 +25,8 @@ async function executeCreate(flags, config, cwd = process.cwd()) {
24
25
 
25
26
  // 2. Resolve Session / Workspace Name
26
27
  const baseWorkspace = flags.workspaceName || dirname.replace(/[\s.:]/g, '_');
27
- const prefix = config.workspace.labelPrefix || '';
28
- const sessionName = (prefix && !baseWorkspace.startsWith(prefix.trim()))
28
+ let prefix = config.workspace.labelPrefix || '';
29
+ let sessionName = (prefix && !baseWorkspace.startsWith(prefix.trim()))
29
30
  ? `${prefix}${baseWorkspace}`
30
31
  : baseWorkspace;
31
32
 
@@ -69,28 +70,37 @@ async function executeCreate(flags, config, cwd = process.cwd()) {
69
70
  }
70
71
  }
71
72
 
72
- // 5. Initialize Context for Hooks
73
+ // 5. Re-resolve config using target worktree directory for branch-specific overrides
74
+ const activeConfig = resolveConfiguration(flags, worktreePathToUse);
75
+ prefix = activeConfig.workspace.labelPrefix || '';
76
+ sessionName = (prefix && !baseWorkspace.startsWith(prefix.trim()))
77
+ ? `${prefix}${baseWorkspace}`
78
+ : baseWorkspace;
79
+
80
+ // Initialize Context for Hooks
73
81
  const ctx = createContext({
74
82
  worktreePath: worktreePathToUse,
75
83
  repoRoot,
76
- bareRepo: config.repo.bareRepo,
84
+ bareRepo: activeConfig.repo.bareRepo,
77
85
  branch,
78
- source: flags.source || config.repo.defaultBaseBranch,
86
+ source: flags.source || activeConfig.repo.defaultBaseBranch,
79
87
  flags,
80
- preset: config.preset,
81
- config,
88
+ preset: activeConfig.preset,
89
+ config: activeConfig,
82
90
  });
83
91
 
84
92
  // 6. Run Preset / Config Hooks
85
- if (typeof config.hooks.onSyncPrimary === 'function') {
86
- await config.hooks.onSyncPrimary(ctx);
93
+ if (typeof activeConfig.hooks.onSyncPrimary === 'function') {
94
+ await activeConfig.hooks.onSyncPrimary(ctx);
87
95
  }
88
96
 
89
- if (!worktreeExists && typeof config.hooks.onScaffold === 'function') {
90
- await config.hooks.onScaffold(ctx);
97
+ if (!worktreeExists && typeof activeConfig.hooks.onScaffold === 'function') {
98
+ await activeConfig.hooks.onScaffold(ctx);
91
99
  }
92
100
 
93
101
  // 7. Orchestrate Herdr Workspace
102
+ await herdr.ensureHerdrInstalled({ yes: flags.yes });
103
+
94
104
  console.log(`\n==> Creating Herdr workspace "${sessionName}"...`);
95
105
  let ws;
96
106
  try {
@@ -103,10 +113,10 @@ async function executeCreate(flags, config, cwd = process.cwd()) {
103
113
  // 8. Render Terminal Layout
104
114
  console.log(`==> Configuring terminal panes...`);
105
115
  layout.renderLayout({
106
- layout: config.layout,
116
+ layout: activeConfig.layout,
107
117
  rootPaneId: ws.rootPaneId,
108
118
  cwd: worktreePathToUse,
109
- focusTarget: flags.focusTarget || config.workspace.defaultFocus,
119
+ focusTarget: flags.focusTarget || activeConfig.workspace.defaultFocus,
110
120
  });
111
121
 
112
122
  // Focus the workspace
@@ -4,6 +4,7 @@ const { execSync } = require('child_process');
4
4
  const git = require('../git');
5
5
  const herdr = require('../herdr');
6
6
  const { createContext } = require('../context');
7
+ const { resolveConfiguration } = require('../config');
7
8
  const { showUsage } = require('../cli');
8
9
 
9
10
  async function executeNuke(flags, config, cwd = process.cwd()) {
@@ -50,6 +51,10 @@ async function executeNuke(flags, config, cwd = process.cwd()) {
50
51
  const targetDirname = path.basename(targetWorktreePath);
51
52
  const targetSessionName = targetDirname.replace(/[\s.:]/g, '_');
52
53
 
54
+ const activeConfig = fs.existsSync(targetWorktreePath)
55
+ ? resolveConfiguration(flags, targetWorktreePath)
56
+ : config;
57
+
53
58
  let targetBranch = flags.branch;
54
59
  if (!targetBranch && existingWorktree && existingWorktree.branch) {
55
60
  targetBranch = existingWorktree.branch;
@@ -64,14 +69,14 @@ async function executeNuke(flags, config, cwd = process.cwd()) {
64
69
  }
65
70
  if (!targetBranch) {
66
71
  try {
67
- const gitCmd = git.getGitPrefix({ repoDir: repoRoot, bareRepo: config.repo.bareRepo });
72
+ const gitCmd = git.getGitPrefix({ repoDir: repoRoot, bareRepo: activeConfig.repo.bareRepo });
68
73
  execSync(`${gitCmd} rev-parse --verify "${target}"`, { stdio: 'ignore' });
69
74
  targetBranch = target;
70
75
  } catch (e) {}
71
76
  }
72
77
 
73
78
  console.log(`\n=== Starting Worktree Nuke ===`);
74
- console.log(`Active Preset: ${config.preset ? config.preset.name : 'generic'}`);
79
+ console.log(`Active Preset: ${activeConfig.preset ? activeConfig.preset.name : 'generic'}`);
75
80
  console.log(`Repository Root: ${repoRoot}`);
76
81
  console.log(`Target Worktree Path: ${targetWorktreePath}`);
77
82
  console.log(`Associated Branch: ${targetBranch || '(None detected)'}`);
@@ -96,16 +101,16 @@ async function executeNuke(flags, config, cwd = process.cwd()) {
96
101
  const ctx = createContext({
97
102
  worktreePath: targetWorktreePath,
98
103
  repoRoot,
99
- bareRepo: config.repo.bareRepo,
104
+ bareRepo: activeConfig.repo.bareRepo,
100
105
  branch: targetBranch,
101
106
  flags,
102
- preset: config.preset,
103
- config,
107
+ preset: activeConfig.preset,
108
+ config: activeConfig,
104
109
  });
105
110
 
106
111
  // Pre-Nuke Hook
107
- if (typeof config.hooks.onPreNuke === 'function') {
108
- await config.hooks.onPreNuke(ctx);
112
+ if (typeof activeConfig.hooks.onPreNuke === 'function') {
113
+ await activeConfig.hooks.onPreNuke(ctx);
109
114
  }
110
115
 
111
116
  // 1. Remove Worktree & Directory
@@ -139,12 +144,12 @@ async function executeNuke(flags, config, cwd = process.cwd()) {
139
144
  // Helper for final cleanup steps (Herdr workspace close + Post-Nuke hook)
140
145
  const finishCleanup = async () => {
141
146
  // Post-Nuke Hook
142
- if (typeof config.hooks.onPostNuke === 'function') {
143
- await config.hooks.onPostNuke(ctx);
147
+ if (typeof activeConfig.hooks.onPostNuke === 'function') {
148
+ await activeConfig.hooks.onPostNuke(ctx);
144
149
  }
145
150
 
146
151
  // Close Herdr Workspace if running (performed last so active pane is not terminated mid-cleanup)
147
- const prefix = config.workspace.labelPrefix || '';
152
+ const prefix = activeConfig.workspace.labelPrefix || '';
148
153
  const matchTargets = [
149
154
  targetSessionName,
150
155
  targetDirname,
@@ -165,7 +170,7 @@ async function executeNuke(flags, config, cwd = process.cwd()) {
165
170
  return;
166
171
  }
167
172
 
168
- const protectedBranches = config.repo.protectedBranches || ['main', 'master', 'develop', 'prod', 'staging', 'production'];
173
+ const protectedBranches = activeConfig.repo.protectedBranches || ['main', 'master', 'develop', 'prod', 'staging', 'production'];
169
174
  if (targetBranch && protectedBranches.includes(targetBranch)) {
170
175
  console.warn(`\n==> WARNING: "${targetBranch}" is a protected branch. Skipping local and remote branch deletion.`);
171
176
  await finishCleanup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsuzuku/arise",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -20,7 +20,6 @@
20
20
  "index.js",
21
21
  "types.d.ts",
22
22
  "arise.schema.json",
23
- "worktree.schema.json",
24
23
  "README.md"
25
24
  ],
26
25
  "engines": {
package/types.d.ts CHANGED
@@ -11,6 +11,7 @@ export interface CliFlags {
11
11
  dirOnly: boolean;
12
12
  keepRemote: boolean;
13
13
  force: boolean;
14
+ yes: boolean;
14
15
  branch: string | null;
15
16
  dirname: string | null;
16
17
  workspaceName: string | null;
@@ -1,130 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "title": "HerdrWorktreeConfig",
4
- "description": "Configuration schema for Herdr Worktree (.worktreerc.json)",
5
- "type": "object",
6
- "properties": {
7
- "preset": {
8
- "type": "string",
9
- "description": "Preset name to use ('node', 'laravel', 'generic' or custom registered preset)"
10
- },
11
- "repo": {
12
- "type": "object",
13
- "description": "Repository topology and branch configuration",
14
- "properties": {
15
- "bareRepo": {
16
- "type": ["string", "null"],
17
- "description": "Path to bare git repository (e.g. '/path/to/bare/repo.git')"
18
- },
19
- "worktreesBase": {
20
- "type": ["string", "null"],
21
- "description": "Base directory where worktrees should be placed (e.g. '/path/to/worktrees')"
22
- },
23
- "defaultBaseBranch": {
24
- "type": "string",
25
- "description": "Default base branch to branch off (e.g. 'develop', 'prod', 'main')"
26
- },
27
- "protectedBranches": {
28
- "type": "array",
29
- "items": { "type": "string" },
30
- "description": "Array of branch names protected against deletion during --nuke"
31
- }
32
- },
33
- "additionalProperties": false
34
- },
35
- "workspace": {
36
- "type": "object",
37
- "description": "Herdr workspace naming, agent, and focus configuration",
38
- "properties": {
39
- "labelPrefix": {
40
- "type": "string",
41
- "description": "Prefix added to Herdr workspace labels (e.g. '[BE] ')"
42
- },
43
- "agent": {
44
- "type": ["string", "object", "null"],
45
- "description": "CLI AI agent to run in the workspace pane ('agy', 'claude', 'aider', 'copilot', 'none', or custom command object)",
46
- "properties": {
47
- "cmd": {
48
- "type": ["string", "null"],
49
- "description": "Command to execute the agent"
50
- },
51
- "title": {
52
- "type": "string",
53
- "description": "Display title for the agent pane in Herdr"
54
- }
55
- }
56
- },
57
- "defaultFocus": {
58
- "type": "string",
59
- "description": "Default pane to focus upon creation ('agent', 'agy', 'claude', 'vim', 'logs', 'server', 'shell')"
60
- }
61
- },
62
- "additionalProperties": false
63
- },
64
- "layout": {
65
- "type": "array",
66
- "description": "Declarative 4-pane quadrant layout definitions",
67
- "items": {
68
- "type": "object",
69
- "required": ["id", "title"],
70
- "properties": {
71
- "id": {
72
- "type": "string",
73
- "description": "Unique identifier for this pane within the layout"
74
- },
75
- "title": {
76
- "type": "string",
77
- "description": "Title displayed on the Herdr pane"
78
- },
79
- "cmd": {
80
- "type": ["string", "null"],
81
- "description": "Command to run when pane is opened (e.g. 'vim .', 'npm run dev', 'tail -f ...')"
82
- },
83
- "position": {
84
- "type": "string",
85
- "enum": ["root"],
86
- "description": "Set to 'root' for the initial root pane"
87
- },
88
- "from": {
89
- "type": "string",
90
- "description": "ID of parent pane to split from"
91
- },
92
- "split": {
93
- "type": "string",
94
- "enum": ["right", "down"],
95
- "description": "Split direction ('right' or 'down')"
96
- },
97
- "focus": {
98
- "type": "boolean",
99
- "description": "Whether this pane should receive focus by default"
100
- },
101
- "isAgent": {
102
- "type": "boolean",
103
- "description": "Whether this pane is designated as the AI CLI agent pane"
104
- }
105
- },
106
- "additionalProperties": false
107
- }
108
- },
109
- "scaffold": {
110
- "type": "object",
111
- "description": "Scaffolding options (environment files, symlinks, dependency installation, etc.)",
112
- "properties": {
113
- "envSource": {
114
- "type": ["string", "null"],
115
- "description": "Path to .env source file to copy into new worktree"
116
- },
117
- "symlink": {
118
- "type": ["string", "null"],
119
- "description": "Path to web server symlink to update to active worktree"
120
- },
121
- "install": {
122
- "type": ["string", "boolean", "null"],
123
- "description": "Command to run to install dependencies upon creation (e.g. 'npm install --legacy-peer-deps', 'pnpm install', 'composer install --no-interaction'), or false/null to skip installation."
124
- }
125
- },
126
- "additionalProperties": true
127
- }
128
- },
129
- "additionalProperties": false
130
- }