hiiro 0.1.337 → 0.1.338
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 -69
- data/bin/h-registry +98 -23
- data/lib/hiiro/db.rb +2 -0
- data/lib/hiiro/registry.rb +62 -5
- data/lib/hiiro/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 92203914806a439748cb5f3020d0784c253e3a1ac91bebf786a2115c9aa3b0d4
|
|
4
|
+
data.tar.gz: 665b26d833fd387edf53814df50d6289e8dea59b56abc97ba485ed0ab169ad71
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ceb994131ac83201c806910f87099df9e1cfbea8ffd91d5fcf15221c64ee153af859a40eb7dc36553cd5f4fd1c690f2123415b933676656fb5d70af54359f608
|
|
7
|
+
data.tar.gz: 5c3f66a48df5269d6d383030c8e46a88a87b451bcca5fdbf1c53fd0aebc7d437810815f616cdd70d9df0e20132c5482425555292b932694825f4972118f677ee
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.338] - 2026-04-07
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Renamed `registry_entries` table to `registry` (auto-migrates existing data)
|
|
7
|
+
|
|
3
8
|
## [0.1.337] - 2026-04-06
|
|
4
9
|
|
|
5
10
|
### Changed
|
|
@@ -312,72 +317,3 @@
|
|
|
312
317
|
- `bin/h-pane` — load/save pane homes via `Hiiro::PaneHome` model with YAML dual-write
|
|
313
318
|
- `bin/h-pr` — adds `q`/`query` subcommands for inspecting PR records via raw SQL
|
|
314
319
|
- `plugins/pins.rb` — `Pin` class reads/writes via `Hiiro::PinRecord` SQLite model with YAML dual-write fallback
|
|
315
|
-
|
|
316
|
-
## [0.1.306] - 2026-03-30
|
|
317
|
-
|
|
318
|
-
### Changed
|
|
319
|
-
- Increase delayed_update sleep duration from 5s to 15s
|
|
320
|
-
- Add logging for delayed_update invocation in publish script
|
|
321
|
-
|
|
322
|
-
## [0.1.305] - 2026-03-30
|
|
323
|
-
|
|
324
|
-
### Changed
|
|
325
|
-
- Refactor: use delayed_update subcommand instead of direct update call
|
|
326
|
-
- Improve gem version matching regex in version check
|
|
327
|
-
|
|
328
|
-
## [0.1.304] - 2026-03-30
|
|
329
|
-
|
|
330
|
-
### Changed
|
|
331
|
-
- h-notify: use universal log instead of per-session logging
|
|
332
|
-
- Todo output simplified
|
|
333
|
-
|
|
334
|
-
## [0.1.302] - 2026-03-30
|
|
335
|
-
|
|
336
|
-
### Fixed
|
|
337
|
-
- Truncate output lines to terminal width in tasks plugin
|
|
338
|
-
|
|
339
|
-
## [0.1.301]
|
|
340
|
-
|
|
341
|
-
### Added
|
|
342
|
-
- Check version delayed update functionality
|
|
343
|
-
|
|
344
|
-
### Changed
|
|
345
|
-
- h-claude: add verbose flags and refactor glob_path handling
|
|
346
|
-
|
|
347
|
-
### Fixed
|
|
348
|
-
- Use exact session matching to prevent tmux prefix ambiguity
|
|
349
|
-
|
|
350
|
-
## [0.1.300]
|
|
351
|
-
|
|
352
|
-
### Added
|
|
353
|
-
- h-claude: fulltext search option for agents/commands/skills
|
|
354
|
-
|
|
355
|
-
### Changed
|
|
356
|
-
- Refactor h-claude directory traversal and file globbing
|
|
357
|
-
|
|
358
|
-
## [0.1.299]
|
|
359
|
-
|
|
360
|
-
### Added
|
|
361
|
-
- h-pr open: support opening multiple PRs
|
|
362
|
-
|
|
363
|
-
## [0.1.298]
|
|
364
|
-
|
|
365
|
-
### Changed
|
|
366
|
-
- Use Pathname to walk up directory tree
|
|
367
|
-
- h-claude agents/commands/skills walk from pwd up to home
|
|
368
|
-
|
|
369
|
-
## [0.1.297]
|
|
370
|
-
|
|
371
|
-
### Added
|
|
372
|
-
- h rnext subcommand
|
|
373
|
-
|
|
374
|
-
## [0.1.296]
|
|
375
|
-
|
|
376
|
-
### Changed
|
|
377
|
-
- Refactor PR filter logic to pinned_pr_manager
|
|
378
|
-
- Move PR filter logic to Pr#matches_filters?
|
|
379
|
-
|
|
380
|
-
## [0.1.295]
|
|
381
|
-
|
|
382
|
-
### Changed
|
|
383
|
-
- Filter logic changes for PR management
|
data/bin/h-registry
CHANGED
|
@@ -21,8 +21,9 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
21
21
|
puts '─' * 40
|
|
22
22
|
end
|
|
23
23
|
alias_col = e.short_name ? "[#{e.short_name}]".ljust(18) : ' ' * 18
|
|
24
|
+
value_col = e.value ? " = #{e.value}" : ''
|
|
24
25
|
desc_col = e.description ? " # #{e.description}" : ''
|
|
25
|
-
puts " #{alias_col} #{e.name}#{desc_col}"
|
|
26
|
+
puts " #{alias_col} #{e.name}#{value_col}#{desc_col}"
|
|
26
27
|
end
|
|
27
28
|
puts
|
|
28
29
|
end
|
|
@@ -33,10 +34,10 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
33
34
|
puts types.empty? ? "No types registered yet." : types.join("\n")
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
# h registry add <type> <name> [--alias <short>] [--desc <description>]
|
|
37
|
+
# h registry add <type> <name> [value] [--alias <short>] [--desc <description>]
|
|
37
38
|
add_subcmd(:add) do |type, name, *rest|
|
|
38
39
|
unless type && name
|
|
39
|
-
puts "Usage: h registry add <type> <name> [--alias <short>] [--desc <text>]"
|
|
40
|
+
puts "Usage: h registry add <type> <name> [value] [--alias <short>] [--desc <text>]"
|
|
40
41
|
next
|
|
41
42
|
end
|
|
42
43
|
opts = Hiiro::Options.setup {
|
|
@@ -44,6 +45,9 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
44
45
|
option(:desc, short: :d, desc: 'Description')
|
|
45
46
|
}.parse(rest)
|
|
46
47
|
|
|
48
|
+
# First positional arg after name is the value
|
|
49
|
+
value = opts.args.first
|
|
50
|
+
|
|
47
51
|
existing = Hiiro::RegistryEntry.find_by_ref(name, type: type)
|
|
48
52
|
if existing
|
|
49
53
|
puts "Already registered: #{existing.display}"
|
|
@@ -53,6 +57,7 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
53
57
|
entry = Hiiro::RegistryEntry.create(
|
|
54
58
|
resource_type: type,
|
|
55
59
|
name: name,
|
|
60
|
+
value: value,
|
|
56
61
|
short_name: opts.alias,
|
|
57
62
|
description: opts.desc,
|
|
58
63
|
created_at: Time.now.iso8601
|
|
@@ -60,15 +65,26 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
60
65
|
puts "Added:\n#{entry.display}"
|
|
61
66
|
end
|
|
62
67
|
|
|
63
|
-
# h registry rm <name_or_alias> [type]
|
|
64
|
-
add_subcmd(:rm, :remove) do |
|
|
68
|
+
# h registry rm <name_or_alias> [type] [-s]
|
|
69
|
+
add_subcmd(:rm, :remove) do |*args|
|
|
70
|
+
opts = Hiiro::Options.setup {
|
|
71
|
+
option(:substring, short: :s, type: :flag, desc: 'Match substring anywhere in name')
|
|
72
|
+
}.parse(args)
|
|
73
|
+
|
|
74
|
+
ref, type = opts.args
|
|
65
75
|
unless ref
|
|
66
|
-
puts "Usage: h registry rm <name_or_alias> [type]"
|
|
76
|
+
puts "Usage: h registry rm <name_or_alias> [type] [-s]"
|
|
67
77
|
next
|
|
68
78
|
end
|
|
69
|
-
entry = Hiiro::RegistryEntry.find_by_ref(ref, type: type
|
|
79
|
+
entry = Hiiro::RegistryEntry.find_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
70
80
|
unless entry
|
|
71
|
-
|
|
81
|
+
matches = Hiiro::RegistryEntry.find_all_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
82
|
+
if matches.any?
|
|
83
|
+
puts "Ambiguous match '#{ref}' - #{matches.size} entries:"
|
|
84
|
+
matches.each { |e| puts " #{e.resource_type}/#{e.name}" }
|
|
85
|
+
else
|
|
86
|
+
puts "Not found: #{ref}#{type ? " (type: #{type})" : ''}"
|
|
87
|
+
end
|
|
72
88
|
next
|
|
73
89
|
end
|
|
74
90
|
puts "Removing: #{entry.display}"
|
|
@@ -76,24 +92,52 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
76
92
|
puts "Done."
|
|
77
93
|
end
|
|
78
94
|
|
|
79
|
-
# h registry get <name_or_alias> [type] — prints
|
|
80
|
-
|
|
95
|
+
# h registry get <name_or_alias> [type] [-s] — prints value (or name if no value)
|
|
96
|
+
# Supports prefix matching; use -s/--substring for substring match
|
|
97
|
+
# Prints all matching values (one per line) if multiple matches
|
|
98
|
+
add_subcmd(:get) do |*args|
|
|
99
|
+
opts = Hiiro::Options.setup {
|
|
100
|
+
option(:substring, short: :s, type: :flag, desc: 'Match substring anywhere in name')
|
|
101
|
+
}.parse(args)
|
|
102
|
+
|
|
103
|
+
ref, type = opts.args
|
|
81
104
|
unless ref
|
|
82
|
-
puts "Usage: h registry get <name_or_alias> [type]"
|
|
105
|
+
puts "Usage: h registry get <name_or_alias> [type] [-s]"
|
|
83
106
|
next
|
|
84
107
|
end
|
|
85
|
-
|
|
86
|
-
|
|
108
|
+
|
|
109
|
+
matches = Hiiro::RegistryEntry.find_all_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
110
|
+
if matches.empty?
|
|
111
|
+
exit(1)
|
|
112
|
+
else
|
|
113
|
+
matches.each { |e| puts(e.value || e.name) }
|
|
114
|
+
end
|
|
87
115
|
end
|
|
88
116
|
|
|
89
|
-
# h registry show <name_or_alias> [type] — human-readable detail
|
|
90
|
-
add_subcmd(:show) do |
|
|
117
|
+
# h registry show <name_or_alias> [type] [-s] — human-readable detail
|
|
118
|
+
add_subcmd(:show) do |*args|
|
|
119
|
+
opts = Hiiro::Options.setup {
|
|
120
|
+
option(:substring, short: :s, type: :flag, desc: 'Match substring anywhere in name')
|
|
121
|
+
}.parse(args)
|
|
122
|
+
|
|
123
|
+
ref, type = opts.args
|
|
91
124
|
unless ref
|
|
92
|
-
puts "Usage: h registry show <name_or_alias> [type]"
|
|
125
|
+
puts "Usage: h registry show <name_or_alias> [type] [-s]"
|
|
93
126
|
next
|
|
94
127
|
end
|
|
95
|
-
entry = Hiiro::RegistryEntry.find_by_ref(ref, type: type
|
|
96
|
-
|
|
128
|
+
entry = Hiiro::RegistryEntry.find_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
129
|
+
if entry
|
|
130
|
+
puts entry.display
|
|
131
|
+
else
|
|
132
|
+
matches = Hiiro::RegistryEntry.find_all_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
133
|
+
if matches.any?
|
|
134
|
+
puts "Ambiguous match '#{ref}' - #{matches.size} entries:"
|
|
135
|
+
matches.each { |e| puts " #{e.resource_type}/#{e.name}" }
|
|
136
|
+
else
|
|
137
|
+
puts "Not found: #{ref}"
|
|
138
|
+
end
|
|
139
|
+
exit 1
|
|
140
|
+
end
|
|
97
141
|
end
|
|
98
142
|
|
|
99
143
|
# h registry select [type] — fuzzyfinder, prints canonical name
|
|
@@ -110,19 +154,50 @@ Hiiro.run(*ARGV, tasks: true) do
|
|
|
110
154
|
puts name
|
|
111
155
|
end
|
|
112
156
|
|
|
113
|
-
# h registry set-alias <name_or_alias> <new_alias> [type]
|
|
114
|
-
add_subcmd(:'set-alias') do |
|
|
157
|
+
# h registry set-alias <name_or_alias> <new_alias> [type] [-s]
|
|
158
|
+
add_subcmd(:'set-alias') do |*args|
|
|
159
|
+
opts = Hiiro::Options.setup {
|
|
160
|
+
option(:substring, short: :s, type: :flag, desc: 'Match substring anywhere in name')
|
|
161
|
+
}.parse(args)
|
|
162
|
+
|
|
163
|
+
ref, new_alias, type = opts.args
|
|
115
164
|
unless ref && new_alias
|
|
116
|
-
puts "Usage: h registry set-alias <name_or_alias> <new_alias> [type]"
|
|
165
|
+
puts "Usage: h registry set-alias <name_or_alias> <new_alias> [type] [-s]"
|
|
117
166
|
next
|
|
118
167
|
end
|
|
119
|
-
entry = Hiiro::RegistryEntry.find_by_ref(ref, type: type
|
|
168
|
+
entry = Hiiro::RegistryEntry.find_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
120
169
|
unless entry
|
|
121
|
-
|
|
170
|
+
matches = Hiiro::RegistryEntry.find_all_by_ref(ref, type: type&.to_s, substring: opts.substring)
|
|
171
|
+
if matches.any?
|
|
172
|
+
puts "Ambiguous match '#{ref}' - #{matches.size} entries:"
|
|
173
|
+
matches.each { |e| puts " #{e.resource_type}/#{e.name}" }
|
|
174
|
+
else
|
|
175
|
+
puts "Not found: #{ref}"
|
|
176
|
+
end
|
|
122
177
|
next
|
|
123
178
|
end
|
|
124
179
|
entry.update(short_name: new_alias)
|
|
125
180
|
puts entry.display
|
|
126
181
|
end
|
|
127
182
|
|
|
183
|
+
# h registry set <type> <name> <value> — update value of existing entry (or create)
|
|
184
|
+
add_subcmd(:set, :update) do |type, name, value = nil|
|
|
185
|
+
unless type && name
|
|
186
|
+
puts "Usage: h registry set <type> <name> <value>"
|
|
187
|
+
next
|
|
188
|
+
end
|
|
189
|
+
entry = Hiiro::RegistryEntry.find_by_ref(name, type: type)
|
|
190
|
+
if entry
|
|
191
|
+
entry.update(value: value)
|
|
192
|
+
else
|
|
193
|
+
entry = Hiiro::RegistryEntry.create(
|
|
194
|
+
resource_type: type,
|
|
195
|
+
name: name,
|
|
196
|
+
value: value,
|
|
197
|
+
created_at: Time.now.iso8601
|
|
198
|
+
)
|
|
199
|
+
end
|
|
200
|
+
puts entry.display
|
|
201
|
+
end
|
|
202
|
+
|
|
128
203
|
end
|
data/lib/hiiro/db.rb
CHANGED
|
@@ -37,6 +37,8 @@ class Hiiro
|
|
|
37
37
|
|
|
38
38
|
MODELS.each do |cls|
|
|
39
39
|
cls.create_table!(conn)
|
|
40
|
+
# Run model-specific migrations (e.g., adding columns to existing tables)
|
|
41
|
+
cls.migrate!(conn) if cls.respond_to?(:migrate!)
|
|
40
42
|
# Clear all schema-related caches on the model and its anonymous Sequel
|
|
41
43
|
# parent class. When require_valid_table=false and the table didn't exist
|
|
42
44
|
# at class-definition time, Sequel caches empty results for @db_schema,
|
data/lib/hiiro/registry.rb
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
require 'sequel'
|
|
2
2
|
|
|
3
3
|
class Hiiro
|
|
4
|
-
class RegistryEntry < Sequel::Model(:
|
|
4
|
+
class RegistryEntry < Sequel::Model(:registry)
|
|
5
5
|
Hiiro::DB.register(self)
|
|
6
6
|
|
|
7
7
|
def self.create_table!(db)
|
|
8
|
-
|
|
8
|
+
# Rename old table if it exists
|
|
9
|
+
if db.table_exists?(:registry_entries) && !db.table_exists?(:registry)
|
|
10
|
+
db.rename_table(:registry_entries, :registry)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
db.create_table?(:registry) do
|
|
9
14
|
primary_key :id
|
|
10
15
|
String :resource_type, null: false # e.g. "service", "queue", "worker"
|
|
11
16
|
String :name, null: false # canonical identifier
|
|
17
|
+
String :value # stored value (optional)
|
|
12
18
|
String :short_name # alias / shorthand
|
|
13
19
|
String :description
|
|
14
20
|
String :meta_json # arbitrary JSON for extra fields
|
|
@@ -18,16 +24,65 @@ class Hiiro
|
|
|
18
24
|
end
|
|
19
25
|
end
|
|
20
26
|
|
|
27
|
+
def self.migrate!(db)
|
|
28
|
+
# Add value column if missing (migration for existing DBs)
|
|
29
|
+
unless db.schema(:registry).any? { |col, _| col == :value }
|
|
30
|
+
db.alter_table(:registry) { add_column :value, String }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
21
34
|
# ── Finders ──────────────────────────────────────────────────────────────
|
|
22
35
|
|
|
23
36
|
def self.of_type(type) = where(resource_type: type.to_s).order(:name).all
|
|
24
37
|
def self.all_ordered = order(:resource_type, :name).all
|
|
25
38
|
def self.known_types = distinct.select_map(:resource_type).sort
|
|
26
39
|
|
|
27
|
-
# Resolve by exact name or
|
|
28
|
-
|
|
40
|
+
# Resolve by exact name, short_name, or prefix within a type (or globally).
|
|
41
|
+
# Returns single entry or nil. Ambiguous prefix matches return nil.
|
|
42
|
+
def self.find_by_ref(ref, type: nil, substring: false)
|
|
43
|
+
scope = type ? where(resource_type: type.to_s) : self
|
|
44
|
+
|
|
45
|
+
# Try exact match first (name or short_name)
|
|
46
|
+
exact = scope.where(name: ref).first || scope.where(short_name: ref).first
|
|
47
|
+
return exact if exact
|
|
48
|
+
|
|
49
|
+
# Fall back to prefix/substring matching
|
|
50
|
+
entries = scope.all
|
|
51
|
+
matcher = Hiiro::Matcher.new(entries, :name)
|
|
52
|
+
result = substring ? matcher.by_substring(ref) : matcher.by_prefix(ref)
|
|
53
|
+
|
|
54
|
+
# Only return if unambiguous (exactly one match)
|
|
55
|
+
return result.first.item if result.one?
|
|
56
|
+
|
|
57
|
+
# Also try matching against short_name
|
|
58
|
+
matcher_short = Hiiro::Matcher.new(entries.select(&:short_name), :short_name)
|
|
59
|
+
result_short = substring ? matcher_short.by_substring(ref) : matcher_short.by_prefix(ref)
|
|
60
|
+
return result_short.first.item if result_short.one?
|
|
61
|
+
|
|
62
|
+
nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Find all entries matching ref (for showing ambiguous matches)
|
|
66
|
+
# Checks both name and short_name, returns unique entries
|
|
67
|
+
def self.find_all_by_ref(ref, type: nil, substring: false)
|
|
29
68
|
scope = type ? where(resource_type: type.to_s) : self
|
|
30
|
-
|
|
69
|
+
|
|
70
|
+
# Check for exact matches first
|
|
71
|
+
exact = scope.where(name: ref).all + scope.where(short_name: ref).all
|
|
72
|
+
return exact.uniq(&:id) if exact.any?
|
|
73
|
+
|
|
74
|
+
# Fall back to prefix/substring matching on name
|
|
75
|
+
entries = scope.all
|
|
76
|
+
matcher = Hiiro::Matcher.new(entries, :name)
|
|
77
|
+
result = substring ? matcher.by_substring(ref) : matcher.by_prefix(ref)
|
|
78
|
+
name_matches = result.matches.map(&:item)
|
|
79
|
+
|
|
80
|
+
# Also match on short_name
|
|
81
|
+
matcher_short = Hiiro::Matcher.new(entries.select(&:short_name), :short_name)
|
|
82
|
+
result_short = substring ? matcher_short.by_substring(ref) : matcher_short.by_prefix(ref)
|
|
83
|
+
short_matches = result_short.matches.map(&:item)
|
|
84
|
+
|
|
85
|
+
(name_matches + short_matches).uniq(&:id)
|
|
31
86
|
end
|
|
32
87
|
|
|
33
88
|
# Fuzzy-finder display lines: "type short name description"
|
|
@@ -51,12 +106,14 @@ class Hiiro
|
|
|
51
106
|
|
|
52
107
|
def fuzzy_line
|
|
53
108
|
parts = [resource_type.ljust(14), short_name&.ljust(16) || ' ' * 16, name]
|
|
109
|
+
parts << " = #{value}" if value && !value.empty?
|
|
54
110
|
parts << " # #{description}" if description && !description.empty?
|
|
55
111
|
parts.join(' ').strip
|
|
56
112
|
end
|
|
57
113
|
|
|
58
114
|
def display
|
|
59
115
|
lines = ["#{resource_type} / #{name}"]
|
|
116
|
+
lines << " value: #{value}" if value
|
|
60
117
|
lines << " alias: #{short_name}" if short_name
|
|
61
118
|
lines << " desc: #{description}" if description
|
|
62
119
|
meta.each { |k, v| lines << " #{k}: #{v}" } unless meta.empty?
|
data/lib/hiiro/version.rb
CHANGED