{"id":31929923,"url":"https://github.com/j-mueller/ernie","last_synced_at":"2025-10-14T03:54:17.313Z","repository":{"id":38411526,"uuid":"506572071","full_name":"j-mueller/ernie","owner":"j-mueller","description":"Project planning","archived":false,"fork":false,"pushed_at":"2025-02-14T16:00:11.000Z","size":114,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-14T16:27:19.433Z","etag":null,"topics":["haskell","haskell-application","pert","planning","project","project-management"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/j-mueller.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-23T09:13:59.000Z","updated_at":"2025-02-14T16:00:13.000Z","dependencies_parsed_at":"2025-02-14T16:35:38.215Z","dependency_job_id":null,"html_url":"https://github.com/j-mueller/ernie","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/j-mueller/ernie","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mueller%2Fernie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mueller%2Fernie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mueller%2Fernie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mueller%2Fernie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/j-mueller","download_url":"https://codeload.github.com/j-mueller/ernie/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j-mueller%2Fernie/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279017767,"owners_count":26086145,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["haskell","haskell-application","pert","planning","project","project-management"],"created_at":"2025-10-14T03:54:15.903Z","updated_at":"2025-10-14T03:54:17.306Z","avatar_url":"https://github.com/j-mueller.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ernie\n\n[PERT](https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique) Project planning in Haskell. Generates a PERT chart and computes the critical path and duration quantiles based on simulations.\n\n![docs/example.svg](docs/example.svg)\n\n## Usage\n\n* There is a CLI that takes task lists (in YAML) and produces PERT charts (in DOT format). The simplest way to run it is `ernie -f project.yaml`. The YAML file has a list of tasks with dependencies and estimates:\n\n```yaml\n- name: Build backend\n  estimate: [0.5, 1.5, 4]\n- name: Build frontend\n  estimate: [2, 4.5, 7]\n  depends:\n    - Build backend\n  group: Phase 1\n- name: Write docs (1)\n  key: D\n  estimate: [3, 4, 9]\n  depends:\n    - Build backend\n  group: Phase 1\n- name: User testing\n  estimate: [3, 5, 8]\n  depends:\n    - Build frontend\n  group: Phase 1\n- name: Write docs (2)\n  estimate: [2, 4, 9]\n  depends:\n    - D\n    - Build frontend\n  group: Phase 1\n- name: Deploy\n  estimate: [3, 3.5, 8]\n  depends:\n    - User testing\n    - Write docs (2)\n```\n\nThe resulting chart shows the dependencies, PERT estimates, and simulation output for each task:\n\n![docs/legend.png](docs/legend.png)\n\n* You can also use it as a Haskell library, see [`Ernie.Example`](https://github.com/j-mueller/ernie/blob/main/src/ernie/lib/Ernie/Example.hs).\n\n## Design Choices\n\nTask durations are entered as PERT estimates, but internally we treat them as probability distributions. As a result we get a distribution of possible realisations of the entire project (this distribution can be sampled from using [`Ernie.Sample.sample`](https://github.com/j-mueller/ernie/blob/main/src/ernie/lib/Ernie/Sample.hs)). The probabilistic approach has some consequences for how we calculate durations.\n\n1. The *critical path* in a PERT chart is usually defined as the longest path from start to finish. The name comes from the fact that a delay in a task on this critical path invariably results in a delay of the entire project. However, if you think about a diamond-shaped dependency (like the example above), it is clear that either of the two tasks in the middle can be on the critical path, depending on which of them takes longer. So in the probabilistic setting the critical path is a distribution, not a single path. We account for this by computing a \"probability of being on the critical path\" for each task. This is the _CP_ value in the charts.\n2. PERT assumes that *minimum and maximum values* for task durations can be determined. From a risk management perspective it doesn't make sense to specify absolute min/max values for task durations - anyone who has ever done any programming knows that the true upper bound of every task is infinity (and the lower bound is 0). Some people use estimates of the 5th and 95th quantile. This is generally preferrable, but in the context of PERT, those estimates are then transformed into a regular PERT estimate with upper and lower bounds (see for example [this blog](https://towardsdatascience.com/python-scenario-analysis-modeling-expert-estimates-with-the-beta-pert-distribution-22a5e90cfa79)). The [transformation that's currently used](https://github.com/j-mueller/ernie/blob/main/src/ernie/lib/Ernie/PERT.hs#L57-L69) in `ernie` still has the finite boundaries problem but I'm hoping to tackle it soon, together with the addition of some actual risk measures for project duration.\n\n## Features (planned)\n\n* Critical path: milestones\n* Risk measures\n* Export samples to CSV\n\nMaybe features\n\n* Calendar - map project days to calendar days\n* Resource planning (maybe?)\n* Combine plan with progress data\n\n## Packages\n\n* `ernie` Implements PERT charts\n* `floyd-warshall` Implements the [Floyd-Warshall algorithm](https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm). Based on a [blog post by Russell O'Connor](r6.ca/blog/20110808T035622Z.html)\n\n## Contributing\n\nContributions are welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj-mueller%2Fernie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fj-mueller%2Fernie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj-mueller%2Fernie/lists"}