ace-support-cli 0.6.9 → 0.6.10
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +25 -0
- data/lib/ace/support/cli/runner.rb +5 -0
- data/lib/ace/support/cli/toolchain.rb +112 -0
- data/lib/ace/support/cli/version.rb +1 -1
- data/lib/ace/support/cli.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 97fff71bfa5c46c0a82bae86872692ae5488919550b2c0c9afce4e4385a5bc64
|
|
4
|
+
data.tar.gz: c6e73139b02112a21a917af26942365a1ffcae3687990a643382a335c0b6fcc6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a8e8bef070892011cd79dbab1b679f6d7362921e294752869d5801c2c7c1e65019897ee5f0f14dbfbbbc3280cf1230a68f82f2d3b3a9b761096b51b7f9893f4
|
|
7
|
+
data.tar.gz: 79687ddb896af4f69e20a9506c586df519486c632ef3a346aa0c5ae20fdd5d6dc8e3871d46efe4b3d82feb0751ab6a6002de39d487304ce9b9cf89ed3138fc44
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.6.10] - 2026-10-20
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Explicit installed toolchain policy: installed executable selection, loaded closure verification, child environment and runtime-origin evidence. Default auto preserves source development.
|
|
11
|
+
|
|
7
12
|
## [0.6.9] - 2026-09-29
|
|
8
13
|
|
|
9
14
|
### Fixed
|
data/README.md
CHANGED
|
@@ -45,3 +45,28 @@ Verification commands:
|
|
|
45
45
|
---
|
|
46
46
|
|
|
47
47
|
Part of [ACE](https://github.com/cs3b/ace)
|
|
48
|
+
|
|
49
|
+
## Installed toolchain
|
|
50
|
+
|
|
51
|
+
`ACE_TOOLCHAIN=installed` selects installed RubyGems executables and rejects a
|
|
52
|
+
loaded path-gem closure. The default `auto` keeps source development. Shared
|
|
53
|
+
`Ace::Support::Cli::Toolchain` resolves executables, cleans Bundler/Ruby source
|
|
54
|
+
injection from child environments, supplies post-shell startup environment for
|
|
55
|
+
Herdr and reports loaded gem origins. It does not grant permissions or replace
|
|
56
|
+
project domain configuration.
|
|
57
|
+
|
|
58
|
+
Installed navigation uses packaged protocol definitions and generic document
|
|
59
|
+
sources; Assign excludes `skill_source_paths`, `workflow_source_paths` and
|
|
60
|
+
repository package discovery in this mode. Coworker briefs expose the selected
|
|
61
|
+
mode and document origin. Missing installed dependencies fail rather than using
|
|
62
|
+
project binstubs. The flag is an execution policy, not a sandbox against code
|
|
63
|
+
that deliberately clears it.
|
|
64
|
+
|
|
65
|
+
For a user-owned installed runtime, start from its Ruby/GEM_HOME/GEM_PATH and run
|
|
66
|
+
`ACE_TOOLCHAIN=installed ace-coworker start --config <project-run-config> --format json`.
|
|
67
|
+
Inspect `toolchain.mode`, loaded gem paths/versions and `instructions_source`;
|
|
68
|
+
`which` alone is not loaded-closure evidence. Commissioned installed runs retain
|
|
69
|
+
`toolchain: installed` in their existing run config; source-mode resume is rejected.
|
|
70
|
+
Herdr installs the selected Ruby/gem environment after shell startup, including
|
|
71
|
+
reused shell panes. Changing an already-running agent's environment is not
|
|
72
|
+
supported: start a fresh executor with the selected toolchain instead.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "parser"
|
|
4
|
+
require_relative "toolchain"
|
|
4
5
|
|
|
5
6
|
module Ace
|
|
6
7
|
module Support
|
|
@@ -12,6 +13,7 @@ module Ace
|
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def call(args: ARGV)
|
|
16
|
+
Toolchain.verify_loaded!
|
|
15
17
|
if root_help_request?(args)
|
|
16
18
|
puts Ace::Support::Cli::Help::Usage.new(@registry, program_name: resolve_program_name).render
|
|
17
19
|
return 0
|
|
@@ -20,6 +22,7 @@ module Ace
|
|
|
20
22
|
command_target, remaining, command_name = resolve_target(args)
|
|
21
23
|
command_class = command_target.is_a?(Class) ? command_target : command_target.class
|
|
22
24
|
parsed = @parser_class.new(command_class, command_name: command_name).parse(remaining)
|
|
25
|
+
Toolchain.verify_loaded!
|
|
23
26
|
result = if command_target.is_a?(Class)
|
|
24
27
|
command_target.new.call(**parsed)
|
|
25
28
|
else
|
|
@@ -33,6 +36,8 @@ module Ace
|
|
|
33
36
|
raise Ace::Support::Cli::Error.new(e.message)
|
|
34
37
|
rescue Ace::Support::Cli::CommandNotFoundError => e
|
|
35
38
|
raise Ace::Support::Cli::Error.new(e.message)
|
|
39
|
+
rescue Toolchain::Error => e
|
|
40
|
+
raise Ace::Support::Cli::Error.new(e.message)
|
|
36
41
|
end
|
|
37
42
|
|
|
38
43
|
private
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rubygems"
|
|
4
|
+
require "shellwords"
|
|
5
|
+
|
|
6
|
+
module Ace
|
|
7
|
+
module Support
|
|
8
|
+
module Cli
|
|
9
|
+
# Selection policy, not authority: project data/configuration remain usable.
|
|
10
|
+
module Toolchain
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def installed?
|
|
16
|
+
mode = ENV.fetch("ACE_TOOLCHAIN", "auto")
|
|
17
|
+
raise Error, "unknown ACE_TOOLCHAIN #{mode.inspect}; use auto or installed" unless %w[auto installed].include?(mode)
|
|
18
|
+
|
|
19
|
+
mode == "installed"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def installed_spec?(spec)
|
|
23
|
+
return false unless spec.loaded_from && File.file?(spec.loaded_from)
|
|
24
|
+
|
|
25
|
+
root = File.realpath(spec.base_dir)
|
|
26
|
+
gem_path = File.realpath(spec.full_gem_path)
|
|
27
|
+
specification = File.realpath(spec.loaded_from)
|
|
28
|
+
gem_path.start_with?("#{root}/gems/") &&
|
|
29
|
+
specification.start_with?("#{root}/specifications/")
|
|
30
|
+
rescue Errno::ENOENT
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def verify_loaded!
|
|
35
|
+
return unless installed?
|
|
36
|
+
|
|
37
|
+
Gem.loaded_specs.each_value do |spec|
|
|
38
|
+
next if installed_spec?(spec) || spec.default_gem?
|
|
39
|
+
|
|
40
|
+
raise Error, "installed toolchain loaded source dependency #{spec.name}: #{spec.full_gem_path}"
|
|
41
|
+
end
|
|
42
|
+
roots = Gem.loaded_specs.values.select { |spec| installed_spec?(spec) }
|
|
43
|
+
.map { |spec| "#{File.realpath(spec.full_gem_path)}/" }
|
|
44
|
+
$LOADED_FEATURES.grep(%r{/lib/ace/}).each do |feature|
|
|
45
|
+
actual = File.realpath(feature)
|
|
46
|
+
next if roots.any? { |root| actual.start_with?(root) }
|
|
47
|
+
|
|
48
|
+
raise Error, "installed toolchain loaded source code outside its gem closure: #{actual}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def executable(name, project_root: nil, prefer_project: true)
|
|
53
|
+
unless installed?
|
|
54
|
+
candidate = File.join(project_root, "bin", name) if project_root && prefer_project
|
|
55
|
+
return candidate if candidate && File.executable?(candidate)
|
|
56
|
+
|
|
57
|
+
return name
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
verify_loaded!
|
|
61
|
+
spec = Gem::Specification.find_all.select do |entry|
|
|
62
|
+
entry.executables.include?(name) && installed_spec?(entry)
|
|
63
|
+
end.max_by(&:version)
|
|
64
|
+
raise Error, "installed executable #{name} unavailable; install its published gem" unless spec
|
|
65
|
+
|
|
66
|
+
path = File.join(spec.full_gem_path, spec.bindir, name)
|
|
67
|
+
unless File.executable?(path) && File.realpath(path).start_with?("#{File.realpath(spec.full_gem_path)}/")
|
|
68
|
+
raise Error, "installed executable #{name} missing or outside its gem: #{path}"
|
|
69
|
+
end
|
|
70
|
+
path
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Bundler/Ruby source injection must not leak into subprocesses. Domain
|
|
74
|
+
# environment (including credentials) is inherited, never inspected here.
|
|
75
|
+
def child_environment
|
|
76
|
+
return {} unless installed?
|
|
77
|
+
|
|
78
|
+
ENV.keys.grep(/\ABUNDLER?_/).to_h { |key| [key, nil] }.merge(
|
|
79
|
+
"RUBYOPT" => nil, "RUBYLIB" => nil, "ACE_TOOLCHAIN" => "installed",
|
|
80
|
+
"GEM_HOME" => Gem.dir, "GEM_PATH" => Gem.path.join(File::PATH_SEPARATOR),
|
|
81
|
+
"PATH" => [Gem.bindir, File.dirname(Gem.ruby), ENV.fetch("PATH", "")].join(File::PATH_SEPARATOR)
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def shell_setup
|
|
86
|
+
return "" unless installed?
|
|
87
|
+
|
|
88
|
+
names = (ENV.keys.grep(/\ABUNDLER?_/) +
|
|
89
|
+
%w[BUNDLE_GEMFILE BUNDLE_PATH BUNDLE_BIN_PATH BUNDLER_SETUP RUBYOPT RUBYLIB]).uniq
|
|
90
|
+
path = [Gem.bindir, File.dirname(Gem.ruby), ENV.fetch("PATH", "")].join(File::PATH_SEPARATOR)
|
|
91
|
+
values = {"ACE_TOOLCHAIN" => "installed", "GEM_HOME" => Gem.dir,
|
|
92
|
+
"GEM_PATH" => Gem.path.join(File::PATH_SEPARATOR), "PATH" => path}
|
|
93
|
+
"unset #{names.map { |name| Shellwords.escape(name) }.join(" ")}; export " +
|
|
94
|
+
values.map { |name, value| "#{name}=#{Shellwords.escape(value)}" }.join(" ") + "; "
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def shell_command(name, *args)
|
|
98
|
+
shell_setup + Shellwords.join([executable(name), *args])
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def evidence
|
|
102
|
+
{"mode" => installed? ? "installed" : "auto",
|
|
103
|
+
"gems" => Gem.loaded_specs.values.select { |spec| spec.name.start_with?("ace-") }
|
|
104
|
+
.to_h do |spec|
|
|
105
|
+
[spec.name, {"version" => spec.version.to_s, "path" => spec.full_gem_path,
|
|
106
|
+
"executables" => spec.executables.to_h { |name| [name, File.join(spec.full_gem_path, spec.bindir, name)] }}]
|
|
107
|
+
end}
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
data/lib/ace/support/cli.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ace-support-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michal Czyz
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-10-20 00:00:00.000000000 Z
|
|
11
11
|
dependencies: []
|
|
12
12
|
description: Provides command DSL, option parsing, registry routing, and runner primitives
|
|
13
13
|
for ACE CLI tools.
|
|
@@ -42,6 +42,7 @@ files:
|
|
|
42
42
|
- lib/ace/support/cli/registry_dsl.rb
|
|
43
43
|
- lib/ace/support/cli/runner.rb
|
|
44
44
|
- lib/ace/support/cli/standard_options.rb
|
|
45
|
+
- lib/ace/support/cli/toolchain.rb
|
|
45
46
|
- lib/ace/support/cli/version.rb
|
|
46
47
|
homepage: https://github.com/cs3b/ace
|
|
47
48
|
licenses:
|