Repository navigation
Blue Team Lane 1: RF-B1, SDLC-1 through SDLC-4 #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,104 +1,243 @@ | ||
| // funcs/sdlc_dispatch_runtime.dag -- compiled SDLC stage dispatch policy. | ||
| // funcs/sdlc_dispatch_runtime.dag -- SDLC stage transition state machine. | ||
| // | ||
| // Each function returns deterministic transition directives for a single | ||
| // lifecycle stage. Rust selects which compiled callable to execute based on | ||
| // the current stage, while side-effects (claim/retry/report updates) remain | ||
| // in the worker runtime. | ||
| // Centralized dispatch policy for the SDLC pipeline. Provides: | ||
| // 1. State machine validation (valid transition check) | ||
| // 2. Next-stage determination from current stage | ||
| // 3. Approval gate detection | ||
| // 4. Terminal state handling | ||
| // 5. Retry budget enforcement | ||
| // | ||
| // The worker (sdlc_worker.dag) calls dispatch_stage() before executing | ||
| // a stage handler. Side-effects (claim/retry/report) remain in the worker. | ||
|
|
||
| module funcs.sdlc_dispatch_runtime | ||
|
|
||
| func dispatch_idea( | ||
| import funcs.sdlc_stages { next_stage_label } | ||
| import std.types { IssueLifecycleStage, NonEmptyStr } | ||
|
|
||
| // ── State machine: valid transitions ───────────────────────────── | ||
|
|
||
| fn valid_next_stage(current: IssueLifecycleStage) -> IssueLifecycleStage { | ||
| match current { | ||
| Idea => Design | ||
| Design => DesignReview | ||
| DesignReview => Accepted | ||
| Accepted => Implementing | ||
| Implementing => CodeReview | ||
| CodeReview => Testing | ||
| Testing => Done | ||
| Done => Done | ||
| } | ||
| } | ||
|
|
||
| fn sdlc_validate_transition(from: IssueLifecycleStage, to: IssueLifecycleStage) -> Bool { | ||
| match from { | ||
| Idea => to == Design | ||
| Design => to == DesignReview | ||
| DesignReview => to == Accepted | ||
| Accepted => to == Implementing | ||
| Implementing => to == CodeReview | ||
| CodeReview => to == Testing | ||
| Testing => to == Done || to == Testing | ||
| Done => false | ||
| } | ||
| } | ||
|
|
||
| fn sdlc_is_terminal(stage: IssueLifecycleStage) -> Bool { | ||
| match stage { | ||
| Done => true | ||
| _ => false | ||
| } | ||
| } | ||
|
|
||
| fn requires_approval(stage: IssueLifecycleStage) -> Bool { | ||
| match stage { | ||
| DesignReview => true | ||
| _ => false | ||
| } | ||
| } | ||
|
|
||
| // ── Unified dispatch function ──────────────────────────────────── | ||
| // Returns transition metadata for the worker to act on. | ||
| // The worker checks should_execute before calling execute_stage. | ||
|
|
||
| fn dispatch_stage( | ||
| current_stage: IssueLifecycleStage, | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: String, | ||
| owner: String, | ||
| repo: String, | ||
| retry_budget_remaining: Int | ||
| ) -> { next_stage: IssueLifecycleStage, should_execute: Bool, awaiting_approval: Bool, terminal: Bool, marker: String, message: String } { | ||
|
|
||
| // Terminal: Done stage has no further transitions | ||
| if sdlc_is_terminal(stage: current_stage) { | ||
| return { | ||
| next_stage: Done, | ||
| should_execute: false, | ||
| awaiting_approval: false, | ||
| terminal: true, | ||
| marker: "", | ||
| message: "Issue already at terminal stage Done." | ||
| } | ||
| } | ||
|
|
||
| // Retry budget exhausted: mark as terminal failure | ||
| if retry_budget_remaining <= 0 { | ||
| return { | ||
| next_stage: current_stage, | ||
| should_execute: false, | ||
| awaiting_approval: false, | ||
| terminal: true, | ||
| marker: "sdlc:terminal-failed:{run_key}", | ||
| message: "Retry budget exhausted for stage {current_stage} on issue {issue_id} in {owner}/{repo}. Marking as terminal failure." | ||
| } | ||
| } | ||
|
|
||
| next = valid_next_stage(current: current_stage) | ||
| needs_approval = requires_approval(stage: current_stage) | ||
| next_label = next_stage_label(current: current_stage) | ||
|
|
||
| return { | ||
| next_stage: next, | ||
| should_execute: true, | ||
| awaiting_approval: needs_approval, | ||
| terminal: false, | ||
| marker: "sdlc:{next_label}:{run_key}", | ||
| message: match current_stage { | ||
| Idea => "Generating design for issue #{issue_id} in {owner}/{repo}" | ||
| Design => "Initiating design review for run_key {run_key}" | ||
| DesignReview => "Awaiting approval for design review on issue #{issue_id}" | ||
| Accepted => "Starting implementation on branch sdlc/issue-{issue_id} for {owner}/{repo} (worker: {worker_id})" | ||
| Implementing => "Creating PR and requesting code review for issue #{issue_id}" | ||
| CodeReview => "Running code review for issue #{issue_id} in {owner}/{repo}" | ||
| Testing => "Running acceptance tests (cargo test + clippy) for issue #{issue_id}" | ||
| Done => "Issue #{issue_id} complete" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // ── Per-stage dispatch functions ───────────────────────────────── | ||
| // Convenience wrappers around dispatch_stage for backward compatibility. | ||
| // Each returns the same record shape as the original stub. | ||
|
|
||
| fn dispatch_idea( | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: Int, | ||
| owner: String, | ||
| repo: String | ||
| ) -> { next_stage: String, awaiting_approval: Bool, marker: String, message: String, value: Json } { | ||
| let d = dispatch_stage( | ||
| current_stage: Idea, run_key: run_key, worker_id: worker_id, | ||
| issue_id: "{issue_id}", owner: owner, repo: repo, retry_budget_remaining: 3 | ||
| ) | ||
| return { | ||
| next_stage: "design", | ||
| awaiting_approval: false, | ||
| marker: "design-marker", | ||
| message: "Generated design prompt", | ||
| value: { "next_stage": "design", "awaiting_approval": false } | ||
| next_stage: "{d.next_stage}", | ||
| awaiting_approval: d.awaiting_approval, | ||
| marker: d.marker, | ||
| message: d.message, | ||
| value: { "next_stage": "{d.next_stage}", "awaiting_approval": d.awaiting_approval, "terminal": d.terminal } | ||
| } | ||
| } | ||
|
|
||
| func dispatch_design( | ||
| fn dispatch_design( | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: Int, | ||
| owner: String, | ||
| repo: String | ||
| ) -> { next_stage: String, awaiting_approval: Bool, marker: String, message: String, value: Json } { | ||
| let d = dispatch_stage( | ||
| current_stage: Design, run_key: run_key, worker_id: worker_id, | ||
| issue_id: "{issue_id}", owner: owner, repo: repo, retry_budget_remaining: 3 | ||
| ) | ||
| return { | ||
| next_stage: "design-review", | ||
| awaiting_approval: false, | ||
| marker: "sdlc:design-review", | ||
| message: "Design review initiated for run_key `{run_key}`", | ||
| value: { "next_stage": "design-review", "awaiting_approval": false } | ||
| next_stage: "{d.next_stage}", | ||
| awaiting_approval: d.awaiting_approval, | ||
| marker: d.marker, | ||
| message: d.message, | ||
| value: { "next_stage": "{d.next_stage}", "awaiting_approval": d.awaiting_approval, "terminal": d.terminal } | ||
| } | ||
| } | ||
|
|
||
| func dispatch_design_review( | ||
| fn dispatch_design_review( | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: Int, | ||
| owner: String, | ||
| repo: String | ||
| ) -> { next_stage: String, awaiting_approval: Bool, marker: String, message: String, value: Json } { | ||
| let d = dispatch_stage( | ||
| current_stage: DesignReview, run_key: run_key, worker_id: worker_id, | ||
| issue_id: "{issue_id}", owner: owner, repo: repo, retry_budget_remaining: 3 | ||
| ) | ||
| return { | ||
| next_stage: "design-review", | ||
| awaiting_approval: true, | ||
| marker: "sdlc:approval-gate", | ||
| message: "Awaiting explicit approval for run_key `{run_key}`; transition to `accepted` after review sign-off.", | ||
| value: { "next_stage": "design-review", "awaiting_approval": true } | ||
| next_stage: "{d.next_stage}", | ||
| awaiting_approval: d.awaiting_approval, | ||
| marker: d.marker, | ||
| message: d.message, | ||
| value: { "next_stage": "{d.next_stage}", "awaiting_approval": d.awaiting_approval, "terminal": d.terminal } | ||
| } | ||
| } | ||
|
|
||
| func dispatch_accepted( | ||
| fn dispatch_accepted( | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: Int, | ||
| owner: String, | ||
| repo: String | ||
| ) -> { next_stage: String, awaiting_approval: Bool, marker: String, message: String, value: Json } { | ||
| let d = dispatch_stage( | ||
| current_stage: Accepted, run_key: run_key, worker_id: worker_id, | ||
| issue_id: "{issue_id}", owner: owner, repo: repo, retry_budget_remaining: 3 | ||
| ) | ||
| return { | ||
| next_stage: "implementation", | ||
| awaiting_approval: false, | ||
| marker: "sdlc:implementation", | ||
| message: "Implementation started on branch `sdlc/issue-{issue_id}` for `{owner}/{repo}` (worker: `{worker_id}`)", | ||
| value: { "next_stage": "implementation", "awaiting_approval": false } | ||
| next_stage: "{d.next_stage}", | ||
| awaiting_approval: d.awaiting_approval, | ||
| marker: d.marker, | ||
| message: d.message, | ||
| value: { "next_stage": "{d.next_stage}", "awaiting_approval": d.awaiting_approval, "terminal": d.terminal } | ||
| } | ||
| } | ||
|
|
||
| func dispatch_implementation( | ||
| fn dispatch_implementation( | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: Int, | ||
| owner: String, | ||
| repo: String | ||
| ) -> { next_stage: String, awaiting_approval: Bool, marker: String, message: String, value: Json } { | ||
| let d = dispatch_stage( | ||
| current_stage: Implementing, run_key: run_key, worker_id: worker_id, | ||
| issue_id: "{issue_id}", owner: owner, repo: repo, retry_budget_remaining: 3 | ||
| ) | ||
| return { | ||
| next_stage: "closed", | ||
| awaiting_approval: false, | ||
| marker: "sdlc:acceptance", | ||
| message: "Acceptance testing and close for run_key `{run_key}` in `{owner}/{repo}` (worker: `{worker_id}`)", | ||
| value: { "next_stage": "closed", "awaiting_approval": false } | ||
| next_stage: "{d.next_stage}", | ||
| awaiting_approval: d.awaiting_approval, | ||
| marker: d.marker, | ||
| message: d.message, | ||
| value: { "next_stage": "{d.next_stage}", "awaiting_approval": d.awaiting_approval, "terminal": d.terminal } | ||
| } | ||
| } | ||
|
|
||
| func dispatch_closed( | ||
| fn dispatch_closed( | ||
| run_key: String, | ||
| worker_id: String, | ||
| issue_id: Int, | ||
| owner: String, | ||
| repo: String | ||
| ) -> { next_stage: String, awaiting_approval: Bool, marker: String, message: String, value: Json } { | ||
| let d = dispatch_stage( | ||
| current_stage: Done, run_key: run_key, worker_id: worker_id, | ||
| issue_id: "{issue_id}", owner: owner, repo: repo, retry_budget_remaining: 3 | ||
| ) | ||
| return { | ||
| next_stage: "closed", | ||
| awaiting_approval: false, | ||
| marker: "", | ||
| message: "", | ||
| value: { "next_stage": "closed", "awaiting_approval": false } | ||
| next_stage: "{d.next_stage}", | ||
| awaiting_approval: d.awaiting_approval, | ||
| marker: d.marker, | ||
| message: d.message, | ||
| value: { "next_stage": "{d.next_stage}", "awaiting_approval": d.awaiting_approval, "terminal": d.terminal } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -470,7 +470,9 @@ func handle_code_review_to_testing( | |
|
|
||
| // ── Stage 7: Testing -> Done ─────────────────────────────────────── | ||
| // Real acceptance testing: run cargo test + cargo clippy on PR branch. | ||
| // Transitions: sdlc:testing -> sdlc:done. | ||
| // On success: merge PR (squash), transition to done. | ||
| // On failure: stay at testing for retry. | ||
| // Transitions: sdlc:testing -> sdlc:done (on pass) or stays at sdlc:testing (on fail). | ||
|
|
||
| func handle_testing_to_done( | ||
| issue_id: NonEmptyStr, | ||
|
|
@@ -500,9 +502,24 @@ func handle_testing_to_done( | |
| false => "FAILED" | ||
| } | ||
|
|
||
| // Conditional merge: only merge PR if all checks pass | ||
| merge_status = if all_passed { | ||
| merge = PullRequest.Merge( | ||
| owner: owner, | ||
| repo: repo, | ||
| number: number, | ||
| merge_method: "squash", | ||
| commit_title: "feat: resolve issue #{number} via SDLC pipeline", | ||
| commit_message: "Automated merge by gunbc SDLC pipeline.\n\nRun key: {run_key}\nCloses #{number}" | ||
| ) | ||
| if merge.merged { "merged (squash)" } else { "merge failed: {merge.message}" } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If Useful? React with 👍 / 👎. |
||
| } else { | ||
| "skipped: tests failed" | ||
| } | ||
|
|
||
| report_body = match all_passed { | ||
| true => "## Acceptance Tests: PASSED\n\n| Check | Status |\n|-------|--------|\n| cargo test | {test_status} |\n| cargo clippy | {clippy_status} |\n\nAll checks passed. Issue complete.\n\n---\n_Tested by gunbc SDLC pipeline_" | ||
| false => "## Acceptance Tests: FAILED\n\n| Check | Status |\n|-------|--------|\n| cargo test | {test_status} |\n| cargo clippy | {clippy_status} |\n\n### Test Output\n```\n{test_result.stderr}\n```\n\n### Clippy Output\n```\n{clippy_result.stderr}\n```\n\n---\n_Tested by gunbc SDLC pipeline_" | ||
| true => "## Acceptance Tests: PASSED\n\n| Check | Status |\n|-------|--------|\n| cargo test | {test_status} |\n| cargo clippy | {clippy_status} |\n| PR merge | {merge_status} |\n\nAll checks passed. PR merged. Issue complete.\n\n---\n_Tested by gunbc SDLC pipeline_" | ||
| false => "## Acceptance Tests: FAILED\n\n| Check | Status |\n|-------|--------|\n| cargo test | {test_status} |\n| cargo clippy | {clippy_status} |\n| PR merge | {merge_status} |\n\n### Test Output\n```\n{test_result.stderr}\n```\n\n### Clippy Output\n```\n{clippy_result.stderr}\n```\n\n---\n_Tested by gunbc SDLC pipeline_" | ||
| } | ||
|
|
||
| // Post result | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sdlc:prefix in dispatch markersnext_stage_label()already returns labels insdlc:<stage>form, so adding anothersdlc:prefix here produces markers likesdlc:sdlc:design:<run_key>. Any consumer expecting canonical marker format for deduping/upserting comments will fail to match these markers.Useful? React with 👍 / 👎.