job-workflow 0.5.0 → 0.6.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.agents/instructions/coding-style.md +38 -0
  3. data/.agents/instructions/domain.md +37 -0
  4. data/.agents/instructions/environment.md +44 -0
  5. data/.agents/instructions/general.md +29 -0
  6. data/.agents/instructions/security.md +20 -0
  7. data/.agents/instructions/structure.md +43 -0
  8. data/.agents/instructions/tech-stack.md +40 -0
  9. data/.agents/instructions/testing.md +46 -0
  10. data/.agents/instructions/workflow.md +39 -0
  11. data/.rubocop.yml +1 -2
  12. data/AGENTS.md +23 -0
  13. data/CHANGELOG.md +26 -0
  14. data/README.md +1 -1
  15. data/app/controllers/job_workflow/monitoring/application_controller.rb +11 -0
  16. data/app/controllers/job_workflow/monitoring/executions_controller.rb +28 -0
  17. data/app/controllers/job_workflow/monitoring/workflows_controller.rb +11 -0
  18. data/app/views/job_workflow/monitoring/executions/index.html.erb +57 -0
  19. data/app/views/job_workflow/monitoring/executions/show.html.erb +200 -0
  20. data/app/views/job_workflow/monitoring/workflows/index.html.erb +39 -0
  21. data/app/views/layouts/job_workflow/monitoring/application.html.erb +117 -0
  22. data/config/routes.rb +8 -0
  23. data/guides/API_REFERENCE.md +9 -6
  24. data/guides/DEPENDENCY_WAIT.md +9 -5
  25. data/guides/MONITORING_UI.md +74 -0
  26. data/guides/PARALLEL_PROCESSING.md +33 -21
  27. data/guides/PRODUCTION_DEPLOYMENT.md +1 -1
  28. data/guides/README.md +6 -1
  29. data/guides/THROTTLING.md +24 -0
  30. data/guides/WORKFLOW_STATUS_QUERY.md +7 -1
  31. data/lib/job_workflow/context.rb +7 -5
  32. data/lib/job_workflow/dsl.rb +0 -4
  33. data/lib/job_workflow/instrumentation/opentelemetry_subscriber.rb +1 -1
  34. data/lib/job_workflow/instrumentation.rb +14 -14
  35. data/lib/job_workflow/job_status.rb +16 -1
  36. data/lib/job_workflow/monitoring/dag_layout.rb +186 -0
  37. data/lib/job_workflow/monitoring/engine.rb +15 -0
  38. data/lib/job_workflow/monitoring/execution_page.rb +16 -0
  39. data/lib/job_workflow/monitoring/execution_registry.rb +50 -0
  40. data/lib/job_workflow/monitoring/execution_view_model.rb +258 -0
  41. data/lib/job_workflow/monitoring/parameter_filter.rb +37 -0
  42. data/lib/job_workflow/monitoring/workflow_definition.rb +24 -0
  43. data/lib/job_workflow/monitoring/workflow_registry.rb +24 -0
  44. data/lib/job_workflow/monitoring.rb +120 -0
  45. data/lib/job_workflow/queue_adapters/abstract.rb +7 -2
  46. data/lib/job_workflow/queue_adapters/null_adapter.rb +12 -1
  47. data/lib/job_workflow/queue_adapters/solid_queue_adapter.rb +42 -12
  48. data/lib/job_workflow/railtie.rb +2 -0
  49. data/lib/job_workflow/runner.rb +5 -3
  50. data/lib/job_workflow/sub_task_job.rb +93 -0
  51. data/lib/job_workflow/task_enqueue.rb +19 -12
  52. data/lib/job_workflow/version.rb +1 -1
  53. data/lib/job_workflow/workflow_status.rb +39 -3
  54. data/lib/job_workflow.rb +2 -0
  55. data/rbs_collection.lock.yaml +11 -11
  56. data/sig/generated/job_workflow/context.rbs +7 -7
  57. data/sig/generated/job_workflow/instrumentation/opentelemetry_subscriber.rbs +0 -1
  58. data/sig/generated/job_workflow/instrumentation.rbs +28 -28
  59. data/sig/generated/job_workflow/job_status.rbs +5 -2
  60. data/sig/generated/job_workflow/monitoring/dag_layout.rbs +80 -0
  61. data/sig/generated/job_workflow/monitoring/engine.rbs +8 -0
  62. data/sig/generated/job_workflow/monitoring/execution_page.rbs +14 -0
  63. data/sig/generated/job_workflow/monitoring/execution_registry.rbs +21 -0
  64. data/sig/generated/job_workflow/monitoring/execution_view_model.rbs +111 -0
  65. data/sig/generated/job_workflow/monitoring/parameter_filter.rbs +16 -0
  66. data/sig/generated/job_workflow/monitoring/workflow_definition.rbs +18 -0
  67. data/sig/generated/job_workflow/monitoring/workflow_registry.rbs +13 -0
  68. data/sig/generated/job_workflow/monitoring.rbs +38 -0
  69. data/sig/generated/job_workflow/queue_adapters/abstract.rbs +7 -4
  70. data/sig/generated/job_workflow/queue_adapters/null_adapter.rbs +5 -2
  71. data/sig/generated/job_workflow/queue_adapters/solid_queue_adapter.rbs +18 -6
  72. data/sig/generated/job_workflow/runner.rbs +1 -1
  73. data/sig/generated/job_workflow/sub_task_job.rbs +40 -0
  74. data/sig/generated/job_workflow/task_enqueue.rbs +5 -8
  75. data/sig/generated/job_workflow/workflow_status.rbs +18 -2
  76. data/sig-private/job-workflow.rbs +11 -0
  77. data/sig-private/rails.rbs +5 -0
  78. metadata +42 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9474c65583cf21d485c3468675d4f23124e60e88f98c954bd38256b916d98ffe
