Skip to content

Record safe job and script outcomes in unified sessions - #72146

Merged
pelikhan merged 6 commits into
mainfrom
copilot/implement-outcome-status-exposure
Oct 26, 2026
Merged

pelikhan merged 6 commits into
mainfrom
copilot/implement-outcome-status-exposure

Conversation

Copilot AI commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Expose execution status and canonical resource URIs from custom safe jobs and scripts so conclusion can include them in the unified session.

  • Outcome contracts
    • Safe jobs support optional outputs.status and outputs.url mappings.
    • Safe scripts returning { success: true, url } persist successful execution evidence in the manifest.
  • Conclusion collection
    • Record safe-job outcomes as safe_output.result events.
    • Project only declared status/URL outputs; preserve existing result-only dependency metadata.
    • Prevent failed, cancelled, skipped, staged, or deferred operations from claiming successful resource creation.
  • Authoring guidance
    • Update developer and grader-design skills, reference documentation, and affected workflow locks.

Safe-job mappings reference execution-step outputs:

outputs:
  status: ${{ steps.publish.outputs.status }}
  url: ${{ steps.publish.outputs.url }}

status accepts success, failure, cancelled, or skipped; absent status falls back to the Actions job result. url identifies the canonical resource returned by the service, not an agent-supplied target.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan October 26, 2026 16:49
@pelikhan
pelikhan marked this pull request as ready for review October 26, 2026 16:54
Copilot AI max review requested due to automatic review settings October 26, 2026 16:54
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from Test Quality Sentinel · sonnet50 · ~14 AIC · ⌖ ~18 AIC · ◇ ~8 AIC · ⊞ 12.2K · ◷

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

Commit pushed: 2a1e0ae

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Ponytail Reviewer

Outcome: reported_no_action

The agent completed and reported no action. A no-op output alone does not verify that all required work was completed or that publication was possible.

Agent messages are omitted from this comment. The category uses structured run status, not interpretation of agent prose.

Generated from Ponytail Reviewer · gpt56 · ~10 AIC · ⌖ ~6 AIC · ⊞ 14.8K · ◷

Generated by Ponytail Reviewer for #72146

@github-actions

Copy link
Copy Markdown
Contributor

🔎 PR Code Quality Reviewer is reviewing code quality for this pull request...

Comment thread actions/setup/js/unified_session.cjs

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

The new safe-job URI collector accepts arbitrary absolute URL schemes via new URL(), including executable or local schemes such as (redacted) (redacted) and file:. Restrict schemes before persisting and rendering resource evidence.

