{"action":"created","comment":{"url":"https://api.github.com/repos/square/workflow/pulls/comments/243705875","pull_request_review_id":187556011,"id":243705875,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI0MzcwNTg3NQ==","diff_hunk":"@@ -109,4 +111,15 @@ class AuthReactor(\n \n   private val SubmitLogin.userInputErrorMessage: String\n     get() = if (email.indexOf('@') < 0) \"Invalid address\" else \"\"\n+\n+  companion object {\n+    /**\n+     * Returns a [RunWorkflow] handle that will instruct a [WorkflowPool] to call\n+     * [launch] and start a workflow.\n+     */\n+    fun getStarter(\n+      state: AuthState = AuthState.startingState()\n+    ): RunWorkflow<AuthState, AuthEvent, String> =\n+      RunWorkflow(AuthReactor::class.makeWorkflowId(), state)","path":"sample-auth-common/src/main/java/com/squareup/sample/authworkflow/AuthReactor.kt","position":24,"original_position":24,"commit_id":"d19a4a98d99c506032b5430381338fbca0bbabc7","original_commit_id":"d19a4a98d99c506032b5430381338fbca0bbabc7","user":{"login":"rjrjr","id":1884445,"node_id":"MDQ6VXNlcjE4ODQ0NDU=","avatar_url":"https://avatars0.githubusercontent.com/u/1884445?v=4","gravatar_id":"","url":"https://api.github.com/users/rjrjr","html_url":"https://github.com/rjrjr","followers_url":"https://api.github.com/users/rjrjr/followers","following_url":"https://api.github.com/users/rjrjr/following{/other_user}","gists_url":"https://api.github.com/users/rjrjr/gists{/gist_id}","starred_url":"https://api.github.com/users/rjrjr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rjrjr/subscriptions","organizations_url":"https://api.github.com/users/rjrjr/orgs","repos_url":"https://api.github.com/users/rjrjr/repos","events_url":"https://api.github.com/users/rjrjr/events{/privacy}","received_events_url":"https://api.github.com/users/rjrjr/received_events","type":"User","site_admin":false},"body":"Will give that a shot.","created_at":"2018-12-21T22:30:55Z","updated_at":"2018-12-21T22:30:55Z","html_url":"https://github.com/square/workflow/pull/98#discussion_r243705875","pull_request_url":"https://api.github.com/repos/square/workflow/pulls/98","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/square/workflow/pulls/comments/243705875"},"html":{"href":"https://github.com/square/workflow/pull/98#discussion_r243705875"},"pull_request":{"href":"https://api.github.com/repos/square/workflow/pulls/98"}},"in_reply_to_id":243704760},"pull_request":{"url":"https://api.github.com/repos/square/workflow/pulls/98","id":238560664,"node_id":"MDExOlB1bGxSZXF1ZXN0MjM4NTYwNjY0","html_url":"https://github.com/square/workflow/pull/98","diff_url":"https://github.com/square/workflow/pull/98.diff","patch_url":"https://github.com/square/workflow/pull/98.patch","issue_url":"https://api.github.com/repos/square/workflow/issues/98","number":98,"state":"open","locked":false,"title":"Goodbye Delegating, hello WorkflowHandle","user":{"login":"rjrjr","id":1884445,"node_id":"MDQ6VXNlcjE4ODQ0NDU=","avatar_url":"https://avatars0.githubusercontent.com/u/1884445?v=4","gravatar_id":"","url":"https://api.github.com/users/rjrjr","html_url":"https://github.com/rjrjr","followers_url":"https://api.github.com/users/rjrjr/followers","following_url":"https://api.github.com/users/rjrjr/following{/other_user}","gists_url":"https://api.github.com/users/rjrjr/gists{/gist_id}","starred_url":"https://api.github.com/users/rjrjr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rjrjr/subscriptions","organizations_url":"https://api.github.com/users/rjrjr/orgs","repos_url":"https://api.github.com/users/rjrjr/repos","events_url":"https://api.github.com/users/rjrjr/events{/privacy}","received_events_url":"https://api.github.com/users/rjrjr/received_events","type":"User","site_admin":false},"body":"Closes #87\r\n\r\n`Delegating` was a confusing interface, an artifact of how I backed into\r\nstitching together composite workflow states.\r\n\r\nIt's replaced by `WorkflowHandle`, a sealed class with two concrete types:\r\n\r\n - `RunningWorkflow`, which includes the workflows current (or bootstrap) state\r\n - `FinishedWorkflow`, which includes its result\r\n\r\nCompositing now looks a lot like it did when we were still hanging live\r\nworkflows off of state objects, but everything remains a value type.\r\n\r\nWe also introduce a convention of reactor companion objects providing\r\na `run() : RunningWorkflow<...>` methods, for easy bootstrapping.\r\n\r\nE.g., this is the state of the `RunGameReactor` while it's\r\ndelegating to the `TakeTurnsReactor`:\r\n\r\n```\r\n  internal data class Playing(\r\n    val takingTurns: RunningWorkflow<Turn, TakeTurnsEvent, CompletedGame>\r\n  ) : RunGameState() {\r\n    constructor(turn: Turn) : this(TakeTurnsReactor.run(turn))\r\n  }\r\n```\r\n\r\nThis is how that reactor behaves in that state:\r\n\r\n```\r\n    is Playing -> events.select {\r\n      workflows.onWorkflowUpdate(state.takingTurns) {\r\n        when (it) {\r\n          is RunningWorkflow -> EnterState(Playing(it))\r\n          is FinishedWorkflow -> when (it.result.ending) {\r\n            Quitted -> EnterState(MaybeQuitting(it.result))\r\n            else -> EnterState(GameOver(it.result))\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n```\r\n\r\nand here is how it's rendered:\r\n\r\n```\r\n      is Playing -> {\r\n        return TakeTurnsRenderer\r\n            .render(state.takingTurns.state, workflows.input(state.takingTurns), workflows)\r\n            .let { MainAndModalScreen(it) }\r\n      }\r\n```\r\n\r\nA composite workflow running several others in parallel might look like this:\r\n\r\n```\r\n  data class LeftAndRightState(\r\n    val leftWorkflow: RunningWorkflow<LeftState, LeftEvent, LeftResult>,\r\n    val rightWorkflow: RunningWorkflow<RigthState, RightEvent, RightResult>,\r\n  ) : LeftAndRightState()\r\n```\r\n\r\n```\r\n    is LeftAndRightState -> events.select {\r\n      workflows.onWorkflowUpdate(state.leftWorfklow) {\r\n        when (it) {\r\n          is RunningWorkflow -> EnterState(state.copy(leftWorkflow = it))\r\n          is FinishedWorkflow -> when (it.result.ending) { ... }\r\n        }\r\n      }\r\n\r\n      workflows.onWorkflowUpdate(state.rightWorfklow) {\r\n        when (it) {\r\n          is RunningWorkflow -> EnterState(state.copy(rightWorkflow = it))\r\n          is FinishedWorkflow -> when (it.result.ending) { ... }\r\n        }\r\n      }\r\n    }\r\n\r\n```\r\n\r\nAlso tidies up `ShellReactor` and `ShellState` a bit, to make them more\r\nconsistent with the others. This is done with an eye toward #97.","created_at":"2018-12-13T23:00:32Z","updated_at":"2018-12-21T22:30:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ab4b51d179d1c58bb5a580aca20d986196901fa0","assignee":null,"assignees":[],"requested_reviewers":[{"login":"zach-klippenstein","id":101754,"node_id":"MDQ6VXNlcjEwMTc1NA==","avatar_url":"https://avatars2.githubusercontent.com/u/101754?v=4","gravatar_id":"","url":"https://api.github.com/users/zach-klippenstein","html_url":"https://github.com/zach-klippenstein","followers_url":"https://api.github.com/users/zach-klippenstein/followers","following_url":"https://api.github.com/users/zach-klippenstein/following{/other_user}","gists_url":"https://api.github.com/users/zach-klippenstein/gists{/gist_id}","starred_url":"https://api.github.com/users/zach-klippenstein/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zach-klippenstein/subscriptions","organizations_url":"https://api.github.com/users/zach-klippenstein/orgs","repos_url":"https://api.github.com/users/zach-klippenstein/repos","events_url":"https://api.github.com/users/zach-klippenstein/events{/privacy}","received_events_url":"https://api.github.com/users/zach-klippenstein/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":{"url":"https://api.github.com/repos/square/workflow/milestones/6","html_url":"https://github.com/square/workflow/milestone/6","labels_url":"https://api.github.com/repos/square/workflow/milestones/6/labels","id":3888047,"node_id":"MDk6TWlsZXN0b25lMzg4ODA0Nw==","number":6,"title":"v0.6.0","description":null,"creator":{"login":"rjrjr","id":1884445,"node_id":"MDQ6VXNlcjE4ODQ0NDU=","avatar_url":"https://avatars0.githubusercontent.com/u/1884445?v=4","gravatar_id":"","url":"https://api.github.com/users/rjrjr","html_url":"https://github.com/rjrjr","followers_url":"https://api.github.com/users/rjrjr/followers","following_url":"https://api.github.com/users/rjrjr/following{/other_user}","gists_url":"https://api.github.com/users/rjrjr/gists{/gist_id}","starred_url":"https://api.github.com/users/rjrjr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rjrjr/subscriptions","organizations_url":"https://api.github.com/users/rjrjr/orgs","repos_url":"https://api.github.com/users/rjrjr/repos","events_url":"https://api.github.com/users/rjrjr/events{/privacy}","received_events_url":"https://api.github.com/users/rjrjr/received_events","type":"User","site_admin":false},"open_issues":6,"closed_issues":8,"state":"open","created_at":"2018-12-10T23:29:34Z","updated_at":"2018-12-21T20:09:17Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/square/workflow/pulls/98/commits","review_comments_url":"https://api.github.com/repos/square/workflow/pulls/98/comments","review_comment_url":"https://api.github.com/repos/square/workflow/pulls/comments{/number}","comments_url":"https://api.github.com/repos/square/workflow/issues/98/comments","statuses_url":"https://api.github.com/repos/square/workflow/statuses/d19a4a98d99c506032b5430381338fbca0bbabc7","head":{"label":"square:ray/87-delegating-is-weird","ref":"ray/87-delegating-is-weird","sha":"d19a4a98d99c506032b5430381338fbca0bbabc7","user":{"login":"square","id":82592,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgyNTky","avatar_url":"https://avatars0.githubusercontent.com/u/82592?v=4","gravatar_id":"","url":"https://api.github.com/users/square","html_url":"https://github.com/square","followers_url":"https://api.github.com/users/square/followers","following_url":"https://api.github.com/users/square/following{/other_user}","gists_url":"https://api.github.com/users/square/gists{/gist_id}","starred_url":"https://api.github.com/users/square/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/square/subscriptions","organizations_url":"https://api.github.com/users/square/orgs","repos_url":"https://api.github.com/users/square/repos","events_url":"https://api.github.com/users/square/events{/privacy}","received_events_url":"https://api.github.com/users/square/received_events","type":"Organization","site_admin":false},"repo":{"id":157799999,"node_id":"MDEwOlJlcG9zaXRvcnkxNTc3OTk5OTk=","name":"workflow","full_name":"square/workflow","private":false,"owner":{"login":"square","id":82592,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgyNTky","avatar_url":"https://avatars0.githubusercontent.com/u/82592?v=4","gravatar_id":"","url":"https://api.github.com/users/square","html_url":"https://github.com/square","followers_url":"https://api.github.com/users/square/followers","following_url":"https://api.github.com/users/square/following{/other_user}","gists_url":"https://api.github.com/users/square/gists{/gist_id}","starred_url":"https://api.github.com/users/square/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/square/subscriptions","organizations_url":"https://api.github.com/users/square/orgs","repos_url":"https://api.github.com/users/square/repos","events_url":"https://api.github.com/users/square/events{/privacy}","received_events_url":"https://api.github.com/users/square/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/square/workflow","description":"A library for making composable state machines, and UIs driven by those state machines.","fork":false,"url":"https://api.github.com/repos/square/workflow","forks_url":"https://api.github.com/repos/square/workflow/forks","keys_url":"https://api.github.com/repos/square/workflow/keys{/key_id}","collaborators_url":"https://api.github.com/repos/square/workflow/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/square/workflow/teams","hooks_url":"https://api.github.com/repos/square/workflow/hooks","issue_events_url":"https://api.github.com/repos/square/workflow/issues/events{/number}","events_url":"https://api.github.com/repos/square/workflow/events","assignees_url":"https://api.github.com/repos/square/workflow/assignees{/user}","branches_url":"https://api.github.com/repos/square/workflow/branches{/branch}","tags_url":"https://api.github.com/repos/square/workflow/tags","blobs_url":"https://api.github.com/repos/square/workflow/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/square/workflow/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/square/workflow/git/refs{/sha}","trees_url":"https://api.github.com/repos/square/workflow/git/trees{/sha}","statuses_url":"https://api.github.com/repos/square/workflow/statuses/{sha}","languages_url":"https://api.github.com/repos/square/workflow/languages","stargazers_url":"https://api.github.com/repos/square/workflow/stargazers","contributors_url":"https://api.github.com/repos/square/workflow/contributors","subscribers_url":"https://api.github.com/repos/square/workflow/subscribers","subscription_url":"https://api.github.com/repos/square/workflow/subscription","commits_url":"https://api.github.com/repos/square/workflow/commits{/sha}","git_commits_url":"https://api.github.com/repos/square/workflow/git/commits{/sha}","comments_url":"https://api.github.com/repos/square/workflow/comments{/number}","issue_comment_url":"https://api.github.com/repos/square/workflow/issues/comments{/number}","contents_url":"https://api.github.com/repos/square/workflow/contents/{+path}","compare_url":"https://api.github.com/repos/square/workflow/compare/{base}...{head}","merges_url":"https://api.github.com/repos/square/workflow/merges","archive_url":"https://api.github.com/repos/square/workflow/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/square/workflow/downloads","issues_url":"https://api.github.com/repos/square/workflow/issues{/number}","pulls_url":"https://api.github.com/repos/square/workflow/pulls{/number}","milestones_url":"https://api.github.com/repos/square/workflow/milestones{/number}","notifications_url":"https://api.github.com/repos/square/workflow/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/square/workflow/labels{/name}","releases_url":"https://api.github.com/repos/square/workflow/releases{/id}","deployments_url":"https://api.github.com/repos/square/workflow/deployments","created_at":"2018-11-16T02:16:30Z","updated_at":"2018-12-21T09:14:29Z","pushed_at":"2018-12-21T02:14:42Z","git_url":"git://github.com/square/workflow.git","ssh_url":"git@github.com:square/workflow.git","clone_url":"https://github.com/square/workflow.git","svn_url":"https://github.com/square/workflow","homepage":"","size":367,"stargazers_count":213,"watchers_count":213,"language":"Kotlin","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"archived":false,"open_issues_count":43,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":7,"open_issues":43,"watchers":213,"default_branch":"master"}},"base":{"label":"square:master","ref":"master","sha":"3cfa2d62f7c17ef508ecf7a05571b57987525a6f","user":{"login":"square","id":82592,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgyNTky","avatar_url":"https://avatars0.githubusercontent.com/u/82592?v=4","gravatar_id":"","url":"https://api.github.com/users/square","html_url":"https://github.com/square","followers_url":"https://api.github.com/users/square/followers","following_url":"https://api.github.com/users/square/following{/other_user}","gists_url":"https://api.github.com/users/square/gists{/gist_id}","starred_url":"https://api.github.com/users/square/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/square/subscriptions","organizations_url":"https://api.github.com/users/square/orgs","repos_url":"https://api.github.com/users/square/repos","events_url":"https://api.github.com/users/square/events{/privacy}","received_events_url":"https://api.github.com/users/square/received_events","type":"Organization","site_admin":false},"repo":{"id":157799999,"node_id":"MDEwOlJlcG9zaXRvcnkxNTc3OTk5OTk=","name":"workflow","full_name":"square/workflow","private":false,"owner":{"login":"square","id":82592,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgyNTky","avatar_url":"https://avatars0.githubusercontent.com/u/82592?v=4","gravatar_id":"","url":"https://api.github.com/users/square","html_url":"https://github.com/square","followers_url":"https://api.github.com/users/square/followers","following_url":"https://api.github.com/users/square/following{/other_user}","gists_url":"https://api.github.com/users/square/gists{/gist_id}","starred_url":"https://api.github.com/users/square/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/square/subscriptions","organizations_url":"https://api.github.com/users/square/orgs","repos_url":"https://api.github.com/users/square/repos","events_url":"https://api.github.com/users/square/events{/privacy}","received_events_url":"https://api.github.com/users/square/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/square/workflow","description":"A library for making composable state machines, and UIs driven by those state machines.","fork":false,"url":"https://api.github.com/repos/square/workflow","forks_url":"https://api.github.com/repos/square/workflow/forks","keys_url":"https://api.github.com/repos/square/workflow/keys{/key_id}","collaborators_url":"https://api.github.com/repos/square/workflow/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/square/workflow/teams","hooks_url":"https://api.github.com/repos/square/workflow/hooks","issue_events_url":"https://api.github.com/repos/square/workflow/issues/events{/number}","events_url":"https://api.github.com/repos/square/workflow/events","assignees_url":"https://api.github.com/repos/square/workflow/assignees{/user}","branches_url":"https://api.github.com/repos/square/workflow/branches{/branch}","tags_url":"https://api.github.com/repos/square/workflow/tags","blobs_url":"https://api.github.com/repos/square/workflow/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/square/workflow/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/square/workflow/git/refs{/sha}","trees_url":"https://api.github.com/repos/square/workflow/git/trees{/sha}","statuses_url":"https://api.github.com/repos/square/workflow/statuses/{sha}","languages_url":"https://api.github.com/repos/square/workflow/languages","stargazers_url":"https://api.github.com/repos/square/workflow/stargazers","contributors_url":"https://api.github.com/repos/square/workflow/contributors","subscribers_url":"https://api.github.com/repos/square/workflow/subscribers","subscription_url":"https://api.github.com/repos/square/workflow/subscription","commits_url":"https://api.github.com/repos/square/workflow/commits{/sha}","git_commits_url":"https://api.github.com/repos/square/workflow/git/commits{/sha}","comments_url":"https://api.github.com/repos/square/workflow/comments{/number}","issue_comment_url":"https://api.github.com/repos/square/workflow/issues/comments{/number}","contents_url":"https://api.github.com/repos/square/workflow/contents/{+path}","compare_url":"https://api.github.com/repos/square/workflow/compare/{base}...{head}","merges_url":"https://api.github.com/repos/square/workflow/merges","archive_url":"https://api.github.com/repos/square/workflow/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/square/workflow/downloads","issues_url":"https://api.github.com/repos/square/workflow/issues{/number}","pulls_url":"https://api.github.com/repos/square/workflow/pulls{/number}","milestones_url":"https://api.github.com/repos/square/workflow/milestones{/number}","notifications_url":"https://api.github.com/repos/square/workflow/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/square/workflow/labels{/name}","releases_url":"https://api.github.com/repos/square/workflow/releases{/id}","deployments_url":"https://api.github.com/repos/square/workflow/deployments","created_at":"2018-11-16T02:16:30Z","updated_at":"2018-12-21T09:14:29Z","pushed_at":"2018-12-21T02:14:42Z","git_url":"git://github.com/square/workflow.git","ssh_url":"git@github.com:square/workflow.git","clone_url":"https://github.com/square/workflow.git","svn_url":"https://github.com/square/workflow","homepage":"","size":367,"stargazers_count":213,"watchers_count":213,"language":"Kotlin","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"archived":false,"open_issues_count":43,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":7,"open_issues":43,"watchers":213,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/square/workflow/pulls/98"},"html":{"href":"https://github.com/square/workflow/pull/98"},"issue":{"href":"https://api.github.com/repos/square/workflow/issues/98"},"comments":{"href":"https://api.github.com/repos/square/workflow/issues/98/comments"},"review_comments":{"href":"https://api.github.com/repos/square/workflow/pulls/98/comments"},"review_comment":{"href":"https://api.github.com/repos/square/workflow/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/square/workflow/pulls/98/commits"},"statuses":{"href":"https://api.github.com/repos/square/workflow/statuses/d19a4a98d99c506032b5430381338fbca0bbabc7"}},"author_association":"COLLABORATOR"}}
{"actor":{"display_login":"rjrjr"}}