# 0.6.0

## Added

- [x] Post-processing from the printed `.dat` output, for when the ODB is too large to open — declare a hook with `HookSpec(script_path=..., source='dat', tasks=[...])` and it reads values written by `*NODE PRINT` / `*EL PRINT` (See `./examples/extraction_scripts/get_dat_results.py`)
- [x] Add `ABQflow.datkit` — a generic parser for Abaqus printed tables (`N O D E` / `E L E M E N T` / `E N E R G Y` / `C O N T A C T` output), staged beside `hookkit.py` under the same stdlib-only, Python 2.7-compatible contract. Streams, so `parse(path, increments='last')` costs one increment however long the analysis ran
- [x] Add `examples/extraction_scripts/get_dat_results.py` — a `.dat` hook written exactly like the ODB ones, with `datkit` in place of `odbAccess`
- [x] Add the `abqflow-check-hook` command (`ABQflow.check_hook`) — self-checks a hook script against a real `.odb` / `.dat` / `.inp` before it goes into a `HookSpec`, by staging `hookkit.py` and building the command line through the same `build_script_command` / `extract_json` / `_validate_envelope` the framework uses. Grades Python 2.7 compatibility, sentinel pairing, `None` results, and sidecar CSVs
- [x] Detect a remote job that died without finishing, by checking process liveness alongside the return-code sentinel. The sentinel is written only when the launcher runs to completion, so a reboot, an out-of-memory kill or someone else's `taskkill` used to leave the poll loop waiting out the whole timeout; such a job now reports `died` within a poll interval. An apparent death is confirmed by re-reading the sentinel, since the launcher's last act is to write it
- [x] Split `timeout` into per-stage limits (`Timeouts(solver=, preflight=, compile=, hook=)`). One number used to govern the solver wait, preflight, compilation and every hook at once, so raising it for a long solve also handed a hung hook the same many-hour budget. `solver` now defaults to `None` — no wall-clock cap, which liveness detection makes safe — while the short stages keep finite defaults. A scalar `timeout=` still means the same limit everywhere

## Fixed

- [x] Fix the remote launcher running the solver in the wrong directory when `cd /d` fails — an unmounted drive or a stale path let it carry on regardless, so the files landed somewhere unexpected and `%ERRORLEVEL%` described the wrong thing. The `cd` is now checked before anything else runs, the failure writes a distinct sentinel code (250) plus a readable reason, and the sentinel and console-log paths are absolute so they reach the job directory whatever cmd's working directory turns out to be


# 0.5.1

## Added

- [x] Submit jobs to remote Windows machines over SSH/SFTP (See `./examples/08_RemoteSubmission`)
- [x] Allow the submitting machine to join the pool via `HostSpec.local()`, so a batch can mix local and remote hosts
- [x] Add `paramiko` as an optional `[remote]` extra
- [x] Add detached remote launch with file-based polling in `core/remote_launch.py` - solver survives SSH disconnects instead of dying with the channel


## Fixed

- [x] Supports `hookkit.py` under Python 2.7 (`abaqus python` on Abaqus 2022 and earlier)
- [x] Fix INP files being read with the platform default encoding, which fails on a Chinese-locale Windows when the file is UTF-8
- [x] Fix bare `abaqus_exe` names failing to launch on Windows — `CreateProcess` ignores `PATHEXT`, so `abaqus.bat` is now resolved before launch and an unresolvable name reports which file and how to configure it
- [x] Fix `OdbExtractionStrategy` checking for the ODB on the local filesystem, which made every remote extraction return all-`None`
- [x] Fix artifact paths in hook `common_args` not being mapped to the executing machine
- [x] Fix `*INCLUDE` directives rewritten to local absolute paths, which cannot resolve on another machine; targets are now uploaded once per machine into a content-addressed shared directory instead of once per job
- [x] Add a lock around `AbaqusCalculation._setup_logging`, which was only safe under process isolation

# 0.5.0

## Added

- [x] add JobOutcome processor in `convert.py`
- [x] allow modular workflow (See `./examples/06_SeparateJob`)
- [x] add subroutine support (See `./examples/07_SubroutineJob`)

## Fixed

- [x] Now use physical core when running ABAQUS
- [x] Remove cpus oversubsciption limit. Only gives warning when exceeds cpu limit
- [x] Fix `BatchAbaqusProcessor` log issue, now logs more after running
- [x] Fix Unused Status
- [x] Remove some typos

# 0.4.0

## Added

- [x] Rename project from `abq-flow` to `ABQflow`
- [x] Allow direct INP-based batch runs on existing INP files (See `./examples/03_ExistingInpBatchJob`)
- [x] Add full documentation site (Sphinx + README/README.zh-CN) and expanded examples

## Fixed

- [x] Reframe package structure into `core`/`helpers` submodules
- [x] Fix error extraction during job execution
- [x] Fix example file structure, add dedicated extraction script examples

# 0.3.0

## Added

- [x] Split the `AbaqusCalculation` god-object into `JobContext` (frozen data) + `AbaqusRunner` (service) + Strategy pattern
- [x] Typed `JobSpec` / `PreparationSpec` / `HookSpec` configuration replacing dict-based config (`from_dict` bridge kept for backward compatibility)
- [x] `run_batch()` now returns `list[JobOutcome]` instead of `list[dict]` / `dict[str, dict]`

## Fixed

- [x] Fix structural defects in `AbaqusCalculation` (circular imports, private-method coupling) by splitting data from service
- [x] Custom strategy signatures changed from `(self, context: AbaqusCalculation)` to `(self, ctx: JobContext, runner: AbaqusRunner, logger: Logger)`
- [x] `BatchAbaqusProcessor.__init__` no longer deletes directories or prompts for input; default `duplicate_mode` changed from `'interactive'` to `'fail'`

# 0.2.0

## Added

- [x] Allow multiple extractions within a single script
- [x] Add `tqdm` progress bars
- [x] Support async execution, allow in-time progress bar updates
- [x] Add `StatusManager`, fix batch job naming
- [x] Allow `skip` / `overwrite` / `rename` duplicate-handling modes when creating `AbaqusCalculation` instances

## Fixed

- [x] Fix `StatusManager`
- [x] Improve docstrings

# 0.1.0

## Added

- [x] Initial release: core batch Abaqus automation prototype
