scout-essentials 1.8.8 → 1.9.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +26 -12
  3. data/README.md +83 -112
  4. data/VERSION +1 -1
  5. data/doc/Improvements.md +226 -0
  6. data/doc/StartHere.md +122 -0
  7. data/doc/developer/AnnotationSystem.md +184 -0
  8. data/doc/developer/Architecture.md +147 -0
  9. data/doc/developer/Configuration.md +238 -0
  10. data/doc/developer/CoreUtilities.md +265 -0
  11. data/doc/developer/DesignPrinciples.md +129 -0
  12. data/doc/developer/ErrorHandling.md +203 -0
  13. data/doc/developer/LockingAndConcurrency.md +157 -0
  14. data/doc/developer/PathResolution.md +200 -0
  15. data/doc/developer/PersistenceAndResources.md +119 -0
  16. data/doc/developer/StreamingModel.md +236 -0
  17. data/doc/user/AnnotatingData.md +202 -0
  18. data/doc/user/CachingResults.md +183 -0
  19. data/doc/user/CommandLineOptions.md +189 -0
  20. data/doc/user/Cookbook.md +211 -0
  21. data/doc/user/HandlingStreams.md +236 -0
  22. data/doc/user/LoggingAndProgress.md +158 -0
  23. data/doc/user/ProducingResources.md +177 -0
  24. data/doc/user/RemoteData.md +157 -0
  25. data/doc/user/RunningCommands.md +218 -0
  26. data/doc/user/WorkingWithFiles.md +217 -0
  27. data/lib/scout/cmd.rb +343 -40
  28. data/lib/scout/concurrent_stream.rb +14 -1
  29. data/lib/scout/indiferent_hash.rb +1 -1
  30. data/lib/scout/log/fingerprint.rb +13 -8
  31. data/lib/scout/log/progress/report.rb +1 -1
  32. data/lib/scout/log.rb +4 -1
  33. data/lib/scout/misc/format.rb +24 -0
  34. data/lib/scout/named_array.rb +1 -1
  35. data/lib/scout/open/stream.rb +2 -2
  36. data/lib/scout/open/util.rb +4 -0
  37. data/lib/scout/path/find.rb +3 -2
  38. data/lib/scout/persist.rb +14 -10
  39. data/research/annotations-data-analysis.md +206 -0
  40. data/research/behavior-probes.md +1925 -0
  41. data/research/commands-streaming-analysis.md +272 -0
  42. data/research/design-philosophy-analysis.md +383 -0
  43. data/research/doc-audit-findings.md +294 -0
  44. data/research/ecosystem-attribution.md +118 -0
  45. data/research/implementation-inventory-core.md +1029 -0
  46. data/research/implementation-inventory-open.md +417 -0
  47. data/research/implementation-inventory-path-persist-resource.md +774 -0
  48. data/research/io-paths-analysis.md +228 -0
  49. data/research/persistence-resources-analysis.md +244 -0
  50. data/research/synthesis-report.md +80 -0
  51. data/scout-essentials.gemspec +37 -15
  52. data/test/scout/test_cmd.rb +411 -0
  53. metadata +36 -14
  54. data/doc/Annotation.md +0 -352
  55. data/doc/CMD.md +0 -363
  56. data/doc/ConcurrentStream.md +0 -163
  57. data/doc/IndiferentHash.md +0 -240
  58. data/doc/Log.md +0 -235
  59. data/doc/NamedArray.md +0 -174
  60. data/doc/Open.md +0 -331
  61. data/doc/Path.md +0 -217
  62. data/doc/Persist.md +0 -214
  63. data/doc/Resource.md +0 -229
  64. data/doc/SimpleOPT.md +0 -236
  65. data/doc/TmpFile.md +0 -154
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ccc931c0ac9a43124ba25f56b1d1e940ee2a00504c37d530df92949bd8a104e
4
- data.tar.gz: 4fab60400647db1a7ceb761c7e59c5900e22630afacbb2516467483f07dff402
3
+ metadata.gz: 526dfca4b8e68e08295052cb58f86b37b346857f0eb80ada50406b2683921de6
4
+ data.tar.gz: b2babc599d88a5e429fbcc1aad07e3f7d62483c3a73c1b56492a5847f7238319
5
5
  SHA512:
6
- metadata.gz: 172b38d8cb18f249f322429df932379c71b4b5067cc92ac26bf26e93c9fba486da6a0e0e51873387d79e0fdc46f6697fc999eaaf6fb93daa99e29b405b19680e
7
- data.tar.gz: 49ae1f7eca956c1fffd420efc34b2c2b700aaf3f66a780ccb34acabc02f4d598420df64bb5552a6b759fc0451229e77c4c56cd11459b3352965a5f4f663fbfc2
6
+ metadata.gz: 5041b9210824ce7add63097c50f67745af42c212197c33816ddef4a11e187e09c75d3e342b4d9e56d4a5e6132717cc5cef078518540e74494d98f7deb819c28b
7
+ data.tar.gz: 695290651c1db53bf9bfcd93f1567126f4eaba1c494d46b0cc6c4bbb221c4fcdd924a5c29d0ca25d8173b2b67fdbac46cfc344d59e9d28f58f8d30f19b71ea16
data/.vimproject CHANGED
@@ -6,20 +6,34 @@ scout-essentials=/$PWD filter="*.rb *.txt *.md *.conf *.yaml" {
6
6
 
7
7
  review
8
8
  document.rb
9
+ documentation
10
+
11
+ cmd
12
+
13
+ timeout
9
14
  }
10
15
  doc=doc{
11
- Annotation.md
12
- CMD.md
13
- ConcurrentStream.md
14
- IndiferentHash.md
15
- Log.md
16
- NamedArray.md
17
- Open.md
18
- Path.md
19
- Persist.md
20
- Resource.md
21
- SimpleOPT.md
22
- TmpFile.md
16
+ Improvements.md
17
+ StartHere.md
18
+ user=user{
19
+ AnnotatingData.md
20
+ CachingResults.md
21
+ CommandLineOptions.md
22
+ Cookbook.md
23
+ HandlingStreams.md
24
+ LoggingAndProgress.md
25
+ ProducingResources.md
26
+ RunningCommands.md
27
+ WorkingWithFiles.md
28
+ }
29
+ developer=developer{
30
+ AnnotationSystem.md
31
+ Architecture.md
32
+ DesignPrinciples.md
33
+ PathResolution.md
34
+ PersistenceAndResources.md
35
+ StreamingModel.md
36
+ }
23
37
  }
24
38
  lib=lib {
25
39
  scout-essentials.rb
data/README.md CHANGED
@@ -1,136 +1,107 @@
1
1
  # scout-essentials
2
2
 
3
- scout-essentials is the core library of the Scout framework. It provides a small, focused set of primitives used across the rest of the Scout ecosystem: process/stream management, file and path utilities, persistence and caching, logging and progress reporting, lightweight annotations for objects, and simple option parsing. The additional, domain-level functionality lives in companion packages such as `scout-gear`, `scout-ai`, etc. — see the mikisvaz GitHub account for those repositories.
3
+ scout-essentials is a small Ruby library (gem `scout-essentials`, [VERSION](VERSION)) that provides the shared substrate the other Scout repositories are built on: path and resource resolution, persistence/caching, file and stream I/O, command execution, streaming, annotations, logging and progress reporting, configuration, CLI-option parsing, remote data access and locking.
4
4
 
5
- This README points you to the key modules, shows quick usage patterns and explains where to find more detailed documentation in the `doc/` directory.
5
+ It deliberately contains no CLI executable, no TSV handling, no workflow engine and no job scheduler. Runtime dependencies are only `term-ansicolor`, `yaml`, `rake` and `listen` ([scout-essentials.gemspec](scout-essentials.gemspec)); it depends on no other scout-family or rbbt-family gem at runtime.
6
6
 
7
- ## Overview
7
+ ## Central abstractions
8
8
 
9
- Core capabilities included in scout-essentials:
9
+ | Abstraction | What it is |
10
+ |---|---|
11
+ | `Path` / `Resource` | `Path` is a `String` carrying annotations that resolves logical names (`data/config.yaml`) to real locations through configurable *path maps*; `Resource` modules declare claims over those paths and `produce` them on demand |
12
+ | `Persist` | typed on-disk caching: `Persist.persist(key, type) { ... }` with per-type serialization drivers, staleness invalidation (`:update`/`:check`), an in-memory cache and lock-protected recompute |
13
+ | `Open` | one interface for local, compressed (`.gz`/`.bgz`/`.zip`) and remote (`http(s)://`, `ssh:`) file and stream I/O, including atomic `sensible_write` and the `wget`/`rsync` remote cache |
14
+ | `CMD` | the subprocess layer: `CMD.cmd` for shell and no-shell commands, stdin piping, timeouts, stderr capture and external-tool bootstrap |
15
+ | `ConcurrentStream` | an `IO` extended with the producer threads/pids that feed it, plus join/abort callbacks — the lifecycle layer behind every pipe |
16
+ | `Annotation` / `AnnotatedObject` / `AnnotatedArray` | a mixin that attaches named metadata to ordinary Ruby objects (Strings, Arrays, Hashes) without changing their class; the mechanism `Path`, `Resource` and `NamedArray` are built on |
17
+ | `Log` / `Log::ProgressBar` | a severity-gated logger writing to STDERR (constants `Log::DEBUG … Log::NONE`) plus stacked progress bars rendered in the same place; colors via `term-ansicolor` |
18
+ | `Scout::Config` | a flat `key -> [tokens, value]` registry where, among the entries whose token matches the caller's context, the one with the lowest priority number wins |
19
+ | `SOPT` | a minimal option parser: options declared as a single string, a **destructive** consumer that edits `ARGV` in place, no subcommands and no coercion beyond booleans |
20
+ | `TmpFile` | scratch files and directories under `$HOME/tmp/scout`, with `·`-flattened names and a 150-character cap |
21
+ | `IndiferentHash` | a `Hash` extended so String and Symbol keys are interchangeable, plus the options-processing helpers built on it |
22
+ | `NamedArray` | Arrays with named positions (`NamedArray.setup(arr, [:a, :b])`), giving both positional and field-name access |
23
+ | `Misc` | small load-bearing helpers: the `Misc.format` family, `timespan`, digests, `insist`, filesystem and process utilities |
24
+ | `Lockfile` / `Open.lock` | `Open.lock(file, &block)` is the locking primitive, built on the vendored `Lockfile` at `lib/scout/open/lock/lockfile.rb`; there are three lock namespaces under `$HOME/.scout/tmp` |
10
25
 
11
- - Process and stream management with safe concurrency: `ConcurrentStream`, `CMD`
12
- - Robust file/stream I/O and remote access: `Open`
13
- - File/path abstraction and package-oriented lookup: `Path`, `Resource`
14
- - Atomic persistence and caching: `Persist`, `TmpFile`
15
- - Logging, color output and progress reporting: `Log`
16
- - Lightweight typed annotations on arbitrary objects: `Annotation`, `NamedArray`
17
- - Flexible indifferent Hash and option helpers: `IndiferentHash`, `SimpleOPT` (SOPT)
26
+ `require 'scout-essentials'` is the only entry point (`lib/scout-essentials.rb`); it loads the modules above plus `Open::NamedStream` and the exceptions (`Aborted`, `DontClose`, `ParameterException`, …). `NamedArray` and `Hook` are not auto-loaded and must be required explicitly.
18
27
 
19
- Each module is documented in the repository `doc/` directory; see the "Documentation" section below for direct links.
28
+ ## Getting started
20
29
 
21
- ---
22
-
23
- ## Documentation
24
-
25
- Full module-level documentation is shipped in `doc/`. The most important documents are:
26
-
27
- - doc/Annotation.md — add typed annotations to objects and arrays; AnnotatedArray
28
- - doc/CMD.md — process execution, streaming, tool discovery and helper wrappers
29
- - doc/ConcurrentStream.md — concurrent stream lifecycle, joining, aborting and callbacks
30
- - doc/IndiferentHash.md — string/symbol indifferent Hash helpers and options utilities
31
- - doc/Log.md — logging, colors, fingerprinting and ProgressBar
32
- - doc/NamedArray.md — small record-like arrays with named fields and fuzzy matching
33
- - doc/Open.md — unified file/stream I/O, remote fetch (wget/ssh), atomic writes, sync
34
- - doc/Path.md — Path helpers, mapping, finding and extension utilities
35
- - doc/Persist.md — typed serialization, persistence/caching and `Persist.persist`
36
- - doc/Resource.md — resource production, claim/produce and rake-based producers
37
- - doc/SimpleOPT.md — small option parsing and usage generation (SOPT)
38
- - doc/TmpFile.md — temporary file/dir helpers and stable cache path generator
39
-
40
- Open those files for detailed API descriptions, examples and notes.
41
-
42
- ---
43
-
44
- ## Quick start (examples)
45
-
46
- These short snippets show typical usage patterns — the docs in `doc/` contain more detail and examples.
47
-
48
- Annotation:
49
30
  ```ruby
50
- module Tag
51
- extend Annotation
52
- annotation :code, :note
53
- end
54
-
55
- s = "hello"
56
- Tag.setup(s, :code) # s.code -> :code
57
- s2 = "other"
58
- s.annotate(s2) # copies annotations
59
- ```
31
+ require 'scout-essentials'
60
32
 
61
- Open (reading a file, auto-decompress):
62
- ```ruby
63
- content = Open.read("data.tsv.gz")
33
+ Open.write('tmp/data.txt', "1\n2\n") # creates parent directories
34
+ Log.info "wrote 2 lines"
35
+ Persist.persist('count', :integer) { Open.read('tmp/data.txt').lines.count }
64
36
  ```
65
37
 
66
- Persist (cache a computed value):
67
- ```ruby
68
- value = Persist.persist("my-result", :json, dir: Path.setup("var/cache")) do
69
- expensive_computation()
70
- end
71
- ```
38
+ Documentation lives in the [`doc/`](doc/StartHere.md) directory start with [doc/StartHere.md](doc/StartHere.md).
72
39
 
73
- CMD + ConcurrentStream (run a pipeline):
74
- ```ruby
75
- io = CMD.cmd("tail -n 100", :in => some_file_io, :pipe => true)
76
- io2 = CMD.cmd("grep foo", :in => io, :pipe => true)
77
- puts io2.read
78
- io2.join
79
- ```
40
+ ## Relationship to the other Scout repositories
80
41
 
81
- Log + ProgressBar:
82
- ```ruby
83
- Log::ProgressBar.with_bar(100, desc: "Working") do |bar|
84
- 100.times { bar.tick; work_item }
85
- end
86
- ```
42
+ scout-essentials is the lowest layer of the Scout stack; everything above it is implemented in separate repositories:
87
43
 
88
- Path + Resource:
89
- ```ruby
90
- # Resource modules typically claim resources and produce them on demand.
91
- # Accessing a Path calls produce, so opening a resource Path triggers creation.
92
- p = Path.setup("share/data/myfile", 'mypkg')
93
- p.produce
94
- Open.read(p)
95
- ```
44
+ - **scout-gear** — adds TSV, `Workflow`/`Task`/`Step`, the `scout` CLI and `scout_commands/` dispatch, and the scheduler/HPC layer (SLURM/PBS/LSF, orchestrators) on top of essentials. It declares `scout-essentials` as a runtime dependency.
45
+ - **scout-camp** — deploys workflows to the cloud: offsite/terraform/AWS provisioning around the CLI. Its bin loads scout-gear's `bin/scout`; the scheduler logic itself lives in gear.
46
+ - **scout-rig** — consumes essentials' `Path`/`Resource` machinery at the code level (`require 'scout'`, `Path.add_path`); its gemspec does not declare the essentials edge.
47
+ - **scout-ai** reaches essentials transitively, via scout-rig and its own `require 'scout'`; it declares no direct dependency on essentials.
96
48
 
97
- ---
49
+ Attribution facts worth keeping straight (verified against installed gem sources; see the attribution table in [Architecture](doc/developer/Architecture.md)):
98
50
 
99
- ## Running tests
51
+ | Concept | Where it actually lives |
52
+ |---|---|
53
+ | `TSV`, `TSV::Dumper`, `Annotation.tsv`, `Workflow`/`Task`/`Step`, `.info` files, the `scout` CLI and `scout_commands/` | scout-gear |
54
+ | scheduler / HPC (SLURM, PBS, LSF, orchestrators) | scout-gear (scout-camp adds the cloud/offside deploy layer) |
55
+ | `Misc.notify` / `Misc.send_email` and the `Bgzf` block API | legacy rbbt-util **only** — scout-essentials references them without a require or gemspec edge, so they are `NoMethodError`/`NameError` in an essentials-only install |
56
+ | `deep_indifferent` | does not exist anywhere in the audited ecosystem |
57
+ | rbbt-util `require_instead` shims | rbbt-util 6.0.5 redirects ~30 requires onto scout files; the *dependency direction* at gemspec level is UNVERIFIED |
100
58
 
101
- The test suite exercises the modules (unit tests use Test::Unit). To run the tests in this repository, use your normal Ruby test runner; the test files are under `test/` — examples:
59
+ ## Documentation
102
60
 
103
- ```bash
104
- # from repository root
105
- ruby -Ilib test/scout/test_tmpfile.rb
106
- # or run the whole suite with your preferred runner
61
+ 22 Markdown pages under [`doc/`](doc/StartHere.md).
62
+
63
+ Entry points:
64
+
65
+ - [Start Here](doc/StartHere.md) — installation, the single require, what loads and what does not, what is *not* in this repo
66
+ - [Improvements](doc/Improvements.md) — running log of known misbehaviours (bug log, not a roadmap)
67
+
68
+ User guides:
69
+
70
+ - [Annotating Data](doc/user/AnnotatingData.md) — attaching metadata to objects
71
+ - [Working with Files](doc/user/WorkingWithFiles.md) — `Open` I/O, compression, grepping, atomic writes, locking, `TmpFile`
72
+ - [Remote Data](doc/user/RemoteData.md) — HTTP(S)/FTP/SSH fetch, the URL cache, rsync helpers
73
+ - [Running Commands](doc/user/RunningCommands.md) — `CMD.cmd`, piping, timeouts, stderr, tool bootstrap
74
+ - [Handling Streams](doc/user/HandlingStreams.md) — using `ConcurrentStream` objects: join, abort, callbacks
75
+ - [Caching Results](doc/user/CachingResults.md) — `Persist.persist`, serialization types, invalidation, in-memory cache
76
+ - [Producing Resources](doc/user/ProducingResources.md) — the `claim` syntax and `produce`
77
+ - [Logging and Progress](doc/user/LoggingAndProgress.md) — `Log`, severity, colors, fingerprints, progress bars
78
+ - [Command-Line Options](doc/user/CommandLineOptions.md) — `SOPT`
79
+ - [Cookbook](doc/user/Cookbook.md) — short executed recipes combining the modules
80
+
81
+ Developer guides:
82
+
83
+ - [Architecture](doc/developer/Architecture.md) — module dependency graph, load order, ecosystem boundaries
84
+ - [Design Principles](doc/developer/DesignPrinciples.md) — composition by annotation, and the other repo-wide conventions
85
+ - [Annotation System](doc/developer/AnnotationSystem.md) — the internals of annotations
86
+ - [Path Resolution](doc/developer/PathResolution.md) — path maps, map order, `find`/`follow`, `Resource#method_missing`
87
+ - [Persistence and Resources](doc/developer/PersistenceAndResources.md) — the `Persist` and `Resource#produce` write contracts
88
+ - [Streaming Model](doc/developer/StreamingModel.md) — how `ConcurrentStream` is built and how errors travel
89
+ - [Configuration](doc/developer/Configuration.md) — `Scout::Config` token priorities
90
+ - [Error Handling](doc/developer/ErrorHandling.md) — the exception taxonomy and the control-flow signals
91
+ - [Locking and Concurrency](doc/developer/LockingAndConcurrency.md) — the vendored `Lockfile` and the three lock namespaces
92
+ - [Core Utilities](doc/developer/CoreUtilities.md) — `IndiferentHash`, `NamedArray`, `Misc`, `TmpFile` naming, `Hook`
93
+
94
+ ## Development and testing
95
+
96
+ ```sh
97
+ bundle install
98
+ rake test # whole suite
99
+ rake test TEST=test/scout/test_open.rb # one file
100
+ ruby -Ilib -Itest test/scout/test_misc.rb # run a file directly
107
101
  ```
108
102
 
109
- Tests in the suite show practical usages and edge cases for the provided utilities.
110
-
111
- ---
112
-
113
- ## Related projects
114
-
115
- scout-essentials is intentionally focused on low-level primitives. Higher-level, domain-specific functionality is implemented in companion projects maintained on the mikisvaz GitHub account (look for repositories named `scout-gear`, `scout-ai`, etc.). Those packages build on what you find here to provide workflows, tools and integrations.
116
-
117
- GitHub: https://github.com/mikisvaz
118
- Look for repositories that begin with `scout-` (e.g. `scout-gear`, `scout-ai`).
119
-
120
- ---
121
-
122
- ## Contributing
123
-
124
- Contributions and improvements are welcome. Please follow the repository contribution guidelines (if present) or submit issues / pull requests on the project repository.
125
-
126
- If you extend or reuse code from this package in companion packages, prefer to keep core primitives here and implement domain logic in separate modules/packages (as done by the Scout ecosystem).
127
-
128
- ---
103
+ The `test` task is defined in the [Rakefile](Rakefile) (`Rake::TestTask`, pattern `test/**/test_*.rb`, which matches 49 files on disk: 47 test files (one of which, `test/scout/log/test_color.rb`, is empty) plus the two `test_helper.rb` files, one of which itself defines `TestMiscHelper`). Tests are plain `Test::Unit` and mirror the `lib/scout/` layout. The gemspec is generated by juwelier from the Rakefile — regenerate it with `rake gemspec` rather than editing it.
129
104
 
130
105
  ## License
131
106
 
132
- See the repository LICENSE (if present) for licensing information.
133
-
134
- ---
135
-
136
- If you need help finding a specific API, open the corresponding file in `doc/` (listed above) or search the `lib/` tree for concrete implementations and tests in `test/` for usage examples.
107
+ MIT-style license, Copyright (c) 2023 Miguel Vazquez — see [LICENSE.txt](LICENSE.txt).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.8.8
1
+ 1.9.0
@@ -0,0 +1,226 @@
1
+ # Improvements
2
+
3
+ Actionable recommendations for improving scout-essentials code, discovered
4
+ during the documentation effort. Each item includes a description, impact,
5
+ and suggested action.
6
+
7
+ ## Status legend
8
+
9
+ - 🔴 **Bug** — Incorrect behavior that should be fixed.
10
+ - 🟡 **Improvement** — Works, but could be better.
11
+ - 🟢 **Done** — Already resolved.
12
+
13
+ ---
14
+
15
+ ## High priority
16
+
17
+ ### I1. 🟡 ConcurrentStream join can deadlock with multi-stage pipelines
18
+
19
+ When joining a multi-stage pipeline (producer → filter → consumer), if the
20
+ producer is joined before the consumer has drained the pipe buffer, the
21
+ join can deadlock because the pipe buffer fills and the producer blocks.
22
+
23
+ **Impact:** Pipeline hangs in production.
24
+
25
+ **Suggested action:** Document the correct join order (consumer first,
26
+ producer last) and consider adding automatic consumer-joins-producer
27
+ chaining via `autojoin`.
28
+
29
+ ---
30
+
31
+ ### I2. 🟡 Persist persistence_path can collide for short keys
32
+
33
+ For short, filesystem-safe keys, Persist uses the key directly as the
34
+ filename. If two modules use the same short key, the cache files collide.
35
+
36
+ **Impact:** Subtle data corruption — one computation overwrites another's
37
+ cache.
38
+
39
+ **Suggested action:** Namespace cache paths by the calling module or
40
+ library. Consider prefixing with a digest of the caller's file path.
41
+
42
+ ---
43
+
44
+ ### I3. 🟡 TmpFile cleanup not guaranteed on signal (SIGTERM/SIGKILL)
45
+
46
+ TmpFile's `with_file` and `with_dir` use `ensure` blocks for cleanup.
47
+ However, SIGTERM and SIGKILL bypass `ensure`, leaving temporary files on
48
+ disk.
49
+
50
+ **Impact:** Temporary file accumulation over time in long-running services.
51
+
52
+ **Suggested action:** Register a PID-based temp directory and add a
53
+ periodic cleanup task. Consider using `at_exit` for graceful shutdown.
54
+
55
+ ---
56
+
57
+ ### I4. 🟡 Open remote read via SSH not documented or tested
58
+
59
+ Open supports reading from SSH paths (`user@host:path`), but this path is
60
+ not well documented, and test coverage is limited.
61
+
62
+ **Impact:** Users may not know SSH support exists; regressions may go
63
+ undetected.
64
+
65
+ **Suggested action:** Document SSH support in [Working with Files](user/WorkingWithFiles.md).
66
+ Add tests. Add retry logic for network failures.
67
+
68
+ ---
69
+
70
+ ## Medium priority
71
+
72
+ ### I5. 🟡 No central registry for path maps
73
+
74
+ Path maps are configured globally via `Path.path_maps` and
75
+ `Path.map_order`. There is no central registry where applications can
76
+ register their maps in a namespace-safe way.
77
+
78
+ **Impact:** Map name collisions between applications.
79
+
80
+ **Suggested action:** Introduce namespaced map registration: e.g.,
81
+ `Path.add_path("myapp:data", "/opt/myapp/{PATH}")`.
82
+
83
+ ---
84
+
85
+ ### I6. 🟡 IndiferentHash deep_indifferent not recursive by default
86
+
87
+ `IndiferentHash.setup` makes the top-level hash key-indifferent, but nested
88
+ hashes are not automatically converted. `deep_indifferent` must be called
89
+ explicitly.
90
+
91
+ **Impact:** Surprising behavior when accessing nested keys with mixed
92
+ string/symbol access.
93
+
94
+ **Suggested action:** Document this clearly. Consider making
95
+ `deep_indifferent` the default behavior or providing a clearer alternative.
96
+
97
+ ---
98
+
99
+ ### I7. 🟡 Path#find returns self even when file doesn't exist (for located paths)
100
+
101
+ When a path is "located" (starts with `/`, `~`, or `./`), `find` returns
102
+ `self` even if the file doesn't exist. This differs from non-located paths
103
+ where `find` may return nil when no map resolves.
104
+
105
+ **Impact:** Callers may assume `find` returns nil for nonexistent files.
106
+
107
+ **Suggested action:** Document this behavior clearly. Consider adding a
108
+ strict mode where `find` returns nil for nonexistent files regardless of
109
+ location status.
110
+
111
+ ---
112
+
113
+ ### I8. 🟡 Resource production failures leave no trace
114
+
115
+ When a Resource claim's production fails (e.g., download fails), the
116
+ production is abandoned silently. No log message is emitted beyond the
117
+ exception itself.
118
+
119
+ **Impact:** Hard to debug resource production issues in production.
120
+
121
+ **Suggested action:** Add `Log.warn` or `Log.error` calls in Resource
122
+ production error paths.
123
+
124
+ ---
125
+
126
+ ### I9. 🟡 CMD tool registry not namespaced
127
+
128
+ CMD tool registration (`CMD.add_tool`) uses a global registry. Multiple
129
+ applications using scout-essentials share the same tool registry.
130
+
131
+ **Impact:** Tool name collisions.
132
+
133
+ **Suggested action:** Namespace tool registration by application or provide
134
+ a scoped registry.
135
+
136
+ ---
137
+
138
+ ### I10. 🟡 No user-facing guide on custom Annotation modules
139
+
140
+ While the annotation system is powerful, there was no user-facing guide on
141
+ how to define and use custom annotation modules for application-specific
142
+ metadata.
143
+
144
+ **Impact:** Users may subclass instead of annotate, missing the idiom.
145
+
146
+ **Suggested action:** The new [Annotating Data](user/AnnotatingData.md)
147
+ guide covers this. It should be promoted more prominently.
148
+
149
+ ---
150
+
151
+ ## Low priority
152
+
153
+ ### I11. 🟢 Done — Documentation reorganized into three layers
154
+
155
+ The documentation has been reorganized from a flat class-by-class structure
156
+ into a three-layer structure (user/developer/research).
157
+
158
+ ---
159
+
160
+ ### I12. 🟡 Misc module is a catch-all
161
+
162
+ The `Misc` module (`lib/scout/misc/`) contains many unrelated utilities:
163
+ format, digest, math, system, hooks, monitor. This is a code smell.
164
+
165
+ **Impact:** Hard to find utilities; import surface too broad.
166
+
167
+ **Suggested action:** Consider splitting into separately named modules or
168
+ documenting the sub-namespace usage more clearly.
169
+
170
+ ---
171
+
172
+ ### I13. 🟡 No CI configuration visible
173
+
174
+ No CI configuration (`.travis.yml`, `.github/workflows/`, etc.) is visible
175
+ in the repository.
176
+
177
+ **Impact:** Tests may not run automatically on commit.
178
+
179
+ **Suggested action:** Add a CI configuration to run tests on commit.
180
+
181
+ ---
182
+
183
+ ### I14. 🟡 Benchmarking suite absent
184
+
185
+ There is no benchmarking suite to track performance across releases.
186
+
187
+ **Impact:** Performance regressions may go unnoticed.
188
+
189
+ **Suggested action:** Add a simple benchmark suite using `benchmark/ips`
190
+ for key operations (Open.read, Persist.persist, Path.find).
191
+
192
+ ---
193
+
194
+ ### I15. 🟡 Annotation `setup` with frozen objects creates a duplicate
195
+
196
+ When `setup` is called on a frozen object, it duplicates the object before
197
+ extending it. The original frozen object is not modified.
198
+
199
+ **Impact:** This is correct behavior but can surprise callers who expect
200
+ the same object to be returned.
201
+
202
+ **Suggested action:** Document this clearly in the Annotation documentation
203
+ and user guides.
204
+
205
+ ---
206
+
207
+ ### I16. 🟡 Persist.persist can raise if cache_dir not writable
208
+
209
+ If `Persist.cache_dir` is not writable, `persist` will fail with a
210
+ permissions error.
211
+
212
+ **Impact:** Can break production when cache_dir is on a read-only
213
+ filesystem.
214
+
215
+ **Suggested action:** Document this requirement and consider falling back
216
+ to a temporary cache dir or raising a clearer error message.
217
+
218
+ ---
219
+
220
+ ## Summary
221
+
222
+ | Category | Count |
223
+ |----------|-------|
224
+ | Bugs (🔴) | 0 |
225
+ | Improvements (🟡) | 15 |
226
+ | Done (🟢) | 1 |
data/doc/StartHere.md ADDED
@@ -0,0 +1,122 @@
1
+ # Start Here
2
+
3
+ `scout-essentials` is the lowest layer of the Scout stack: a Ruby gem of
4
+ small, composable modules for paths, file I/O, command execution, caching,
5
+ annotations, logging, progress bars and option parsing. It deliberately
6
+ contains **no** CLI, no TSV handling, no workflow engine and no job
7
+ scheduler — those live in other repos (see
8
+ [Architecture](developer/Architecture.md), attribution table).
9
+
10
+ ## Installation and first require
11
+
12
+ ```ruby
13
+ gem 'scout-essentials' # Gemfile
14
+ ```
15
+
16
+ ```ruby
17
+ require 'scout-essentials'
18
+ Path.setup('tmp/data.txt') # => annotated String
19
+ Open.write('tmp/data.txt', "1\n2\n")
20
+ Log.info "wrote 2 lines"
21
+ ```
22
+
23
+ ### What that single require actually loads
24
+
25
+ `lib/scout-essentials.rb` is the whole surface — in this order:
26
+
27
+ | require | gives you |
28
+ | --- | --- |
29
+ | `scout/exceptions` | `Aborted`, `DontClose`, `DontPersist`, `ParameterException`, … |
30
+ | `scout/indiferent_hash` | `IndiferentHash` |
31
+ | `scout/tmpfile` | `TmpFile` (also pulls `scout/open`) |
32
+ | `scout/log` | `Log`, `Log::ProgressBar` |
33
+ | `scout/path` | `Path`, `Resource`-adjacent path helpers |
34
+ | `scout/simple_opt` | `SOPT` |
35
+ | `scout/resource` | `Resource`, `Scout::Resource` |
36
+ | `scout/resource/scout` | scout resource defaults (`pkgdir`, `subdir`) |
37
+ | `scout/persist` | `Persist` |
38
+ | `scout/config` | `Scout::Config` |
39
+
40
+ Transitive pulls: `scout/open` (hence `Open`, `CMD`, `NamedStream`),
41
+ `scout/annotation` (hence `Annotation`), `scout/misc` (via
42
+ `scout/tmpfile`/`scout/open`). Notably **not** loaded by the umbrella
43
+ require (verified by probe `tmp/rewrite_C/probe_01_requires.rb`):
44
+
45
+ - `NamedArray` — `require 'scout/named_array'`
46
+ - `Hook` (a **top-level** `module Hook`, *not* `Misc::Hook`) —
47
+ `require 'scout/misc/hook'`
48
+
49
+ `Scout::Config` is loaded but you must use the namespaced name.
50
+
51
+ ## What is *not* in this repository
52
+
53
+ | Not here | Where it lives |
54
+ | --- | --- |
55
+ | `bin/` CLI, `scout` executable, `scout_commands/` | scout-gear |
56
+ | TSV, `TSV` parsing, `Annotation.tsv` | scout-gear |
57
+ | `Workflow`, `Step`, job dependencies | scout-gear / scout-rig |
58
+ | scheduler, HPC/DRMAA/LSF/SLURM orchestration | scout-workflows |
59
+ | `notify`, `send_email` | rbbt-util |
60
+ | Bgzf (`Open.bgunzip` is here, the Bgzf block API is not) | scout-gear |
61
+ | `deep_indifferent` | nowhere — it does not exist |
62
+
63
+ See the [attribution table in Architecture](developer/Architecture.md) for
64
+ the full map.
65
+
66
+ ## Bug log
67
+
68
+ [Improvements.md](Improvements.md) is the running log of known
69
+ misbehaviours that were documented during the audit
70
+ (`TmpFile.with_file` leaking on exception, `Persist` lock races, …). It is
71
+ **not** a roadmap; it records what the code actually does versus what you
72
+ might expect.
73
+
74
+ ## Development and testing
75
+
76
+ ```sh
77
+ bundle install
78
+ rake test # runs the whole suite (49 test files)
79
+ rake test TEST=test/scout/test_open.rb
80
+ ```
81
+
82
+ The `test` task is defined at `Rakefile:26-28`; the suite lives under
83
+ `test/scout/**` and mirrors the module layout (`test_path.rb`,
84
+ `test_open.rb`, `test_persist.rb`, `test_annotation.rb`, …). Tests are
85
+ plain `Test::Unit` and can be run directly:
86
+
87
+ ```sh
88
+ ruby -Ilib -Itest test/scout/test_misc.rb
89
+ ```
90
+
91
+ ## Where to go next
92
+
93
+ **User guides** — how to *use* the library:
94
+
95
+ - [Annotating Data](user/AnnotatingData.md)
96
+ - [Working with Files](user/WorkingWithFiles.md)
97
+ - [Remote Data](user/RemoteData.md)
98
+ - [Running Commands](user/RunningCommands.md)
99
+ - [Handling Streams](user/HandlingStreams.md)
100
+ - [Caching Results](user/CachingResults.md)
101
+ - [Producing Resources](user/ProducingResources.md)
102
+ - [Logging and Progress](user/LoggingAndProgress.md)
103
+ - [Command-Line Options](user/CommandLineOptions.md)
104
+ - [Cookbook](user/Cookbook.md)
105
+
106
+ **Developer guides** — how the library *works*:
107
+
108
+ - [Architecture](developer/Architecture.md)
109
+ - [Design Principles](developer/DesignPrinciples.md)
110
+ - [Annotation System](developer/AnnotationSystem.md)
111
+ - [Path Resolution](developer/PathResolution.md)
112
+ - [Persistence and Resources](developer/PersistenceAndResources.md)
113
+ - [Streaming Model](developer/StreamingModel.md)
114
+ - [Configuration](developer/Configuration.md)
115
+ - [Error Handling](developer/ErrorHandling.md)
116
+ - [Locking and Concurrency](developer/LockingAndConcurrency.md)
117
+ - [Core Utilities](developer/CoreUtilities.md)
118
+
119
+ **Research artifacts** (`../research/`) are non-normative supporting
120
+ material: `research/doc_audit/*` holds the per-claim audit ledgers,
121
+ `research/behavior-probes.md` the probe transcripts, and
122
+ `research/implementation-inventory-*.md` the file:line inventories.