Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .agents/pm/history/pm-github-f1ev.jsonl

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions .agents/pm/issues/pm-github-f1ev.toon
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
id: pm-github-f1ev
title: Refuse closeout when required-check metadata is unverified
description: "Fix https://github.com/unbraind/pm-github/issues/138. Require complete protection metadata or explicit caller-declared contexts; harden caller permissions."
type: Issue
status: in_progress
priority: 1
tags[2]: closeout,validation
created_at: "2026-10-16T16:04:00.890Z"
updated_at: "2026-10-16T21:41:48.600Z"
author: codex-agent
acceptance_criteria: Unavailable metadata without declarations never closes or publishes; declared contexts require success; metadata-backed behavior remains unchanged; npm and Bun release gates pass.
comments[21]{created_at,author,text}:
"2026-10-16T16:04:15.081Z",codex-agent,"Plan: distinguish unavailable protection metadata from a readable empty policy. Refuse with required_checks_unverified unless required-checks declares contexts; retain readable app-bound requirements. Exercise real command and workflow shell against injected HTTP evidence and real trackers. Keep workflow edits minimal around open PR #139."
"2026-10-16T16:08:21.292Z",codex-agent,"Implementation distinguishes metadata gaps from a readable empty policy. required_checks_unverified blocks workflow publication; required-checks verifies declared contexts plus readable app-bound requirements. Regression coverage uses actual workflow bash, a packed extension, injected HTTP APIs, real SDK tracker mutations and an isolated Git remote. Caller write scopes now belong only to gated-closeout."
"2026-10-16T16:10:06.013Z",codex-agent,"Behavioural revert proof: restored only checkCloseoutHead to its previous implementation (retaining the added argument for compilation), rebuilt dist, and ran node --test --test-name-pattern='required-check metadata boundary (undeclared|missing) ' test/closeout-workflow.test.ts. Both tests failed: each observed closed=1 where closed=0 was required (0 passed, 2 failed). Fixed function restored and rebuilt. This exercises the packed command and real workflow rather than SDK mocks."
"2026-10-16T16:11:08.008Z",codex-agent,"Workflow revert proof: removed only required_checks_unverified from the real workflow refusal guard and ran node --test --test-name-pattern='required-check metadata boundary undeclared ' test/closeout-workflow.test.ts. The regression failed (0 passed, 1 failed): workflow exit was 0 instead of required refusal exit 1. Guard restored. Head-function revert separately proved unsafe closures for both absent and missing declarations."
"2026-10-16T16:16:08.002Z",codex-agent,"The real workflow regression caught CLI normalization: the host passes requiredChecks while direct core callers use required-checks. Normalize both spellings before validating declarations. The initial linked run reported 4 passed and 5 failed; successful declarations had been ignored. The fix and refusal diagnostic compatibility are now being revalidated before final gates."
"2026-10-16T16:20:35.758Z",codex-agent,"Pinned pm linked test run passed 9/9, zero failures, skips, cancellations or todos. Exact command: npm run build && npm run build:test && node --test --test-name-pattern=\"required-check metadata boundary|declared contexts|declared names\" test/closeout.test.ts test/closeout-workflow.test.ts. Covers default refusal/no publication, missing/neutral/skipped/pending declarations, successful declared closure, readable metadata precedence, exact context names, latest legacy statuses, optional failures and preserved app bindings. Both flag spellings now work through the actual command. Earlier pre-fix full runs were stopped and will not be used as gate evidence."
"2026-10-16T16:45:11.663Z",codex-agent,"Fresh npm run release:check passed in a clean HOME with GIT_CONFIG_GLOBAL=/dev/null and GIT_CONFIG_NOSYSTEM=1: 711/711 tests, zero failures/skips/cancellations/todos. Exact coverage across 13 authored modules: lines and statements 10082/10082, functions 256/256, branches 2858/2858, all four dimensions 100 percent at unchanged thresholds. Typecheck, build, docstrings, lint, zero duplication, privacy, production audit (zero vulnerabilities), package dry-run, changelog and publish-attestation gates passed. Clean-home pm health --strict-exit --require-merge-drivers also passed; normal host health reports an environment-specific extension version skew and existing stale-item warnings. Bun release gate is running next."
"2026-10-16T17:04:25.496Z",codex-agent,"bun run release:check passed in the same clean-home/Git identity environment: 711/711 tests, zero failures/skips/cancellations/todos, 13 authored modules with exact 100/100/100/100 coverage (10082 lines/statements, 256 functions, 2858 branches). All remaining release gates passed at unchanged thresholds. Both behavioral revert proofs and the passing 9/9 real-command boundary run are recorded above. Caller declarations must remain aligned with required contexts; no release or downstream adoption is part of this change. Preparing the review PR for issue #138; item remains in_progress and will not be closed."
"2026-10-16T17:05:41.112Z",codex-agent,PR #139 merged during validation. Rebased onto main commit 6d9cc23 and resolved the caller-template conflict by preserving the self-versioned release SHA/tag comment plus this change's job-only permissions and required-checks input. No self-versioning implementation was changed. Previous 711/711 npm and Bun receipts predate this integration; rerunning the full gates on the rebased branch before delivery.
"2026-10-16T17:41:09.873Z",codex-agent,"Rebased acceptance on main 6d9cc23: npm run release:check passed 747/747 tests with zero failures/skips/cancellations/todos. Exact coverage remains 13 modules, 10082/10082 lines and statements, 256/256 functions, 2858/2858 branches (100/100/100/100; thresholds unchanged). All release gates passed. Dedicated integration checks also passed: node --test test/self-versioned-workflows.test.ts (36/36) and node --test --test-name-pattern='closeout contract' test/closeout-workflow.test.ts (1/1). The rebased Bun gate is now running."
"2026-10-16T18:06:25.089Z",codex-agent,"Final rebased acceptance: npm run release:check and bun run release:check both passed 747/747 tests, zero failures/skips/cancellations/todos, exact 100/100/100/100 coverage across 13 authored modules (10082 lines/statements, 256 functions, 2858 branches). All release gates passed at unchanged thresholds on the implementation rebased over #139. Behavioral head-function and workflow-guard revert proofs remain recorded above; real-command boundary tests passed 9/9. Ready for review; no release, merge, downstream adoption or item close is performed. Caller-declared context lists must stay aligned with required checks."
"2026-10-16T19:13:43.207Z",codex-agent,"Round 1: address declared-policy success wording. Keep head_checks_passed and rule=declared stable; describe only caller-declared success and unavailable repository required-check metadata in the gate reason and structured evidence. Update README and real-workflow assertions, prove failures by reverting each changed function separately, then run both release gates at unchanged thresholds. The branch already contains origin/main; no merge is needed."
"2026-10-16T19:15:42.418Z",codex-agent,"Round 1 behavioral revert proof: restoring only checkCloseoutHead from the pre-review HEAD, rebuilding, and running node --test --test-name-pattern='declared contexts' test/closeout.test.ts fails exactly 1/1 test on the old overstated gate reason. Restoring only checkEvidence, rebuilding, and running node --test --test-name-pattern='required-check metadata boundary success' test/closeout-workflow.test.ts fails exactly 1/1 real-workflow test on persisted actual_result. Each function was restored after its proof and the fixed build succeeds. Pinned pm test pm-github-f1ev --run --progress passed all 9/9 linked boundary tests. Codes remain head_checks_passed with rule=declared; README documents this contract."
"2026-10-16T19:35:17.666Z",codex-agent,"Round 1 npm acceptance: CI-identity-isolated npm run release:check passed 747/747 tests with zero failures/skips/cancellations/todos. Coverage is exact 100/100/100/100 across 13 authored modules: 10083/10083 lines and statements, 256/256 functions, 2858/2858 branches. All release gates passed at unchanged thresholds. CI-style pinned tracker health also passes; normal-home health reports local extension host version skew, with no tracked integrity/history drift. Bun release gate is running next."
"2026-10-16T19:53:20.313Z",codex-agent,"Round 1 final acceptance: npm run release:check and bun run release:check both passed 747/747 tests with zero failures/skips/cancellations/todos using isolated CI-style Git identity. Both measured exact 100/100/100/100 coverage across 13 authored modules (10083 lines/statements, 256 functions, 2858 branches) at unchanged thresholds, with all static, privacy, audit, package, changelog and attestation gates passing. The fixed linked boundary suite passed 9/9; independent function revert proofs are recorded above. Declared-only success now explicitly states that repository required-check metadata was unavailable, without changing head_checks_passed or rule=declared. Caller declarations still require maintenance to match repository policy. Ready to push PR #140; item remains in progress for orchestrator verification."
"2026-10-16T20:39:26.384Z",codex-agent,"Round 2: replace whitespace splitting with one trimmed required context per line, dropping empty lines. Preserve the quoted newline-joined workflow argument, update CLI help and caller examples, and exercise exact names plus literal shell-shaped names through real workflow bash and SDK trackers. Record behavioural revert proof, then run unchanged npm and Bun release gates."
"2026-10-16T20:43:48.686Z",codex-agent,"Round 2 behavioural revert proof: restored only the required-context parsing stanza inside runCloseout to the pre-review repeated(...).flatMap(value => value.split(/\\s+/)) implementation, retaining all new tests and other changes. After npm run build, node --test --test-name-pattern=\"newline required contexts\" test/closeout-workflow.test.ts failed all 5/5 tests (0 passed; closed=0 instead of 1): single spaced name, spaces/parentheses/slashes, fleet example, empty lines/trimming, and literal shell-shaped names. Restored the line parser and rebuilt successfully. The fixed focused suite passed 18/18 with no skips or cancellations."
"2026-10-16T20:46:05.570Z",codex-agent,"The first pinned linked-test run hit its already-loaded default 120-second timeout before completion, with no assertion failures in completed cases. Set the new linked entry to timeout_seconds=1800 and rerun with an explicit --timeout 1800. This timeout is missing acceptance evidence, not a pass."
"2026-10-16T20:49:00.145Z",codex-agent,"Pinned node_modules/.bin/pm test pm-github-f1ev --run --progress --only-last --timeout 1800 passed the new linked command: 18/18 tests, zero failures/skips/cancellations/todos, no timeout. Test-result tracking is disabled by project policy, so this comment preserves the completed acceptance receipt without changing that policy."
"2026-10-16T21:13:33.378Z",codex-agent,"Round 2 npm run release:check passed with isolated CI-style Git identity: 754/754 tests, zero failures/skips/cancellations/todos. Exact 100/100/100/100 coverage across 13 authored modules: 10090/10090 lines and statements, 257/257 functions, 2866/2866 branches. All static, privacy, audit, package, changelog and attestation gates passed at unchanged thresholds. Tracker health passed with advisory telemetry/stale-item findings. Starting the Bun release gate on unchanged code."
"2026-10-16T21:41:47.426Z",codex-agent,"Round 2 final local acceptance: npm run release:check and bun run release:check both passed 754/754 tests with zero failures/skips/cancellations/todos using isolated CI-style Git identity. Both measured exact 100/100/100/100 coverage across 13 authored modules (10090 lines/statements, 257 functions, 2866 branches), at unchanged thresholds; all static, privacy, audit, package, changelog and attestation gates passed. The pinned linked suite passed 18/18 after replacing its default timeout with 1800 seconds. The 5/5 failing behavioural revert proof is recorded above. required-checks now preserves one trimmed literal context per line, drops blank lines, and retains safe quoted transport. README, CLI help and caller template show the new contract, including test (22) and test (26). No new PM CLI/SDK defect was identified. Caller declarations must still match repository policy. Ready to push PR #140; GitHub checks will be polled without thread replies or mentions. Item remains in progress for orchestrator verification."
files[5]{path,scope}:
.github/workflows/pm-github-closeout.yml,project
closeout.ts,project
index.ts,project
test/closeout-workflow.test.ts,project
test/closeout.test.ts,project
tests[2]:
- command: "npm run build && npm run build:test && node --test --test-name-pattern=\"required-check metadata boundary|declared contexts|declared names\" test/closeout.test.ts test/closeout-workflow.test.ts"
scope: project
timeout_seconds: 1800
provenance:
author: codex-agent
created_at: "2026-10-16T16:10:42.723Z"
source_kind: local_mutation
source_ref: fix/closeout-required-checks-unverified
- command: "npm run build && npm run build:test && node --test --test-name-pattern=\"newline|required-check metadata boundary|declared contexts|declared names|invalid selectors|closeout contract\" test/closeout.test.ts test/closeout-workflow.test.ts"
scope: project
timeout_seconds: 1800
provenance:
author: codex-agent
created_at: "2026-10-16T20:40:51.494Z"
source_kind: local_mutation
source_ref: fix/closeout-required-checks-unverified
updated_by: codex-agent
updated_at: "2026-10-16T20:44:12.196Z"
docs[2]{path,scope}:
docs/closeout-workflow-caller.yml,project
README.md,project
body: ""
17 changes: 14 additions & 3 deletions .github/workflows/pm-github-closeout.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ on:
type: string
required: false
default: "ci.yml"
required-checks:
description: "One required context name per line; spaces are preserved and blank lines ignored; used when protection metadata is unavailable"
type: string
required: false
default: ""
node-version:
description: "Node.js version for the pm CLI"
type: string
Expand Down Expand Up @@ -59,6 +64,7 @@ jobs:
REQUESTED_PM_GITHUB_VERSION: ${{ inputs.pm-github-version }}
NPM_PROJECT_DIR: ${{ inputs.npm-project-dir }}
POST_CLOSEOUT_SCRIPT: ${{ inputs.post-closeout-script }}
REQUIRED_CHECKS: ${{ inputs.required-checks }}
CI_WORKFLOWS: ${{ inputs.ci-workflows }}
CALLING_REPOSITORY: ${{ github.repository }}
steps:
Expand Down Expand Up @@ -283,16 +289,21 @@ jobs:
set -euo pipefail
# Full history catches up after missed schedules; the command skips terminal items.
# Keep the report private until the proposed change has passed the privacy gate.
if ! pm github closeout --repo "${REPOSITORY}" --since 1970-01-01 --apply --json > "${RUNNER_TEMP}/pm-github-closeout.json" 2> "${RUNNER_TEMP}/pm-github-closeout.err"; then
required_args=()
# Forward the newline-joined list as one literal argument; TypeScript parses lines.
if [[ -n "${REQUIRED_CHECKS:-}" ]]; then
required_args+=(--required-checks "${REQUIRED_CHECKS}")
fi
if ! pm github closeout --repo "${REPOSITORY}" --since 1970-01-01 --apply --json "${required_args[@]}" > "${RUNNER_TEMP}/pm-github-closeout.json" 2> "${RUNNER_TEMP}/pm-github-closeout.err"; then
echo "::error::Closeout refused; check token read access to pull requests, checks and branch rules, and tracker close validation. No branch was published."
exit 1
fi
jq -e '.command == "github closeout" and .dry_run == false and .failed == 0 and (.closed | type == "number")' "${RUNNER_TEMP}/pm-github-closeout.json" >/dev/null
# Only a local tracker refusal makes missing head evidence actionable.
# Foreign, terminal, excluded and unlinked PRs cannot block this run.
jq -e 'all(.plan[]; (.code | type) == "string")' "${RUNNER_TEMP}/pm-github-closeout.json" >/dev/null
if jq -e 'any(.plan[]; .action == "skip" and .code == "head_evidence_unavailable")' "${RUNNER_TEMP}/pm-github-closeout.json" >/dev/null; then
echo "::error::Closeout refused; check token read access to head checks for linked local tracker items. No branch was published."
if jq -e 'any(.plan[]; .action == "skip" and (.code == "head_evidence_unavailable" or .code == "required_checks_unverified"))' "${RUNNER_TEMP}/pm-github-closeout.json" >/dev/null; then
echo "::error::Closeout refused; check token read access to head checks for linked local tracker items, and declare required-checks when protection metadata is unavailable. No branch was published."
exit 1
fi
# Merge facts are checked before head lookup and have a distinct decision.
Expand Down
Loading
Loading