The specialist pass was unavailable because its file-read invocation was denied; this review is based on the pre-fetched diff and targeted source inspection. Inline publication was blocked by workflow permissions, so no inline comments were published.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt50 · ~3 AIC · ⌖ ~1 AIC · ⊞ 1.6K
Comment /review to run again

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (290 new lines in pkg/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/72146-record-safe-job-and-script-outcomes-in-unified-sessions.md. Review and complete it before merging.

Decision captured in the draft: Add an opt-in outcome contract. Safe jobs can declare outputs.status and outputs.url, and safe scripts can return { success: true, url }. The conclusion job projects only these declared outputs into safe_output.result session events. A URL counts as evidence only when the outcome succeeded and the URL validates.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch. It was generated from the PR diff.
  2. Complete the missing sections. Check the alternatives (inferring outcomes from the job result only, forwarding all outputs, or having custom jobs write manifest entries) and the deciders marked [TODO: verify].
  3. Commit the finalized ADR to docs/adr/ on your branch.
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-72146: Record Safe Job and Script Outcomes in Unified Sessions

After the PR body links an ADR, this gate will run again and check that the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context: What is the problem? What forces are at play?
  • Decision: What did you decide? Why?
  • Alternatives Considered: What else could have been done?
  • Consequences: What are the trade-offs (positive and negative)?

ADRs are stored in docs/adr/ and numbered by PR number.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · pi · opus55 · ~31 AIC · ⌖ ~42 AIC · ⊞ 1.9K · ◷
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /tdd and /codebase-design to review the safe-job/script outcome recording work. No actionable issues found — the change is well-scoped and heavily tested.

📋 Key Themes & Highlights

What was reviewed

  • actions/setup/js/unified_session.cjs (safe-job outcome projection): validates job names, status values, and resource URLs with explicit fail-closed warnings (invalid_safe_job_names, invalid_safe_job_status, invalid_safe_job_url) rather than silently accepting forged data. Authoritative Actions job result always overrides a reported success from outputs.status, which correctly prevents a compromised step from claiming success after a job failure.
  • pkg/workflow/notify_comment.go (buildUsageSafeJobResultsEnv): projects only declared status/url outputs per job into the conclusion env, keeping private needs outputs and unrelated jobs out of scope — confirmed by TestSafeJobOutcomeProjectionOnlyReferencesDeclaredOutputs and TestConclusionSafeJobOutcomeAllowlist.
  • actions/setup/js/safe_output_manifest.cjs (extractCreatedItemFromResult): correctly excludes skipped/deferred/cancelled/staged/success:false results from being counted as created resources, even when a URL is present — this closes a real gap where a staged/failed operation could previously have looked like a successful creation.
  • URL values pass through existing redactManifestValue/secret-redaction before being written to the manifest, and the unified-session collector rejects URLs with embedded control characters or userinfo (uri.username/uri.password), guarding against injection via forged step outputs.

Test coverage

  • Go: TestSafeJobOutcomeOutputsPropagation, TestConclusionSafeJobOutcomeAllowlist, TestConclusionSafeJobOutcomesPreserveAllJobResults, TestSafeJobOutcomeProjectionOnlyReferencesDeclaredOutputs, and pkg/parser/schema_safe_job_outputs_test.go all pass locally.
  • JS: new actions/setup/js/safe_output_script_outcomes.test.cjs and additions to unified_session.test.cjs cover malformed/forged status, URL redaction, and legacy-shape compatibility (could not execute vitest in this sandbox due to a network/cert restriction on npm install, so JS coverage was verified by inspection only).
  • Docs (safe-outputs-runtime.md, shared-safe-jobs.md, custom-safe-outputs.md) and skill files (developer-internals, operational-value-designer) were updated consistently with the new outputs.status/outputs.url contract.

Positive highlights

  • ✅ Fail-closed validation throughout (name/status/URL) with warnings instead of exceptions or silent corruption
  • ✅ Authoritative job result cannot be overridden by a forged success status
  • ✅ Non-applied outcomes (skipped/deferred/cancelled/staged/failed) never register as created resources, even with a URL present
  • ✅ Minimal, surgical projection of only declared outputs into the conclusion job env

No blocking issues identified; approving.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · ~81 AIC · ⌖ ~19 AIC · ⊞ 10.2K
Comment /matt to run again

Comment thread actions/setup/js/unified_session.cjs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Outcome handling can miscount artifacts and label preparation as successful execution, and an affected compiler golden remains stale.

4 open issues
What changed in this PR

Updates gh-aw’s compiler and safe-output runtime to capture custom job and script execution outcomes in unified conclusion sessions.

Changes:

  • Adds optional safe-job status and resource URI mappings, projecting only declared outputs.
  • Persists applied script outcomes and displays execution status in session summaries.
  • Adds regression coverage, authoring guidance, and updated workflow locks.
File Description
pkg/​workflow/​safe_jobs.go Parses and propagates safe-job output mappings.
pkg/​workflow/​safe_job_outcomes_test.go Tests output propagation and conclusion projection.
pkg/​workflow/​notify_comment.go Supplies configured safe-job outcomes to conclusion.
pkg/​parser/​schemas/​main_workflow_schema.json Defines optional status and URL mappings.
pkg/​parser/​schema_safe_job_outputs_test.go Tests accepted and rejected output configurations.
docs/​src/​content/​docs/​reference/​custom-safe-outputs.md Documents job and script outcome contracts.
actions/​setup/​js/​unified_session.test.cjs Tests outcome collection and validation.
actions/​setup/​js/​unified_session.cjs Collects safe-job result events.
actions/​setup/​js/​unified_session_render.test.cjs Tests status and URI rendering.
actions/​setup/​js/​unified_session_render.cjs Displays safe-output execution status.
actions/​setup/​js/​types/​safe-output-script.d.ts Documents script returns and permits void results.
actions/​setup/​js/​types/​handler-factory.d.ts Defines resource URI and non-applied result flags.
actions/​setup/​js/​safe_output_script_outcomes.test.cjs Tests script outcome persistence and suppression.
actions/​setup/​js/​safe_output_manifest.test.cjs Updates successful manifest expectations.
actions/​setup/​js/​safe_output_manifest.cjs Records explicit success and suppresses non-applied results.
actions/​setup/​js/​safe_output_handler_manager.test.cjs Updates finalized-review manifest expectations.
.github/​workflows/​smoke-copilot.lock.yml Adds safe-job outcome collection variables.
.github/​workflows/​smoke-copilot-arm.lock.yml Adds safe-job outcome collection variables.
.github/​workflows/​smoke-copilot-aoai-entra.lock.yml Adds safe-job outcome collection variables.
.github/​workflows/​smoke-copilot-aoai-apikey.lock.yml Adds safe-job outcome collection variables.
.github/​workflows/​mcp-inspector.lock.yml Adds Slack-job outcome collection variables.
.github/​workflows/​daily-choice-test.lock.yml Adds environment-job outcome collection variables.
.github/​workflows/​aw-issue-clustering.lock.yml Adds publishing-job outcome collection variables.
.github/​skills/​operational-value-designer/​SKILL.md Explains outcome evidence for graders.
.github/​skills/​developer-internals/​SKILL.md Documents internal outcome collection contracts.
.github/​aw/​shared-safe-jobs.md Adds shared-job evidence guidance.
.github/​aw/​safe-outputs-runtime.md Describes job mappings and script return values.

Review effort: Max

Comment thread actions/setup/js/safe_output_manifest.cjs
Comment thread actions/setup/js/unified_session.cjs
Comment thread pkg/workflow/notify_comment.go
Comment thread actions/setup/js/safe_output_manifest.cjs
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot address the following outstanding work in one pass:

  1. Update this branch with the latest main using make merge-main, resolving any conflicts and preserving the intended changes.
  2. Review (actions/setup/js/unified_session.cjs:782): Sensitive information disclosure risk: actions/setup/js/unified_session.cjs persists custom safe-job outputs.url into safe_output.result events after only minimal validation (no whitespace/control chars; no URL userinfo), so signed/credential-bearing resource URIs (for example, pre-signed URLs or query-token URLs returned by external services) can be written to usage/aw_session.jsonl and rendered in conclusions without stripping/normalizing credentials. Consider rejecting or stripping URL search/hash components, or otherwise preventing credential-bearing URIs from being published as execution ... - Record safe job and script outcomes in unified sessions #72146 (comment)
  3. Review (actions/setup/js/unified_session.cjs:779): Sensitive information disclosure risk: collectUnifiedSession records safe-job outputs.url into usage/aw_session.jsonl without applying the manifest-style secret redaction, so signed URLs / embedded tokens returned as 'canonical' URIs by external services can be persisted and later exposed via session artifacts/rendering. The current validation only rejects control characters and URL credentials; it does not mask or reject other secret-bearing URL components (e.g., query tokens). - Record safe job and script outcomes in unified sessions #72146 (comment)
  4. Review (actions/setup/js/safe_output_manifest.cjs:301): [P2] Do not mark custom-action preparation as applied success. This extractor also receives results from safe_output_action_handler.cjs, which returns success: true after exporting the action payload, before the generated uses: step runs. Adding status: "success" here turns that preparation record into successful execution evidence even if the actual action later fails or is skipped; the manifest upload uses always(). Defer outcome recording for these preparation results and derive the final outcome from the action step instead. - Record safe job and script outcomes in unified sessions #72146 (comment)
  5. Review (actions/setup/js/unified_session.cjs:789): createSessionLookups() in grader_session.cjs:156 counts every safe_output.result, so skipped, failed, and cancelled safe jobs now increase the default artifact-production score. A requested custom job is also counted twice because safe_output_handler_manager.cjs:1175–1196 already writes a dispatch entry to the manifest. Keep the outcome events, but exclude explicit non-success outcomes and superseded dispatch entries from artifact accounting while preserving genuine legacy results, with regression coverage for both cases. - Record safe job and script outcomes in unified sessions #72146 (comment)
  6. Review (pkg/workflow/notify_comment.go:135): The new environment entries change the compiled output for the existing smoke-copilot golden fixture, but pkg/workflow/testdata/TestWasmGolden_CompileFixtures/smoke-copilot.golden:2535–2538 still goes directly from the grader variables to GH_AW_JOB_DURATIONS. TestWasmGolden_CompileFixtures compares the complete normalized YAML, and its normalization does not remove these entries, so the snapshot comparison will fail. Please regenerate and include the affected compiler goldens alongside the workflow locks. - Record safe job and script outcomes in unified sessions #72146 (comment)
  7. Review (actions/setup/js/safe_output_manifest.cjs:301): Finalized PR review comments reach this extractor through reviewResult.review_comments without per-item success, so newly applied comments are recorded without status. Graders following the new guidance to filter successful outcomes will exclude those resources. In the confirmed-success path at safe_output_handler_manager.cjs:2218, explicitly mark each finalized comment successful before logging it rather than inferring success from identity fields. - Record safe job and script outcomes in unified sessions #72146 (comment)
  8. Fix failing check build-wasm (FAILURE): https://github.com/github/gh-aw/actions/runs/40364916036/job/121730165748.
  9. Fix failing check impacted-go-tests (FAILURE): https://github.com/github/gh-aw/actions/runs/40364916036/job/121730165531.
  10. Fix failing check JS Tests (shard 1/4) (FAILURE): https://github.com/github/gh-aw/actions/runs/40364915918/job/121730199773.

Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI.

Sous-chef head: 2a1e0ae
Sous-chef work: 02175154c7bac91aab5ec34be73bd62f1d3b9ea1f3727b95be7f284ebffd2c24 126fd48a764b8b8d7b1fea8f486520d4e8efaeb181eb1d3af126ad5e435b1036 1ecb2c5a63380b4e671e856264d8f94b22f3c44ccc5117497e9308fdeebe2093 42e5d572d9d75b7168fe7d0aeda0717cc07e65ed240f6d299e6fec661214f1ac 5b73b2014cbfecb7c083441d2e6556046b16c99c25b70780e69e5249398c099a 694beb3c5be8c0f575f7db5704679fc3a4382fa03f43449de3ed0933f4d294c7 70ff6ecd06af00e89084076feec51e0a21386ffd2b0d8da88d896c1bf1a06518 7274f539b03aeebec767c1a84199afe6fe05b3e9eb129f16f860d462f746429b 8acb61a077717e3a460018aacdfde96fd489f77606cd36169e2328d9079b75bb
Sous-chef state: 6f9a1c3152fcc37339d7c587cb1d5762026a391c1330308ed76143916801ddb4

Generated by 👨‍🍳 PR Sous Chef · pi · haiku45 · ~6 AIC · ⌖ ~17 AIC · ⊞ 1.1K · ◷
Comment /souschef to run again

pelikhan and others added 2 commits October 26, 2026 10:45
…come-status-exposure

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Integrate origin/main at e03dba1, including the deterministic setup-action resolver tests. Regenerate compiled workflows from the merged sources and preserve both safe-job outcome and memory-save session evidence.

Give script outcome tests explicit GitHub runtime fixtures and verify closed pull requests still suppress script effects.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v1.0.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants