docopslab-dev 0.1.0 → 0.3.0

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +682 -324
  3. data/docopslab-dev.gemspec +3 -4
  4. data/lib/docopslab/dev/cast_ops.rb +199 -0
  5. data/lib/docopslab/dev/config_manager.rb +6 -6
  6. data/lib/docopslab/dev/data_utils.rb +42 -0
  7. data/lib/docopslab/dev/docker_aware.rb +40 -0
  8. data/lib/docopslab/dev/file_utils.rb +18 -7
  9. data/lib/docopslab/dev/git_branch.rb +201 -0
  10. data/lib/docopslab/dev/git_hooks.rb +17 -11
  11. data/lib/docopslab/dev/initializer.rb +34 -11
  12. data/lib/docopslab/dev/library/cache.rb +167 -0
  13. data/lib/docopslab/dev/library/fetch.rb +209 -0
  14. data/lib/docopslab/dev/library.rb +341 -0
  15. data/lib/docopslab/dev/linters.rb +73 -15
  16. data/lib/docopslab/dev/manifest.rb +28 -0
  17. data/lib/docopslab/dev/paths.rb +0 -17
  18. data/lib/docopslab/dev/script_manager.rb +12 -6
  19. data/lib/docopslab/dev/skim.rb +109 -0
  20. data/lib/docopslab/dev/spell_check.rb +2 -2
  21. data/lib/docopslab/dev/sync_ops.rb +94 -33
  22. data/lib/docopslab/dev/tasks.rb +58 -18
  23. data/lib/docopslab/dev/version.rb +1 -1
  24. data/lib/docopslab/dev.rb +77 -36
  25. data/specs/data/default-manifest.yml +23 -5
  26. data/specs/data/library-index.yml +22 -0
  27. data/specs/data/manifest-schema.yaml +142 -4
  28. data/specs/data/tasks-def.yml +122 -10
  29. metadata +28 -73
  30. data/assets/config-packs/actionlint/base.yml +0 -13
  31. data/assets/config-packs/actionlint/project.yml +0 -13
  32. data/assets/config-packs/htmlproofer/base.yml +0 -27
  33. data/assets/config-packs/htmlproofer/project.yml +0 -25
  34. data/assets/config-packs/rubocop/base.yml +0 -130
  35. data/assets/config-packs/rubocop/project.yml +0 -8
  36. data/assets/config-packs/shellcheck/base.shellcheckrc +0 -14
  37. data/assets/config-packs/subtxt/ai-asciidoc-antipatterns.sub.txt +0 -11
  38. data/assets/config-packs/vale/asciidoc/ExplicitSectionIDs.yml +0 -8
  39. data/assets/config-packs/vale/asciidoc/ExtraLineBeforeLevel1.yml +0 -7
  40. data/assets/config-packs/vale/asciidoc/OneSentencePerLine.yml +0 -8
  41. data/assets/config-packs/vale/asciidoc/PreferSourceBlocks.yml +0 -8
  42. data/assets/config-packs/vale/asciidoc/ProperAdmonitions.yml +0 -8
  43. data/assets/config-packs/vale/asciidoc/ProperDLs.yml +0 -7
  44. data/assets/config-packs/vale/asciidoc/UncleanListStart.yml +0 -8
  45. data/assets/config-packs/vale/authoring/ButParagraph.yml +0 -8
  46. data/assets/config-packs/vale/authoring/ExNotEg.yml +0 -8
  47. data/assets/config-packs/vale/authoring/LiteralTerms.yml +0 -20
  48. data/assets/config-packs/vale/authoring/Spelling.yml +0 -679
  49. data/assets/config-packs/vale/base.ini +0 -38
  50. data/assets/config-packs/vale/config/scripts/ExplicitSectionIDs.tengo +0 -56
  51. data/assets/config-packs/vale/config/scripts/ExtraLineBeforeLevel1.tengo +0 -121
  52. data/assets/config-packs/vale/config/scripts/OneSentencePerLine.tengo +0 -53
  53. data/assets/config-packs/vale/project.ini +0 -5
  54. data/assets/hooks/pre-commit +0 -63
  55. data/assets/hooks/pre-push +0 -72
  56. data/assets/scripts/adoc_section_ids.rb +0 -50
  57. data/assets/scripts/build-common.sh +0 -193
  58. data/assets/scripts/build-docker.sh +0 -64
  59. data/assets/scripts/build.sh +0 -56
  60. data/assets/scripts/parse_jekyll_asciidoc_logs.rb +0 -467
  61. data/assets/templates/Gemfile +0 -7
  62. data/assets/templates/Rakefile +0 -3
  63. data/assets/templates/gitignore +0 -69
  64. data/assets/templates/jekyll-asciidoc-fix.prompt.yml +0 -17
  65. data/assets/templates/spellcheck.prompt.yml +0 -16
  66. data/docs/agent/AGENTS.md +0 -229
  67. data/docs/agent/index.md +0 -80
  68. data/docs/agent/missions/conduct-release.md +0 -224
  69. data/docs/agent/missions/setup-new-project.md +0 -250
  70. data/docs/agent/roles/devops-release-engineer.md +0 -152
  71. data/docs/agent/roles/docops-engineer.md +0 -193
  72. data/docs/agent/roles/planner-architect.md +0 -74
  73. data/docs/agent/roles/product-engineer.md +0 -153
  74. data/docs/agent/roles/product-manager.md +0 -130
  75. data/docs/agent/roles/project-manager.md +0 -139
  76. data/docs/agent/roles/qa-testing-engineer.md +0 -115
  77. data/docs/agent/roles/tech-docs-manager.md +0 -143
  78. data/docs/agent/roles/tech-writer.md +0 -163
  79. data/docs/agent/skills/asciidoc.md +0 -609
  80. data/docs/agent/skills/code-commenting.md +0 -347
  81. data/docs/agent/skills/fix-broken-links.md +0 -309
  82. data/docs/agent/skills/fix-jekyll-asciidoc-build-errors.md +0 -23
  83. data/docs/agent/skills/fix-spelling-issues.md +0 -13
  84. data/docs/agent/skills/git.md +0 -170
  85. data/docs/agent/skills/github-issues.md +0 -135
  86. data/docs/agent/skills/product-release-rollback-and-patching.md +0 -71
  87. data/docs/agent/skills/rake-cli-dev.md +0 -57
  88. data/docs/agent/skills/readme-driven-dev.md +0 -13
  89. data/docs/agent/skills/release-history.md +0 -29
  90. data/docs/agent/skills/ruby.md +0 -192
  91. data/docs/agent/skills/schemagraphy-sgyml.md +0 -18
  92. data/docs/agent/skills/tests-running.md +0 -25
  93. data/docs/agent/skills/tests-writing.md +0 -45
  94. data/docs/agent/skills/write-the-docs.md +0 -54
  95. data/docs/agent/topics/common-project-paths.md +0 -117
  96. data/docs/agent/topics/dev-tooling-usage.md +0 -202
  97. data/docs/agent/topics/devops-ci-cd.md +0 -55
  98. data/docs/agent/topics/product-docs-deployment.md +0 -25
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'asciisourcerer'
5
+ require 'sourcerer/util/pathifier'
6
+
7
+ module DocOpsLab
8
+ module Dev
9
+ # Source skimming via Sourcerer::SourceSkim
10
+ module Skim
11
+ ADOC_EXTS = %w[.adoc .asc .ad .asciidoc].freeze
12
+ MD_EXTS = %w[.md .markdown].freeze
13
+ ALL_EXTS = (ADOC_EXTS + MD_EXTS).freeze
14
+
15
+ class << self
16
+ # Skim all supported file types (AsciiDoc + Markdown), format auto-detected.
17
+ def run path, form: nil, syntax: nil
18
+ run_with_format(path, exts: ALL_EXTS, form: form, syntax: syntax)
19
+ end
20
+
21
+ # Skim AsciiDoc source files only.
22
+ def run_adoc path, form: nil, syntax: nil
23
+ run_with_format(path, exts: ADOC_EXTS, form: form, syntax: syntax, default_forms: [:tree])
24
+ end
25
+
26
+ # Skim Markdown source files only, with optional upstream:local overlay support.
27
+ def run_md path, form: nil, syntax: nil
28
+ run_with_format(path, exts: MD_EXTS, form: form, syntax: syntax, overlay: true)
29
+ end
30
+
31
+ private
32
+
33
+ def run_with_format path, exts:, form: nil, syntax: nil, default_forms: nil, overlay: false
34
+ unless path
35
+ puts '❌ Path is required.'
36
+ puts 'Usage: bundle exec rake labdev:skim[path,form,syntax]'
37
+ return
38
+ end
39
+
40
+ forms = form ? parse_forms(form) : default_forms
41
+ file_paths = overlay ? resolve_overlay_paths(path, exts) : resolve_paths(path, exts)
42
+
43
+ if file_paths.empty?
44
+ ext_desc = exts.size == 1 ? exts.first : exts.join(', ')
45
+ warn "No #{ext_desc} files found for: #{path}"
46
+ return
47
+ end
48
+
49
+ results = {}
50
+ cats = Sourcerer::SourceSkim::DEFAULT_CATEGORIES - [:attributes_custom]
51
+ file_paths.each do |fp|
52
+ skim_opts = { categories: cats }
53
+ skim_opts[:forms] = forms if forms
54
+ results[fp] = Sourcerer::SourceSkim.skim_file(fp, **skim_opts)
55
+ end
56
+ portable = JSON.parse(JSON.generate(results))
57
+
58
+ output_syntax = resolve_syntax(syntax, form)
59
+ puts output_syntax == :json ? JSON.pretty_generate(portable) : portable.to_yaml
60
+ end
61
+
62
+ # Resolve file paths with optional upstream:local overlay.
63
+ #
64
+ # When path_arg contains ':', split into upstream_dir:local_dir. Local files shadow
65
+ # upstream files that share the same relative path; local-only files are appended.
66
+ def resolve_overlay_paths path_arg, exts
67
+ parts = path_arg.split(':', 2).map(&:strip)
68
+ return resolve_paths(parts[0], exts) if parts.size == 1
69
+
70
+ upstream_dir, local_dir = parts
71
+ upstream_map = build_relative_map(upstream_dir, exts)
72
+ local_map = build_relative_map(local_dir, exts)
73
+ upstream_map.merge(local_map).values
74
+ end
75
+
76
+ def build_relative_map dir_path, exts
77
+ dir_path = dir_path.chomp('/')
78
+ return {} unless File.directory?(dir_path)
79
+
80
+ abs_base = File.expand_path(dir_path)
81
+ Sourcerer::Util::Pathifier.match(dir_path).enum
82
+ .select { |p| exts.any? { |e| p.end_with?(e) } }
83
+ .each_with_object({}) do |abs_path, map|
84
+ map[abs_path.sub("#{abs_base}/", '')] = abs_path
85
+ end
86
+ end
87
+
88
+ def parse_forms form
89
+ form.split(',').map { |f| f.strip.to_sym }
90
+ end
91
+
92
+ def resolve_paths path, exts
93
+ result = Sourcerer::Util::Pathifier.match(path)
94
+ result.type == :dir ? result.enum.select { |p| exts.any? { |e| p.end_with?(e) } } : result.enum.to_a
95
+ end
96
+
97
+ def resolve_syntax syntax, form
98
+ return :yaml unless form
99
+
100
+ syntax = 'yaml' if syntax == 'yml'
101
+ puts
102
+ return syntax.to_sym if syntax
103
+
104
+ :json
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -146,8 +146,8 @@ module DocOpsLab
146
146
  require 'erb'
147
147
 
148
148
  unless agent_prompt
149
- template_path = File.join(TEMPLATES_DIR, 'spellcheck.prompt.yml')
150
- agent_prompt = File.read(template_path) if File.exist?(template_path)
149
+ template_path = Library.resolve('templates/spellcheck.prompt.yml')
150
+ agent_prompt = File.read(template_path) if template_path && File.exist?(template_path)
151
151
  end
152
152
 
153
153
  # Create the YAML content with ERB templating for better formatting
@@ -6,36 +6,35 @@ require 'pathname'
6
6
 
7
7
  module DocOpsLab
8
8
  module Dev
9
+ # rubocop:disable Metrics/ModuleLength
9
10
  module SyncOps
10
- # rubocop :disable Metrics/ClassLength
11
+ # rubocop:disable Metrics/ClassLength
11
12
  class << self
12
13
  def install_vale_styles context
13
- return unless File.exist?(CONFIG_PATHS[:vale]) && context.tool_available?('vale')
14
+ return unless File.exist?(Paths::CONFIG_FILES[:vale]) && context.tool_available?('vale')
14
15
 
15
- puts "📚 Syncing Vale styles using Packages key in #{CONFIG_PATHS[:vale]} (local and remote packages)"
16
- context.run_with_fallback('vale', "vale --config=#{CONFIG_PATHS[:vale]} sync")
16
+ puts "📚 Syncing Vale styles using Packages key in #{Paths::CONFIG_FILES[:vale]} (local and remote packages)"
17
+ context.run_with_fallback('vale', "vale --config=#{Paths::CONFIG_FILES[:vale]} sync")
17
18
  end
18
19
 
19
20
  def sync_vale_styles context, local: false
20
21
  puts '📚 Syncing Vale styles...'
21
22
 
22
- styles_source_root = if context.lab_dev_mode?
23
- # Running inside lab monorepo
24
- 'gems/docopslab-dev/assets/config-packs/vale'
25
- else
26
- # Running from consumer project with path dependency
27
- File.join(GEM_ROOT, 'assets', 'config-packs', 'vale')
28
- end
23
+ unless Library.available?
24
+ puts '❌ Library not available; run `labdev:sync:library` to fetch.'
25
+ return false
26
+ end
27
+ styles_source_root = Library.resolve('config-packs/vale')
28
+ unless styles_source_root
29
+ puts '❌ config-packs/vale not found in library; run `labdev:sync:library` to fetch.'
30
+ return false
31
+ end
29
32
  styles_dest_root = '.config/.vendor/vale/styles'
30
33
  FileUtils.mkdir_p(styles_dest_root)
31
34
 
32
35
  # Get the list of local styles from tools.yml
33
36
  begin
34
- tools_yml_path = if context.lab_dev_mode?
35
- 'gems/docopslab-dev/specs/data/tools.yml'
36
- else
37
- File.join(GEM_ROOT, 'specs', 'data', 'tools.yml')
38
- end
37
+ tools_yml_path = Dev.tools_def_path
39
38
 
40
39
  style_paths_array = YAML.load_file(tools_yml_path)
41
40
  .find { |t| t['slug'] == 'vale' }['packaging']['packages']
@@ -77,7 +76,7 @@ module DocOpsLab
77
76
  # If not local-only, also run Vale sync for remote styles
78
77
  unless local
79
78
  puts '📦 Syncing remote Vale packages...'
80
- vale_config = CONFIG_PATHS[:vale]
79
+ vale_config = Paths::CONFIG_FILES[:vale]
81
80
  context.generate_vale_config unless File.exist?(vale_config)
82
81
  context.run_with_fallback('vale', "vale --config=#{vale_config} sync")
83
82
  end
@@ -92,6 +91,12 @@ module DocOpsLab
92
91
  docs_entries = manifest['docs']
93
92
  return false unless docs_entries.is_a?(Array)
94
93
 
94
+ lib_root = Library.root
95
+ unless lib_root
96
+ puts '❌ Library not available; run `labdev:sync:library` to fetch.'
97
+ return false
98
+ end
99
+
95
100
  puts '📚 Syncing documentation files...'
96
101
 
97
102
  synced_count = 0
@@ -107,16 +112,14 @@ module DocOpsLab
107
112
  next unless source_pattern
108
113
  next if synced # Only collect exclusions
109
114
 
110
- # Resolve source file path
115
+ # Resolve source file path relative to library root
111
116
  if source_pattern.include?('*')
112
- # Glob pattern for exclusions
113
- source_glob = File.join(GEM_ROOT, source_pattern)
117
+ source_glob = File.join(lib_root, source_pattern)
114
118
  Dir.glob(source_glob).each do |source_file|
