fgof-devloop Public
fgof-devloop
Watch-driven rebuild, restart, and smoke-loop helpers for modern Fortran tools.
fgof-devloop is intended to be a small standalone library for the reusable
parts of development loops: deciding when file changes should trigger work,
tracking run cycles, modeling restart policy, and layering those decisions
over fgof-watch, fgof-process, and fgof-jobs.
It is part of the FortranGoingOnForty lib-modules
catalog, but it is intended to stand on its own as a normal fpm package.
Current v1 target:
- stable dev-loop option and state types
- deterministic cycle and restart decision helpers
- watch-event shaping that can consume
fgof-watch - process-runner integration that can supervise rebuild and run commands
- long-running service/job restart planning over
fgof-jobs - examples for command-line tools and local service smoke loops
Status
v0.1.0 is released.
Tracked today:
- package layout, CI, and standalone repo setup
- local sprint plan in ignored
.docs/sprints/ - stable option, trigger, cycle, decision, and state types
- pure run-cycle helpers for start, finish, stop, and restart decisions
- deterministic failure policy through
stop_on_failureandmax_failures fgof-watchintegration through shaped event summaries and trigger policy- loop-owned restart filters for directory events and minimum change counts
- watch option projection for debounce polls, hidden-path ignores, and directory-event emission
fgof-processintegration for one-shot build, run, and smoke command supervision- command results that retain full
process_resultoutput, exit, timeout, and error detail fgof-jobsintegration for long-running service ownership, wait observation, cleanup, and restart planning- pipeline-aware job observation that preserves terminal member state during group stop/continue events
- released jobs are treated as unmanaged and will not receive restart/stop/start plans
- tracked examples for watch-driven command cycles and service restart planning
- CI coverage for both
fpm test --verboseandfpm run --example --all - focused model, watch-bridge, process-supervision, job-supervision, and example coverage
Public API Shape
Primary modules:
fgof_devloopfgof_devloop_types
Current public procedures:
clear_devloop_optionsclear_devloop_triggerclear_devloop_cycleclear_devloop_decisionclear_devloop_watch_summaryclear_devloop_command_specclear_devloop_command_resultclear_devloop_supervision_resultclear_devloop_job_specclear_devloop_job_stateclear_devloop_job_plandevloop_backend_nameclear_devloop_statestart_devloopstop_devloopshould_start_on_opendevloop_start_triggerdevloop_change_triggerdevloop_manual_triggerdevloop_summarize_watch_eventsdevloop_watch_failure_summarydevloop_watch_optionsdevloop_watch_triggerdevloop_build_commanddevloop_run_commanddevloop_smoke_commandrun_devloop_commandrun_devloop_cycledevloop_service_jobattach_devloop_jobattach_devloop_pipeline_membersobserve_devloop_jobrelease_devloop_jobdevloop_job_restart_planbegin_devloop_cyclefinish_devloop_cycle
Current semantics:
devloop_optionscarries run-on-start, restart-on-change, directory restart, hidden-path ignore, debounce, stop-on-failure, and max-failure policydevloop_triggerrecords why work should begin, such as start, file change, or manual requestdevloop_watch_summarycondensesfgof-watchevent batches into file, directory, create, modify, remove, move, ignored, and failure countersdevloop_watch_options()projects dev-loop policy intofgof-watchoptions for debounce polls, hidden-path filtering, and directory event emissiondevloop_watch_trigger()turns successful watch summaries into change triggers while suppressing watcher failures, disabled restart-on-change policy, empty batches, directory-only batches when disabled, and batches belowmin_restart_changesdevloop_change_trigger()suppresses nonpositive change counts so empty batches cannot start cycles through the lower-level trigger APIdevloop_build_command(),devloop_run_command(), anddevloop_smoke_command()wrapfgof-processcommands with loop roles and optional process optionsrun_devloop_command()executes one command spec and preserves the rawprocess_result, including stdout, stderr, exit code, timeout state, and process error detailsrun_devloop_cycle()starts a cycle, executes enabled build/run/smoke specs in order, skips later specs after the first failure, and feeds the outcome intofinish_devloop_cycle()devloop_service_job()builds a long-running service/job spec backed byfgof-jobsattach_devloop_job()records an already-launched pid/process group and ownership expectationsobserve_devloop_job()appliesfgof-jobswait results while preserving member-level terminal statedevloop_job_restart_plan()models whether a watched change should stop, start, restart, release, or require terminal handoff for a long-running job; released jobs and release-on-handoff plans return no stop/start/restart actionbegin_devloop_cycle()increments the cycle counter and starts work only when the loop is active, idle, and policy permits the triggerfinish_devloop_cycle()records success or failure and returns an explicit decision to idle, restart, or stop- negative
max_failuresvalues normalize to unlimited failures - negative
debounce_pollsvalues normalize to no debounce - Sprint 05 remains model-first: it plans and observes long-running job ownership, while actual spawning/signaling stays in the launcher layer
Dependency
fgof-devloop depends on fgof-watch v0.1.0 for watch-event types and
watch option projection, fgof-process v0.1.1 for one-shot process
execution, and fgof-jobs v0.1.0 for long-running job ownership and
wait-state modeling:
[dependencies]
fgof-jobs = { git = "https://github.com/FortranGoingOnForty/fgof-jobs.git", tag = "v0.1.0" }
fgof-process = { git = "https://github.com/FortranGoingOnForty/fgof-process.git", tag = "v0.1.1" }
fgof-watch = { git = "https://github.com/FortranGoingOnForty/fgof-watch.git", tag = "v0.1.0" }
Build And Test
fpm test
fpm run --example --all
Examples
Tracked examples live in example/ and are intentionally deterministic:
watch_cycle_demo.f90shapes a synthetic watch batch into a trigger, then runs build and smoke commands throughfgof-processservice_restart_demo.f90models restart and release behavior for a long-running service using an attachedfgof-jobshandle
Supported Platforms
- macOS
- Linux
Boundaries
- focused on reusable development-loop mechanics, not a full CLI app
- should remain useful on its own even if future tools wrap it with UI policy
- watch, process, and job integration should stay layered over stable state transitions
- does not spawn long-running services or send signals directly; callers own
launcher policy and use
devloop_job_restart_plan()as the planning surface - uses tagged dependencies for the released process, watch, and jobs surfaces
License
MIT
View source
| 1 | # fgof-devloop |
| 2 | |
| 3 | Watch-driven rebuild, restart, and smoke-loop helpers for modern Fortran tools. |
| 4 | |
| 5 | `fgof-devloop` is intended to be a small standalone library for the reusable |
| 6 | parts of development loops: deciding when file changes should trigger work, |
| 7 | tracking run cycles, modeling restart policy, and layering those decisions |
| 8 | over `fgof-watch`, `fgof-process`, and `fgof-jobs`. |
| 9 | |
| 10 | It is part of the [FortranGoingOnForty lib-modules](https://github.com/FortranGoingOnForty/lib-modules) |
| 11 | catalog, but it is intended to stand on its own as a normal `fpm` package. |
| 12 | |
| 13 | Current v1 target: |
| 14 | |
| 15 | - stable dev-loop option and state types |
| 16 | - deterministic cycle and restart decision helpers |
| 17 | - watch-event shaping that can consume `fgof-watch` |
| 18 | - process-runner integration that can supervise rebuild and run commands |
| 19 | - long-running service/job restart planning over `fgof-jobs` |
| 20 | - examples for command-line tools and local service smoke loops |
| 21 | |
| 22 | ## Status |
| 23 | |
| 24 | `v0.1.0` is released. |
| 25 | |
| 26 | Tracked today: |
| 27 | |
| 28 | - package layout, CI, and standalone repo setup |
| 29 | - local sprint plan in ignored `.docs/sprints/` |
| 30 | - stable option, trigger, cycle, decision, and state types |
| 31 | - pure run-cycle helpers for start, finish, stop, and restart decisions |
| 32 | - deterministic failure policy through `stop_on_failure` and `max_failures` |
| 33 | - `fgof-watch` integration through shaped event summaries and trigger policy |
| 34 | - loop-owned restart filters for directory events and minimum change counts |
| 35 | - watch option projection for debounce polls, hidden-path ignores, and directory-event emission |
| 36 | - `fgof-process` integration for one-shot build, run, and smoke command supervision |
| 37 | - command results that retain full `process_result` output, exit, timeout, and error detail |
| 38 | - `fgof-jobs` integration for long-running service ownership, wait observation, cleanup, and restart planning |
| 39 | - pipeline-aware job observation that preserves terminal member state during group stop/continue events |
| 40 | - released jobs are treated as unmanaged and will not receive restart/stop/start plans |
| 41 | - tracked examples for watch-driven command cycles and service restart planning |
| 42 | - CI coverage for both `fpm test --verbose` and `fpm run --example --all` |
| 43 | - focused model, watch-bridge, process-supervision, job-supervision, and example coverage |
| 44 | |
| 45 | ## Public API Shape |
| 46 | |
| 47 | Primary modules: |
| 48 | |
| 49 | - `fgof_devloop` |
| 50 | - `fgof_devloop_types` |
| 51 | |
| 52 | Current public procedures: |
| 53 | |
| 54 | - `clear_devloop_options` |
| 55 | - `clear_devloop_trigger` |
| 56 | - `clear_devloop_cycle` |
| 57 | - `clear_devloop_decision` |
| 58 | - `clear_devloop_watch_summary` |
| 59 | - `clear_devloop_command_spec` |
| 60 | - `clear_devloop_command_result` |
| 61 | - `clear_devloop_supervision_result` |
| 62 | - `clear_devloop_job_spec` |
| 63 | - `clear_devloop_job_state` |
| 64 | - `clear_devloop_job_plan` |
| 65 | - `devloop_backend_name` |
| 66 | - `clear_devloop_state` |
| 67 | - `start_devloop` |
| 68 | - `stop_devloop` |
| 69 | - `should_start_on_open` |
| 70 | - `devloop_start_trigger` |
| 71 | - `devloop_change_trigger` |
| 72 | - `devloop_manual_trigger` |
| 73 | - `devloop_summarize_watch_events` |
| 74 | - `devloop_watch_failure_summary` |
| 75 | - `devloop_watch_options` |
| 76 | - `devloop_watch_trigger` |
| 77 | - `devloop_build_command` |
| 78 | - `devloop_run_command` |
| 79 | - `devloop_smoke_command` |
| 80 | - `run_devloop_command` |
| 81 | - `run_devloop_cycle` |
| 82 | - `devloop_service_job` |
| 83 | - `attach_devloop_job` |
| 84 | - `attach_devloop_pipeline_members` |
| 85 | - `observe_devloop_job` |
| 86 | - `release_devloop_job` |
| 87 | - `devloop_job_restart_plan` |
| 88 | - `begin_devloop_cycle` |
| 89 | - `finish_devloop_cycle` |
| 90 | |
| 91 | Current semantics: |
| 92 | |
| 93 | - `devloop_options` carries run-on-start, restart-on-change, directory restart, hidden-path ignore, debounce, stop-on-failure, and max-failure policy |
| 94 | - `devloop_trigger` records why work should begin, such as start, file change, or manual request |
| 95 | - `devloop_watch_summary` condenses `fgof-watch` event batches into file, directory, create, modify, remove, move, ignored, and failure counters |
| 96 | - `devloop_watch_options()` projects dev-loop policy into `fgof-watch` options for debounce polls, hidden-path filtering, and directory event emission |
| 97 | - `devloop_watch_trigger()` turns successful watch summaries into change triggers while suppressing watcher failures, disabled restart-on-change policy, empty batches, directory-only batches when disabled, and batches below `min_restart_changes` |
| 98 | - `devloop_change_trigger()` suppresses nonpositive change counts so empty batches cannot start cycles through the lower-level trigger API |
| 99 | - `devloop_build_command()`, `devloop_run_command()`, and `devloop_smoke_command()` wrap `fgof-process` commands with loop roles and optional process options |
| 100 | - `run_devloop_command()` executes one command spec and preserves the raw `process_result`, including stdout, stderr, exit code, timeout state, and process error details |
| 101 | - `run_devloop_cycle()` starts a cycle, executes enabled build/run/smoke specs in order, skips later specs after the first failure, and feeds the outcome into `finish_devloop_cycle()` |
| 102 | - `devloop_service_job()` builds a long-running service/job spec backed by `fgof-jobs` |
| 103 | - `attach_devloop_job()` records an already-launched pid/process group and ownership expectations |
| 104 | - `observe_devloop_job()` applies `fgof-jobs` wait results while preserving member-level terminal state |
| 105 | - `devloop_job_restart_plan()` models whether a watched change should stop, start, restart, release, or require terminal handoff for a long-running job; released jobs and release-on-handoff plans return no stop/start/restart action |
| 106 | - `begin_devloop_cycle()` increments the cycle counter and starts work only when the loop is active, idle, and policy permits the trigger |
| 107 | - `finish_devloop_cycle()` records success or failure and returns an explicit decision to idle, restart, or stop |
| 108 | - negative `max_failures` values normalize to unlimited failures |
| 109 | - negative `debounce_polls` values normalize to no debounce |
| 110 | - Sprint 05 remains model-first: it plans and observes long-running job ownership, while actual spawning/signaling stays in the launcher layer |
| 111 | |
| 112 | ## Dependency |
| 113 | |
| 114 | `fgof-devloop` depends on `fgof-watch` `v0.1.0` for watch-event types and |
| 115 | watch option projection, `fgof-process` `v0.1.1` for one-shot process |
| 116 | execution, and `fgof-jobs` `v0.1.0` for long-running job ownership and |
| 117 | wait-state modeling: |
| 118 | |
| 119 | ```toml |
| 120 | [dependencies] |
| 121 | fgof-jobs = { git = "https://github.com/FortranGoingOnForty/fgof-jobs.git", tag = "v0.1.0" } |
| 122 | fgof-process = { git = "https://github.com/FortranGoingOnForty/fgof-process.git", tag = "v0.1.1" } |
| 123 | fgof-watch = { git = "https://github.com/FortranGoingOnForty/fgof-watch.git", tag = "v0.1.0" } |
| 124 | ``` |
| 125 | |
| 126 | ## Build And Test |
| 127 | |
| 128 | ```bash |
| 129 | fpm test |
| 130 | fpm run --example --all |
| 131 | ``` |
| 132 | |
| 133 | ## Examples |
| 134 | |
| 135 | Tracked examples live in `example/` and are intentionally deterministic: |
| 136 | |
| 137 | - `watch_cycle_demo.f90` shapes a synthetic watch batch into a trigger, then runs build and smoke commands through `fgof-process` |
| 138 | - `service_restart_demo.f90` models restart and release behavior for a long-running service using an attached `fgof-jobs` handle |
| 139 | |
| 140 | ## Supported Platforms |
| 141 | |
| 142 | - macOS |
| 143 | - Linux |
| 144 | |
| 145 | ## Boundaries |
| 146 | |
| 147 | - focused on reusable development-loop mechanics, not a full CLI app |
| 148 | - should remain useful on its own even if future tools wrap it with UI policy |
| 149 | - watch, process, and job integration should stay layered over stable state |
| 150 | transitions |
| 151 | - does not spawn long-running services or send signals directly; callers own |
| 152 | launcher policy and use `devloop_job_restart_plan()` as the planning surface |
| 153 | - uses tagged dependencies for the released process, watch, and jobs surfaces |
| 154 | |
| 155 | ## License |
| 156 | |
| 157 | MIT |