4
- data.tar.gz: 59d5e0b60a2b52e87ea4da4aab1834d02c63f88cba36f661acd8c74f89a4e6a9
3
+ metadata.gz: '08ad79c285a78a258aaafdf2cca6141982291f52c00a7c95412a7df728f96217'
4
+ data.tar.gz: 4fba62aa4a507ab75f8fb33ac21b1fadaa409452f985be9e1eedff0a010a3614
5
5
  SHA512:
6
- metadata.gz: 4ac034e1b373b28aa52dcffd059bc5b64e5c45fc04d9b07460c24491c2514eabddf839b2dcb2c4a2cfbf36b578e2836e153e9bd6f34cd24f8af543cf06242ce9
7
- data.tar.gz: 455b6913137103b6a5871562a6adc0ffca11e9e99543b94ec7e0bda9f2b78c6c76c5cee73baec30ca5b5b5e2fd388d6a4b119c08d7cf1039c20e115e255f58d7
6
+ metadata.gz: 5b079b1bb1b534b9952de0b431d6fac1658e9581ea30d22cbe5b0737e7c7748f78af68a46880500d8c3da9edc51bf5b4e558adf568ae1f0ce014cf77bd336ab8
7
+ data.tar.gz: fc2a98038a737cd4bc47c4f029bc2df17d55ec6d2ce16ca031f14a84cce8ac5a9418f20b18fc8174a2e157b74488557e4335bbed9afe71582141adc97ea28a00
@@ -0,0 +1,38 @@
1
+ # Coding Style
2
+
3
+ ## Primary sources of truth
4
+
5
+ - `.rubocop.yml` for Ruby style, complexity, and naming constraints
6
+ - `Steepfile`, `rbs_collection.yaml`, and inline RBS usage for type-checking expectations
7
+ - `.github/copilot-instructions.md` for repository-specific design and testing rules
8
+
9
+ ## Mechanical style constraints
10
+
11
+ - Ruby string literals use double quotes.
12
+ - RuboCop line length is capped at 120 characters.
13
+ - The repository excludes `examples/**/*` from the root RuboCop config because the example app validates itself separately.
14
+
15
+ ## Design rules
16
+
17
+ - Keep code small and focused on a single responsibility.
18
+ - Prefer composable behavior over large monolithic methods.
19
+ - Favor immutable workflow inputs through `Arguments`.
20
+ - Use `Output` as the main way to communicate task side effects and downstream data.
21
+ - Preserve clear boundaries between `Workflow`, `Task`, and `Runner`.
22
+ - Avoid breaking public APIs without a documented migration or deprecation path.
23
+
24
+ ## Type and signature rules
25
+
26
+ - Prefer `rbs-inline` comments in implementation files when type information changes.
27
+ - Do not edit generated `.rbs` files or `sig/` artifacts directly unless maintainers explicitly approve it.
28
+
29
+ ## Test-adjacent implementation rules
30
+
31
+ - Add only the code necessary for the requested behavior and its directly related fixes.
32
+ - Reuse existing helpers and patterns before adding new abstractions.
33
+ - Comment code only when the behavior is non-obvious.
34
+ - Do not change established naming conventions without approval.
35
+
36
+ ## Unconfirmed items
37
+
38
+ - Any additional hand-written naming rules beyond Ruby conventions and RuboCop enforcement
@@ -0,0 +1,37 @@
1
+ # Domain
2
+
3
+ ## Repository purpose
4
+
5
+ JobWorkflow is a workflow orchestration library for Ruby on Rails applications. It provides a declarative DSL on top of ActiveJob so applications can define task graphs, dependencies, fan-out work, retries, throttling, and monitoring.
6
+
7
+ ## Core concepts
8
+
9
+ - `Workflow`: the ordered graph of tasks for a job class
10
+ - `Task`: one unit of work in a workflow, optionally depending on other tasks
11
+ - `Arguments`: immutable workflow inputs exposed to tasks through `Context`
12
+ - `Context`: the task-facing object used to read arguments, outputs, runtime helpers, and execution state
13
+ - `Output`: the structured result store for completed task outputs
14
+ - `Runner`: the orchestration layer that executes tasks and updates workflow state
15
+ - `SubTaskJob`: the dedicated async job class used for `enqueue: true` fan-out work
16
+ - `WorkflowStatus` / `JobStatus`: read models for workflow and sub-task execution state
17
+ - Monitoring UI: the Rails engine that visualizes workflow definitions and execution DAGs
18
+
19
+ ## Common terminology
20
+
21
+ - `each task`: a task that fans out over a collection
22
+ - `dependency_wait`: waiting behavior for dependent async work
23
+ - `fan-out`: splitting work into sub-jobs
24
+ - `root execution`: the top-level workflow job, excluding sub-task jobs
25
+
26
+ ## Detailed references
27
+
28
+ - `guides/GETTING_STARTED.md` for the high-level workflow model
29
+ - `guides/DSL_BASICS.md` for task definitions and dependency rules
30
+ - `guides/TASK_OUTPUTS.md` for output flow and downstream consumption
31
+ - `guides/PARALLEL_PROCESSING.md` for fan-out and aggregation behavior
32
+ - `guides/WORKFLOW_STATUS_QUERY.md` for workflow vs job status read models
33
+ - `guides/MONITORING_UI.md` for the monitoring view of root executions and sub-task jobs
34
+
35
+ ## Unconfirmed items
36
+
37
+ - Additional external domain vocabulary used by downstream adopters
@@ -0,0 +1,44 @@
1
+ # Environment
2
+
3
+ ## Required local tools
4
+
5
+ - Ruby and Bundler for gem development
6
+ - SQLite3 for local development and the example app
7
+ - A shell environment that can run the root and example-app Rake tasks
8
+
9
+ ## Root setup
10
+
11
+ ```bash
12
+ bin/setup
13
+ bundle install
14
+ bundle exec rake rbs:install
15
+ ```
16
+
17
+ ## Example app setup
18
+
19
+ From `examples/rails_8_1/`:
20
+
21
+ ```bash
22
+ bundle install
23
+ bundle exec rails db:prepare
24
+ bundle exec rake rbs:install
25
+ ```
26
+
27
+ ## Running the example app
28
+
29
+ - Start the Rails server from `examples/rails_8_1/` with `bin/rails server`
30
+ - Start background job processing with `bin/jobs`
31
+ - Open `/job_workflow` for the monitoring UI and `/jobs` for Mission Control Jobs in the example app
32
+ - For a denser monitoring DAG preview, enqueue `AcceptanceComplexMonitoringDagJob` from `examples/rails_8_1/`
33
+
34
+ ## Useful notes
35
+
36
+ - The example app is the main place to verify real monitoring UI behavior.
37
+ - The example app has its own lockfile and validation commands; treat it as an additional maintained surface.
38
+ - Use `examples/rails_8_1/README.md` for the full preview sequence.
39
+ - Use `guides/GETTING_STARTED.md` for first-time library setup and `guides/MONITORING_UI.md` for monitoring behavior.
40
+
41
+ ## Unconfirmed items
42
+
43
+ - Preferred Ruby version manager for maintainers
44
+ - Any editor or shell configuration the team expects
@@ -0,0 +1,29 @@
1
+ # General
2
+
3
+ ## Core behavior
4
+
5
+ - Respond to repository collaborators in Japanese, even though these agent resource files are written in English.
6
+ - Interpret user instructions literally and keep changes scoped to the requested task.
7
+ - Ask for clarification before making risky, ambiguous, or behavior-changing edits.
8
+ - Prefer existing repository conventions over personal defaults.
9
+
10
+ ## Always do
11
+
12
+ - Read the relevant repository context before editing.
13
+ - Keep changes focused and avoid unrelated cleanup.
14
+ - Report what changed, what was validated, and any unresolved points when finishing work.
15
+
16
+ ## Do not do
17
+
18
+ - Do not create unrelated refactors while working on a user request.
19
+ - Do not assume undocumented behavior when repository sources do not confirm it.
20
+ - Do not treat generated signatures in `sig/generated/` as the primary editing surface.
21
+
22
+ ## Communication
23
+
24
+ - Use concise Japanese in user-facing chat.
25
+ - State uncertainty explicitly instead of presenting guesses as facts.
26
+
27
+ ## Unconfirmed items
28
+
29
+ - Additional organization-wide communication rules beyond this repository
@@ -0,0 +1,20 @@
1
+ # Security
2
+
3
+ ## Secrets and sensitive data
4
+
5
+ - Do not commit API keys, tokens, passwords, private keys, or other secrets.
6
+ - Stop and ask if a value looks like a secret or production credential.
7
+
8
+ ## Restricted operations
9
+
10
+ - Do not modify files outside the repository root.
11
+
12
+ ## Dependency and code safety
13
+
14
+ - Prefer existing repository dependencies and tools over introducing new ones.
15
+ - Avoid risky shell operations, destructive git commands, and history rewriting unless explicitly requested.
16
+ - Surface errors instead of silently swallowing them.
17
+
18
+ ## Unconfirmed items
19
+
20
+ - External secret-management system used by maintainers
@@ -0,0 +1,43 @@
1
+ # Structure
2
+
3
+ ## Repository layout
4
+
5
+ ```text
6
+ .
7
+ ├── app/ # Rails engine assets for the monitoring UI
8
+ ├── bin/ # executable helpers
9
+ ├── config/ # Rails engine and routing configuration
10
+ ├── examples/rails_8_1/ # acceptance Rails application used to verify integration
11
+ ├── guides/ # user-facing documentation
12
+ ├── lib/ # main JobWorkflow library code
13
+ ├── sig/ # generated signatures and type artifacts
14
+ ├── sig-private/ # private type definitions used by Steep
15
+ ├── spec/ # main RSpec suite
16
+ ├── .agents/instructions/ # agent instructions files referenced from AGENTS.md
17
+ └── AGENTS.md # root agent entry point
18
+ ```
19
+
20
+ ## Key areas
21
+
22
+ - `lib/job_workflow/` holds the core DSL, runtime, adapters, monitoring models, and version file.
23
+ - `lib/job_workflow/monitoring/` contains monitoring presenters, registries, and layout helpers.
24
+ - `app/` and `config/routes.rb` support the monitoring UI engine.
25
+ - `examples/rails_8_1/` is a separate validation surface with its own Rake tasks, lockfile, and specs.
26
+ - `examples/rails_8_1/app/jobs/` contains acceptance workflow definitions.
27
+ - `examples/rails_8_1/spec/jobs/` contains acceptance and integration-oriented example-app specs.
28
+ - `guides/` is the documentation index for feature and operational guides.
29
+
30
+ ## Structure expectations
31
+
32
+ - Treat this repository as a single package with an embedded example application, not as a monorepo of independent packages.
33
+ - Keep agent-wide documentation at the root unless a future task explicitly introduces subdirectory-specific AGENTS.md files.
34
+
35
+ ## Documentation entry points
36
+
37
+ - Start with `guides/README.md` to find the right feature guide.
38
+ - Use `guides/MONITORING_UI.md` for monitoring-specific behavior.
39
+ - Use `examples/rails_8_1/README.md` for example-app setup and preview flows.
40
+
41
+ ## Unconfirmed items
42
+
43
+ - Whether additional future example applications should get their own AGENTS.md
@@ -0,0 +1,40 @@
1
+ # Tech Stack
2
+
3
+ ## Languages and frameworks
4
+
5
+ - Ruby `>= 3.1.0` for the gem runtime
6
+ - Rails and ActiveJob for the workflow runtime and monitoring engine integration
7
+ - Solid Queue in the example app for asynchronous execution scenarios
8
+ - SQLite in local and example-app development flows
9
+ - RBS Inline plus Steep for type checking
10
+ - RSpec for tests
11
+ - RuboCop with repository plugins for linting
12
+ - SimpleCov for 100% line and branch coverage enforcement
13
+
14
+ ## Primary commands
15
+
16
+ - Root validation:
17
+ - `bundle exec rake spec`
18
+ - `bundle exec rake lint`
19
+ - `bundle exec rake typecheck`
20
+ - Useful root helpers:
21
+ - `bundle exec rake lint:fix`
22
+ - `bundle exec rake lint:fixall`
23
+ - `bundle exec rake rbs:install`
24
+ - `bundle exec rake rbs:update`
25
+ - `bundle exec rake rbs:inline`
26
+ - Example app validation from `examples/rails_8_1/`:
27
+ - `bundle exec rake spec`
28
+ - `bundle exec rake lint`
29
+ - `bundle exec rake typecheck`
30
+
31
+ ## Architecture summary
32
+
33
+ - `Workflow`, `Task`, `Runner`, `Arguments`, `Context`, and `Output` form the core execution model.
34
+ - Queue adapters isolate runtime-specific job lookup and persistence behavior.
35
+ - Monitoring code lives under `lib/job_workflow/monitoring/` and is rendered through the Rails engine in `app/`.
36
+ - The example Rails app is the main integration harness for real ActiveJob and Solid Queue behavior.
37
+
38
+ ## Important command rule
39
+
40
+ - Use the repository Rake tasks instead of calling `rspec`, `rubocop`, or `steep` directly for final validation.
@@ -0,0 +1,46 @@
1
+ # Testing
2
+
3
+ ## Required validation
4
+
5
+ - Every functional change must include new or updated specs that cover the changed behavior.
6
+ - Root repository changes must pass:
7
+ - `bundle exec rake spec`
8
+ - `bundle exec rake lint`
9
+ - `bundle exec rake typecheck`
10
+ - Root coverage must remain at `100%` line coverage and `100%` branch coverage.
11
+
12
+ ## Example app validation
13
+
14
+ - If a change touches `examples/rails_8_1/`, also run inside that directory:
15
+ - `bundle exec rake spec`
16
+ - `bundle exec rake lint`
17
+ - `bundle exec rake typecheck`
18
+ - Example app coverage must also stay at `100%` line coverage and `100%` branch coverage.
19
+
20
+ ## Validation scope
21
+
22
+ - If the change only touches root library, engine, guides, or specs outside `examples/rails_8_1/`, run the root validation set.
23
+ - If the change touches both root code and `examples/rails_8_1/`, run both validation sets.
24
+ - If the change alters behavior, update the relevant guide examples as well as tests.
25
+
26
+ ## Test-writing rules
27
+
28
+ - Use `bundle exec rake spec`, not `bundle exec rspec`.
29
+ - Define a named subject with `subject(:name)`.
30
+ - Keep `describe` / `context` nesting at three levels or fewer.
31
+ - Prefer one expectation per example unless a matcher like `have_attributes` or a combined matcher makes the assertion a single behavior check.
32
+ - Test through public APIs only; do not use `instance_variable_set`, `instance_variable_get`, or similar reflection in specs.
33
+ - Keep `let` usage lean and split contexts when conditions differ.
34
+
35
+ ## Completion rule
36
+
37
+ - Do not report a code change as ready until the required validation commands for the touched surfaces have succeeded.
38
+
39
+ ## Reference material
40
+
41
+ - Use `guides/TESTING_STRATEGY.md` for testing guidance beyond the mandatory checks.
42
+ - Use `guides/MONITORING_UI.md` and feature-specific guides when behavior-oriented expectations need clarification.
43
+
44
+ ## Unconfirmed items
45
+
46
+ - Whether any additional external CI jobs run outside the repository-local Rake tasks
@@ -0,0 +1,39 @@
1
+ # Workflow
2
+
3
+ ## Branches
4
+
5
+ - Use a dedicated branch for work.
6
+ - Preferred branch prefixes are `feature/<short-desc>` and `fix/<short-desc>`.
7
+
8
+ ## Commits
9
+
10
+ - Use Conventional Commits in `type(scope): short summary` format.
11
+ - Valid types include `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, and `perf`.
12
+ - Keep the subject line within 72 characters.
13
+ - Update `CHANGELOG.md` before creating a commit when the change should be reflected in release notes.
14
+
15
+ ## Pull requests
16
+
17
+ - Keep one PR focused on one logical change.
18
+ - PR creation and merge are normally done by the user unless they explicitly delegate that step.
19
+ - A completion handoff should include validation results, coverage, lint status, typecheck status, major changed files, and any recommended follow-up.
20
+
21
+ ## Before changing behavior
22
+
23
+ - Check `guides/README.md` first to find the relevant feature guide.
24
+ - Use feature guides such as `guides/DSL_BASICS.md`, `guides/TASK_OUTPUTS.md`, `guides/PARALLEL_PROCESSING.md`, `guides/DEPENDENCY_WAIT.md`, and `guides/MONITORING_UI.md` before changing semantics in those areas.
25
+
26
+ ## Release preparation
27
+
28
+ - Record shipped changes in `CHANGELOG.md`, starting from `## [Unreleased]` before they are cut into a release section.
29
+ - Keep version-related files in sync when preparing a release.
30
+
31
+ ## Review expectations
32
+
33
+ - Explain why a change is necessary.
34
+ - Keep PRs small enough to review without mixing unrelated work.
35
+
36
+ ## Unconfirmed items
37
+
38
+ - Reviewer assignment rules outside the repository instructions
39
+ - Whether release tagging always happens from `main`
data/.rubocop.yml CHANGED
@@ -41,7 +41,7 @@ Metrics/BlockLength:
41
41
  Metrics/ClassLength:
42
42
  Enabled: true
43
43
  CountComments: false
44
- Max: 100
44
+ Max: 124
45
45
  CountAsOne:
46
46
  - array
47
47
  - hash
@@ -88,4 +88,3 @@ Style/StringLiteralsInInterpolation:
88
88
 
89
89
  ThreadSafety/ClassAndModuleAttributes:
90
90
  Enabled: false
91
-
data/AGENTS.md ADDED
@@ -0,0 +1,23 @@
1
+ # AGENTS.md
2
+
3
+ This repository uses AGENTS.md as a thin hub. Read the required instructions files before making changes.
4
+
5
+ ## Required instructions
6
+
7
+ - @.agents/instructions/general.md
8
+ - @.agents/instructions/structure.md
9
+ - @.agents/instructions/tech-stack.md
10
+ - @.agents/instructions/security.md
11
+ - @.agents/instructions/testing.md
12
+ - @.agents/instructions/workflow.md
13
+
14
+ ## Load when needed
15
+
16
+ - .agents/instructions/domain.md — JobWorkflow concepts and terminology
17
+ - .agents/instructions/environment.md — local setup and example app workflow
18
+ - .agents/instructions/coding-style.md — design rules, style constraints, and implementation patterns
19
+
20
+ ## Repository notes
21
+
22
+ - Repository-specific reusable agent assets should live under `.agents/skills/`.
23
+ - No subdirectory-level AGENTS.md files are defined at the moment. Use this root entry point unless a later task adds a more specific AGENTS.md.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.6.1] - 2026-06-01
4
+
5
+ ### Fixed
6
+
7
+ - Fix monitoring UI task state rendering so tasks recorded as completed in ActiveJob continuation data no longer appear as `pending` when they have no outputs or sub-task statuses
8
+
9
+ ## [0.6.0] - 2026-05-24
10
+
11
+ ### Added
12
+
13
+ - Add `JobWorkflow::SubTaskJob` for `enqueue: true` task fan-out so each-task sub-jobs run on a dedicated job class instead of reusing the workflow DSL job class directly
14
+ - Add a JobWorkflow monitoring UI engine with an execution DAG overview for browsing workflow definitions, root executions, DAG state, arguments, outputs, fan-out progress, and linked Mission Control Jobs rows
15
+
16
+ ### Changed
17
+
18
+ - **Breaking:** `WorkflowStatus.find` / `find_by` are now root-workflow-only APIs. Sub-task job IDs are excluded and should be tracked via `JobStatus`.
19
+
20
+ ### Fixed
21
+
22
+ - Route enqueued each-task execution through `SubTaskJob`, restoring workflow/task context from the parent workflow job and keeping parent/sub-job identity separate during async execution
23
+ - Extend queue-adapter and workflow-status hydration so monitoring can paginate root workflow executions, hydrate sub-task detail on demand, and keep partially completed fan-out tasks visible as `running` until the workflow actually settles
24
+
25
+ ### Removed
26
+
27
+ - Remove `enqueue: { concurrency: N }`. Async map task fan-out is still controlled by `enqueue`, but execution caps are now configured exclusively with `throttle`.
28
+
3
29
  ## [0.5.0] - 2026-05-13
4
30
 
5
31
  ### Added
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # JobWorkflow
2
2
 
3
- > ⚠️ **Early Stage (v0.5.0):** This library is in active development. APIs and features may change in breaking ways without notice. Use in production at your own risk and expect potential breaking changes in future releases.
3
+ > ⚠️ **Early Stage (v0.6.1):** This library is in active development. APIs and features may change in breaking ways without notice. Use in production at your own risk and expect potential breaking changes in future releases.
4
4
 
5
5
  ## Overview
6
6
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JobWorkflow
4
+ module Monitoring
5
+ # Resolve the host app controller at load time so engine controllers inherit
6
+ # the app's existing authentication and access control hooks.
7
+ class ApplicationController < JobWorkflow::Monitoring.resolved_base_controller_class.constantize
8
+ layout "job_workflow/monitoring/application"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JobWorkflow
4
+ module Monitoring
5
+ class ExecutionsController < ApplicationController
6
+ def index
7
+ @workflow = WorkflowRegistry.find(params[:workflow_job_class_name])
8
+ return render plain: "Workflow definition not found.", status: :not_found if @workflow.nil?
9
+
10
+ @page = ExecutionRegistry.page_for(
11
+ job_class_name: @workflow.name,
12
+ cursor: params[:cursor]
13
+ )
14
+ @executions = @page.executions
15
+ end
16
+
17
+ def show
18
+ @workflow = WorkflowRegistry.find(params[:workflow_job_class_name])
19
+ return render plain: "Workflow definition not found.", status: :not_found if @workflow.nil?
20
+
21
+ @execution = ExecutionRegistry.find(params[:id])
22
+ return if @execution && @execution.job_class_name == @workflow.name
23
+
24
+ render plain: "Workflow execution is no longer available.", status: :not_found
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JobWorkflow
4
+ module Monitoring
5
+ class WorkflowsController < ApplicationController
6
+ def index
7
+ @workflows = Monitoring.workflows
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ <section class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-end gap-3 mb-4">
2
+ <div>
3
+ <div class="text-body-secondary small mb-1">Workflow</div>
4
+ <h1 class="display-6 fw-semibold mb-2"><%= @workflow.name %></h1>
5
+ <p class="text-body-secondary mb-0">Paginated root executions. sub task jobs appear only inside execution detail.</p>
6
+ </div>
7
+ <div>
8
+ <%= link_to "Back to workflows", root_path, class: "btn btn-outline-secondary" %>
9
+ </div>
10
+ </section>
11
+
12
+ <div class="card jw-card">
13
+ <div class="card-body p-0">
14
+ <% if @executions.empty? %>
15
+ <div class="p-4 text-body-secondary">No currently available workflow executions.</div>
16
+ <% else %>
17
+ <div class="table-responsive">
18
+ <table class="table table-hover align-middle mb-0">
19
+ <thead class="table-light">
20
+ <tr>
21
+ <th class="ps-4">Status</th>
22
+ <th>Current task</th>
23
+ <th>Queue</th>
24
+ <th>Job</th>
25
+ <th class="text-end pe-4">Detail</th>
26
+ </tr>
27
+ </thead>
28
+ <tbody>
29
+ <% @executions.each do |execution| %>
30
+ <% status_class = case execution.workflow_status
31
+ when :succeeded then "text-bg-success"
32
+ when :failed then "text-bg-danger"
33
+ when :running then "text-bg-primary"
34
+ else "text-bg-secondary"
35
+ end %>
36
+ <tr>
37
+ <td class="ps-4"><span class="badge <%= status_class %>"><%= execution.workflow_status %></span></td>
38
+ <td><%= execution.current_task_name || "-" %></td>
39
+ <td><span class="jw-mono"><%= execution.queue_name || "-" %></span></td>
40
+ <td class="jw-mono"><%= execution.job_id %></td>
41
+ <td class="text-end pe-4">
42
+ <%= link_to "Open", workflow_execution_path(@workflow.name, execution.job_id), class: "btn btn-sm btn-primary" %>
43
+ </td>
44
+ </tr>
45
+ <% end %>
46
+ </tbody>
47
+ </table>
48
+ </div>
49
+ <% end %>
50
+ </div>
51
+ </div>
52
+
53
+ <% if @page.next_cursor %>
54
+ <div class="d-flex justify-content-end mt-3">
55
+ <%= link_to "Next page", workflow_executions_path(@workflow.name, cursor: @page.next_cursor), class: "btn btn-outline-primary" %>
56
+ </div>
57
+ <% end %>