115
119
  excluded_files.add(source_file) if File.file?(source_file)
116
120
  end
117
121
  else
118
- # Single file exclusion
119
- source_file = File.join(GEM_ROOT, source_pattern)
122
+ source_file = File.join(lib_root, source_pattern)
120
123
  excluded_files.add(source_file) if File.exist?(source_file)
121
124
  end
122
125
  end
@@ -134,8 +137,7 @@ module DocOpsLab
134
137
 
135
138
  # Check if source is a glob pattern
136
139
  if source_pattern.include?('*')
137
- # Glob pattern; copy matching files
138
- source_glob = File.join(GEM_ROOT, source_pattern)
140
+ source_glob = File.join(lib_root, source_pattern)
139
141
  matching_files = Dir.glob(source_glob)
140
142
 
141
143
  if matching_files.empty?
@@ -147,13 +149,18 @@ module DocOpsLab
147
149
  next unless File.file?(source_file)
148
150
  next if sources_checked.include?(source_file)
149
151
 
150
- # Skip if explicitly excluded
151
152
  if excluded_files.include?(source_file)
152
153
  puts " ⏭️ Skipped #{File.basename(source_file)} (explicitly excluded)"
153
154
  next
154
155
  end
155
156
 
156
- # Determine target file path
157
+ # Guard: docs/agent/AGENTS.md was relocated to templates/AGENTS.markdown.
158
+ if source_file.end_with?('docs/agent/AGENTS.md')
159
+ puts ' ⏭️ Skipped docs/agent/AGENTS.md \
160
+ (relocated to templates/AGENTS.markdown; remove from manifest)'
161
+ next
162
+ end
163
+
157
164
  filename = File.basename(source_file)
158
165
  target_file = File.join(target_path, filename)
159
166
 
@@ -163,11 +170,11 @@ module DocOpsLab
163
170
  skipped_count += 1 if result == :skipped
164
171
  end
165
172
  else # Single file
166
- source_file = File.join(GEM_ROOT, source_pattern)
173
+ source_file = File.join(lib_root, source_pattern)
167
174
 
168
175
  unless File.exist?(source_file)
169
176
  puts " ❌ Source file not found: #{source_file}"
170
- puts " Run 'bundle exec rake gemdo:gen_agent_docs' in DocOps/lab to generate docs"
177
+ puts " Run 'bundle exec rake labdev:sync:library` then 'labdev:sync:docs' to refresh"
171
178
  next
172
179
  end
173
180
 
@@ -179,6 +186,12 @@ module DocOpsLab
179
186
  next
180
187
  end
181
188
 
189
+ # Guard: docs/agent/AGENTS.md was relocated to templates/AGENTS.markdown.
190
+ if source_file.end_with?('docs/agent/AGENTS.md')
191
+ puts ' ⏭️ Skipped docs/agent/AGENTS.md (relocated to templates/AGENTS.markdown; remove from manifest)'
192
+ next
193
+ end
194
+
182
195
  sources_checked << source_file
183
196
 
184
197
  result = copy_doc_file(source_file, target_path, synced: synced, force: force)
@@ -198,6 +211,52 @@ module DocOpsLab
198
211
  ScriptManager.sync_scripts
199
212
  end
200
213
 
214
+ def sync_templates context, force: false
215
+ manifest = context.load_manifest
216
+ return false unless manifest
217
+
218
+ template_entries = manifest['templates']
219
+ return false unless template_entries.is_a?(Array)
220
+
221
+ lib_root = Library.root
222
+ unless lib_root
223
+ puts '❌ Library not available; run `labdev:sync:library` to fetch.'
224
+ return false
225
+ end
226
+
227
+ puts '📄 Syncing template files...'
228
+
229
+ synced_count = 0
230
+ skipped_count = 0
231
+
232
+ template_entries.each do |entry|
233
+ source_rel = entry['source']
234
+ target_path = entry['target']
235
+ synced = entry.fetch('synced', false)
236
+
237
+ next unless source_rel && target_path
238
+
239
+ source_file = File.join(lib_root, source_rel)
240
+
241
+ unless File.exist?(source_file)
242
+ puts " \u274c Template source not found: #{source_rel}"
243
+ puts ' Run `bundle exec rake labdev:sync:library` to fetch the latest library.'
244
+ next
245
+ end
246
+
247
+ result = copy_doc_file(source_file, target_path, synced: synced, force: force)
248
+ synced_count += 1 if result == :copied
249
+ skipped_count += 1 if result == :skipped
250
+ end
251
+
252
+ puts "\u2705 Synced #{synced_count} template file(s)" if synced_count.positive?
253
+ if skipped_count.positive?
254
+ puts "\u2139\ufe0f Skipped #{skipped_count} existing template(s) (use --force to overwrite)"
255
+ end
256
+
257
+ synced_count.positive? || skipped_count.positive?
258
+ end
259
+
201
260
  def sync_config_files context, tool_filter: :all, offline: false
202
261
  # Validate tool filter parameter
203
262
  unless tool_filter == :all || tool_filter.is_a?(String) || tool_filter.is_a?(Symbol)
@@ -222,8 +281,9 @@ module DocOpsLab
222
281
  return false
223
282
  end
224
283
 
225
- unless Dir.exist?(CONFIG_PACKS_SOURCE_DIR)
226
- puts '❌ No assets/config-packs directory found in gem'
284
+ config_packs_root = Library.resolve('config-packs')
285
+ unless config_packs_root && Dir.exist?(config_packs_root)
286
+ puts '❌ config-packs not found in library; run `labdev:sync:library` to fetch.'
227
287
  return false
228
288
  end
229
289
 
@@ -270,7 +330,7 @@ module DocOpsLab
270
330
  next
271
331
  end
272
332
 
273
- source_path = File.join(CONFIG_PACKS_SOURCE_DIR, source_rel)
333
+ source_path = File.join(config_packs_root, source_rel)
274
334
 
275
335
  unless File.exist?(source_path)
276
336
  puts " ❌ Source not found: #{source_rel}"
@@ -375,7 +435,7 @@ module DocOpsLab
375
435
  obsolete_files = []
376
436
  # Common vendor paths to check for obsolete files
377
437
  vendor_patterns = [
378
- File.join(CONFIG_VENDOR_DIR, '**', '*')
438
+ File.join(Paths.config_vendor_dir, '**', '*')
379
439
  ]
380
440
  vendor_patterns.each do |pattern|
381
441
  Dir.glob(pattern).each do |file_path|
@@ -462,7 +522,8 @@ module DocOpsLab
462
522
  end
463
523
  end
464
524
  end
465
- # rubocop :enable Metrics/ClassLength
525
+ # rubocop:enable Metrics/ClassLength
466
526
  end
527
+ # rubocop:enable Metrics/ModuleLength
467
528
  end
468
529
  end
@@ -54,11 +54,6 @@ module DocOpsLab
54
54
  Dev.check_standard_rake_tasks
55
55
  end
56
56
 
57
- desc desc_for('check:updates')
58
- task :updates do
59
- Dev.check_hook_updates
60
- end
61
-
62
57
  desc desc_for('check:all')
63
58
  task :all do
64
59
  Rake::Task['labdev:check:env'].invoke
@@ -89,6 +84,11 @@ module DocOpsLab
89
84
  puts '⚠️ Agent docs sync skipped or failed'
90
85
  end
91
86
  end
87
+
88
+ desc desc_for('init:templates')
89
+ task :templates do
90
+ CastOps.init_cast_targets(Dev)
91
+ end
92
92
  end
93
93
 
94
94
  # ============================================================
@@ -135,9 +135,10 @@ module DocOpsLab
135
135
  # end
136
136
 
137
137
  desc desc_for('run:shellcheck')
138
- task :shellcheck, [:opts] => [] do |_t, args|
138
+ task :shellcheck, %i[path opts] => [] do |_t, args|
139
+ path = args[:path]
139
140
  opts = args[:opts] || ''
140
- Dev.run_shellcheck(nil, opts)
141
+ Dev.run_shellcheck(path, opts)
141
142
  end
142
143
 
143
144
  desc desc_for('run:actionlint')
@@ -167,6 +168,13 @@ module DocOpsLab
167
168
  Dev.sync_docs(force: true)
168
169
  end
169
170
 
171
+ desc desc_for('sync:templates')
172
+ task :templates, %i[path dry] => [] do |_t, args|
173
+ target = args[:path]
174
+ dry = args[:dry].to_s.downcase == 'dry'
175
+ CastOps.sync_cast_targets(Dev, target_filter: target, dry_run: dry)
176
+ end
177
+
170
178
  namespace :styles do
171
179
  desc desc_for('sync:styles:local')
172
180
  task :local do
@@ -210,11 +218,22 @@ module DocOpsLab
210
218
 
211
219
  desc desc_for('sync:all')
212
220
  task :all do
213
- Dev.sync_config_files
214
- Dev.sync_scripts
215
- Dev.sync_docs
221
+ Library.sync!
216
222
  Dev.install_missing_hooks
217
223
  Dev.sync_vale_styles
224
+ CastOps.sync_cast_targets(Dev)
225
+ end
226
+
227
+ desc desc_for('sync:library')
228
+ task :library do
229
+ Library.sync!
230
+ end
231
+
232
+ namespace :library do
233
+ desc desc_for('sync:library:stage')
234
+ task :stage, [:path] => [] do |_t, args|
235
+ Library.stage!(source_path: args[:path])
236
+ end
218
237
  end
219
238
  end
220
239
 
@@ -262,17 +281,12 @@ module DocOpsLab
262
281
 
263
282
  desc desc_for('lint:docs')
264
283
  task :docs, %i[path rule opts] => [] do |_t, args|
265
- path = args[:path]
284
+ path = args[:path] || '.'
266
285
  rule = args[:rule]
267
286
  opts = args[:opts]
268
287
 
269
- if path || rule || opts
270
- filter = rule ? ".Name==#{rule}" : nil
271
- target = path || nil
272
- Dev.run_vale(target, opts || '', filter: filter)
273
- else
274
- Dev.run_linter_group('AsciiDoc', %w[vale])
275
- end
288
+ filter = rule ? ".Name==#{rule}" : nil
289
+ Dev.run_vale(path, opts || '', filter: filter)
276
290
  end
277
291
 
278
292
  desc desc_for('lint:html')
@@ -398,6 +412,27 @@ module DocOpsLab
398
412
  Help.show_task_help('heal')
399
413
  end
400
414
 
415
+ # ============================================================
416
+ # SKIM tasks; Skim source files for machine-oriented outlines
417
+ # ============================================================
418
+
419
+ desc desc_for('skim')
420
+ task :skim, %i[path form syntax] => [] do |_t, args|
421
+ Skim.run(args[:path], form: args[:form], syntax: args[:syntax])
422
+ end
423
+
424
+ namespace :skim do
425
+ desc desc_for('skim:adoc')
426
+ task :adoc, %i[path form syntax] => [] do |_t, args|
427
+ Skim.run_adoc(args[:path], form: args[:form], syntax: args[:syntax])
428
+ end
429
+
430
+ desc desc_for('skim:md')
431
+ task :md, %i[path form syntax] => [] do |_t, args|
432
+ Skim.run_md(args[:path], form: args[:form], syntax: args[:syntax])
433
+ end
434
+ end
435
+
401
436
  # ============================================================
402
437
  # SHOW and HELP tasks; Display information
403
438
  # ============================================================
@@ -427,6 +462,11 @@ module DocOpsLab
427
462
 
428
463
  Dev.show_lint_rule(tool, rule)
429
464
  end
465
+
466
+ desc desc_for('show:library')
467
+ task :library do
468
+ Library.print_status
469
+ end
430
470
  end
431
471
 
432
472
  desc desc_for('help')
@@ -2,7 +2,7 @@
2
2
 
3
3
  module DocOpsLab
4
4
  module Dev
5
- VERSION = '0.1.0'
5
+ VERSION = '0.3.0'
6
6
  RUBY_TARGET = '3.2.7'
7
7
  end
8
8
  end