Skip to content

Blind review: R12 trusted authority evolution - #405

Open
thebtf wants to merge 5 commits into
review/release-integration-r1from
work/prc-governance-a17-b17-sol
Open

Blind review: R12 trusted authority evolution#405
thebtf wants to merge 5 commits into
review/release-integration-r1from
work/prc-governance-a17-b17-sol

Conversation

@thebtf

@thebtf thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Review brief

Description: establish the R12 trusted-base ordinary PR guard and owner-only self-reference-free control-plane maintenance path; repair CI database ownership and recurring epoch validation.

Requirements:

  • privileged pull_request_target execution must use only exact trusted-base validator bytes and treat PR-head bytes as data;
  • ordinary PRs must reject protected workflow/gate/governance changes and non-regular or ambiguous Git diffs;
  • maintenance must be same-repository, owner-authored, exact-epoch, exact base/head/tree/path/status/blob bound, replay-safe, and usable for at least two consecutive epochs;
  • candidate workflows must remain read-only/no-secrets and limited to audited immutable action pins;
  • load-bearing JSON types must be strict; no PowerShell scalar coercion;
  • canonical PostgreSQL release gate owns DB completeness, zero unexpected skips, residue, and coverage; the portable OS matrix must not claim those properties without a DB.

Base: 8279d221845ddc0c84007035266e00a79c4994e2
Head: 1dc6b91c
Scope: this PR only (review/release-integration-r1...work/prc-governance-a17-b17-sol).

Risk focus: trusted/untrusted execution boundary, Git object/ref races, stale-label replay, self-reference/fixed-point traps, type confusion, duplicate path/status semantics, workflow permissions/secrets/actions, recurring-epoch liveness, CI false-green/false-red behavior.

Known limits: Tavily research route remained OAuth-blocked; current claims use official sources plus Context7 and Parallel. Application runtime/UI behavior is unchanged. The full project critical suite and exact dev-stand were already green on the base synthesis; this PR adds focused governance evidence and awaits independent PR review/CI.

Expected output: independently derive findings without relying on author conclusions; label severity; cite file and line; distinguish merge blockers from optional notes; explicitly test behavioral edges, not only structure or green tests.

Summary by CodeRabbit

  • Новые возможности

    • Добавлены R12 release-gate проверки для trusted-base authority и безопасных maintenance-переходов с контролем цепочки эпох и статусов.
    • Обновлён CI с усиленной валидацией планов/контрактов, governance и проверками на запрещённые изменения (включая секреты и privileged-поверхности).
    • Запущен/обновлён authority-guard, который формирует подробный итоговый артефакт проверки.
  • Исправления

    • Усилены проверки каноничности SHA/путей и корректности доказательств для переходов, включая replacement.
  • Тестирование

    • R12 Windows/кроссплатформенные прогоны обновлены: критический набор проходит 203/203.
  • Документация

    • Добавлен security-review с описанием security-контуров и критериев валидации.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 69792346-20ba-416f-b247-745d3de1afc6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Добавлены R12 trusted-base валидаторы для обычных PR и maintenance-переходов, сценарный harness, обновления CI-конформности, successor self-test и evidence-отчёты с результатами security-проверок.

Changes

R12 trusted authority maintenance

Layer / File(s) Summary
Проверка PR authority
scripts/production-gates/assert-pr-authority-guard.ps1
Валидатор проверяет trusted Git base, ancestry, merge-tree, diff paths, защищённые области, canonical SHA и authorization envelopes, затем создаёт PASS/FAIL artifact.
Валидация maintenance-перехода
scripts/production-gates/assert-pr-authority-maintenance.ps1
Добавлены проверки maintenance-контрактов, historical anchors, workflow safety, blob inventory, epoch-цепочек и successor transition.
Аудит R12-контрактов и replacement evidence
scripts/production-gates/assert-active-candidate-path-authority.ps1, scripts/production-gates/assert-plan-path-ownership.ps1, .agent/plans/...
Для revision 12 добавлен отдельный аудит candidates и pending contracts; ownership validator поддерживает replacement evidence и self-tests; обновлены pending path-контракты.
Сценарный harness maintenance
.agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1
Harness создаёт synthetic Git-репозиторий, запускает ordinary и maintenance сценарии и формирует итоговый JSON.
Интеграция release-gates в CI
.github/workflows/authority-guard.yml, .github/workflows/test.yml
Workflow переведены на R12, добавлены SHA-проверки, pinned actions, successor self-test и ownership-поля coverage/DB completeness.
Evidence и security review
.agent/specs/release-gates-r12/evidence/*
Добавлены отчёты с verdict PASS, сценариями, security contract, результатами harness и SHA-256 артефактов.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PullRequest
  participant AuthorityGuard
  participant TrustedGit
  participant Validators
  participant Evidence
  PullRequest->>AuthorityGuard: open, synchronize or maintenance label
  AuthorityGuard->>TrustedGit: fetch trusted base and candidate refs
  TrustedGit-->>AuthorityGuard: commits, trees, blobs and diff
  AuthorityGuard->>Validators: run authority and maintenance checks
  Validators-->>AuthorityGuard: PASS/FAIL verdict and details
  AuthorityGuard->>Evidence: write and upload JSON artifact
Loading

Poem

Я, кролик, скачy по веткам в ночи,
Где trusted-хэши светят, как фонари.
Пусть каждый successor путь сохранит,
А каждый gate честно verdict объявит.
Морковка — PASS, и cleanup блестит!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Заголовок кратко и точно отражает основной смысл PR: развитие R12 доверенной authority и maintenance-пути.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch work/prc-governance-a17-b17-sol

Comment @coderabbitai help to get the list of available commands.

@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review\n\nPlease perform an independent adversarial review of this PR. Focus on behavioral edges (wrong JSON types, raw/normalized values, silent acceptance, subset/full truth), privileged workflow execution, Git races, and two-epoch liveness. Do not infer correctness from green tests.

@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

@gemini-code-assist review\n\nPlease act as a blind judge. Independently verify the security and liveness contract, inspect sibling/generic validation paths, and return severity-labeled file:line findings plus an explicit merge verdict.

@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review\n\nBlind focus: derive trust-boundary, recurring-epoch, strict-type, Git-ref/blob, and CI ownership findings independently. Please cite file:line and separate blockers from optional notes.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
cd /tmp
REPO="thebtf/engram"
PR=405

echo "=== PR metadata ==="
gh pr view $PR --repo $REPO --json title,body,baseRefName,headRefName,files,additions,deletions,changedFiles 2>&1 | head -c 3000

echo "=== Files changed ==="
gh pr view $PR --repo $REPO --json files --jq '.files[].path' 2>&1

echo "=== Diff (first 2000 lines) ==="
gh pr diff $PR --repo $REPO 2>&1 | head -c 20000

Length of output: 24505


🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
PR=405

mkdir -p /tmp/pr405
cd /tmp/pr405

for f in ".github/workflows/authority-guard.yml" ".github/workflows/test.yml"; do
  echo "=== $f ==="
  gh api "repos/$REPO/contents/$f?ref=1dc6b91c" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null | cat -n || echo "FAILED to fetch $f"
  echo
done

Length of output: 111647


🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
for f in "scripts/production-gates/assert-pr-authority-guard.ps1" "scripts/production-gates/assert-pr-authority-maintenance.ps1"; do
  echo "=== $f ==="
  gh api "repos/$REPO/contents/$f?ref=1dc6b91c" --jq '.content' 2>/dev/null | base64 -d 2>/dev/null | cat -n
  echo
done

Length of output: 99412


@thebtf Independent review completed by tracing actual code paths rather than trusting the evidence JSON/security-review.md self-reports. Findings below are derived directly from .github/workflows/authority-guard.yml, .github/workflows/test.yml, scripts/production-gates/assert-pr-authority-guard.ps1, and scripts/production-gates/assert-pr-authority-maintenance.ps1.

Trust boundary (verified sound)

  • authority-guard.yml (pull_request_target, Line 4-19) never checks out candidate bytes. It extracts trusted-base script bytes via git cat-file blob $BaseSha:$Path, then double-verifies: trusted blob hash at Line 89 (assert-pr-authority-guard.ps1 L88-90 equivalent) and, critically, both validators re-hash their own running file ($PSCommandPath) against the expected trusted blob before proceeding (assert-pr-authority-guard.ps1 Line 195-196; assert-pr-authority-maintenance.ps1 Line 646-647). This closes the obvious "script got swapped after fetch" gap.
  • Ordinary-PR diff validation (assert-pr-authority-guard.ps1 Lines 80-117) fails closed on renames/copies/deletes/type-changes/symlinks/submodules (mode ∉ {100644,100755} or object type ≠ blob), and on non-canonical paths. This is real enforcement, not just documentation.
  • Self-reference ban for the maintenance manifest is structurally enforced, not just policy text: Assert-ObjectShape at assert-pr-authority-maintenance.ps1 Line 403 and Line 544 defines the exact allowed property set for transition_manifest, which excludes event_head_sha and manifest_container_git_blob — any manifest carrying either field is rejected outright (matches the maintenance-self-reference-rejected fixture).
  • Duplicate-path/blob races are closed via HashSet-based uniqueness checks in Assert-ChangeArray/Assert-ValidatorBlobArray/Assert-ProtectedBlobArray (Lines 203-239).
  • Two-epoch liveness: the successor epoch's rotation-window check at assert-pr-authority-maintenance.ps1 Line 599 requires at least rotate_before_expiry_seconds (7 days) of remaining lifetime after acceptance, so a freshly-approved epoch is always usable for a subsequent transition — this is a real, not merely asserted, guarantee.
  • Strict JSON typing: Assert-JsonInteger/Assert-JsonBoolean/Assert-JsonString/Assert-JsonArray (Lines 95-113) correctly reject PowerShell scalar coercion given how PowerShell 7's ConvertFrom-Json types JSON values (booleans → [bool], integers → [long], strings → [string]); a numeric string like "2" genuinely fails Assert-JsonInteger.

Findings

MEDIUM — Concurrency cancellation can grief an in-flight owner-approved maintenance run (liveness).
.github/workflows/authority-guard.yml Lines 3-19: the workflow triggers on any labeled/unlabeled event, not just authority-maintenance:* labels, and shares one concurrency group per PR number with cancel-in-progress: true. Any collaborator who can add/remove an unrelated label on the PR while the owner's maintenance-approval run is executing will cancel it mid-flight. This doesn't break the security invariant (a canceled run simply produces no PASS status), but it is a real availability/liveness risk directly relevant to the "usable for at least two consecutive epochs" requirement — a busy PR with routine label churn could repeatedly starve the maintenance validator from ever completing.

MEDIUM — The "authority-guard" required-status binding is unverifiable from this diff.
scripts/production-gates/assert-pr-authority-maintenance.ps1 Line 756 checks required_status_context == 'authority-guard', required_status_integration_id == 15368, required_status_app_slug == 'github-actions' — but this is only a self-consistency check against the documented contract, not proof that GitHub branch protection on main actually requires this status/app before merge. If branch protection is missing this required check (or a maintainer merges via admin override), none of the R12 machinery in this PR is load-bearing at all. This is outside code review's visibility — please confirm the live branch-protection rule.

LOW — Protected-path prefix gap for plan-governance evidence files.
Test-ProtectedPath (assert-pr-authority-guard.ps1 Lines 119-125 and assert-pr-authority-maintenance.ps1 Lines 148-151) covers .github/workflows/, scripts/production-gates/, and .agent/plans/, but not .agent/specs/release-gates-r12/evidence/plan-governance/ (which holds test-r12-plan-governance.ps1, path-envelope.json, fixed-point-proof.json, authority-snapshot.json). I found no exploit path — both privileged validators always export and execute these files from the trusted $BaseSha, never from PR head bytes — but an ordinary PR can silently rewrite this governance-evidence directory without tripping the "protected governance change rejected" guard, which is inconsistent with this PR's own stated requirement ("ordinary PRs must reject protected...governance changes"). Recommend adding this prefix to Test-ProtectedPath for defense-in-depth, or explicitly documenting that it's intentionally unprotected bootstrap-only dead weight once consumed_epochs is non-empty.

INFO — Base ref is fetched by branch name, not pinned SHA.
authority-guard.yml Line 69 (+refs/heads/main:refs/authority/bootstrap-base) and both validators fetch refs/heads/main live and require exact equality with EVENT_BASE_SHA. This fails closed correctly (no bypass), but on a repository with concurrent merge activity, any main advance between event delivery and job start will fail the run rather than validate against the (still-valid, still-reachable) event base commit. Worth confirming this doesn't degrade the "usable for at least two consecutive epochs" guarantee under realistic merge cadence, since the simulation evidence only exercises a single-actor local-Git harness, not concurrent-push races.

INFO — git merge-tree --write-tree runner-Git-version dependency not independently verified.
Both validators rely on the merge-ort-based git merge-tree --write-tree <base> <head> syntax. This needs a sufficiently recent Git on ubuntu-latest; I did not independently confirm the current runner image's Git version supports this exact invocation.

Verified structural claims (not just asserted)

  • Ordinary/DB CI ownership repair: test.yml explicitly tags db_completeness_owner/coverage_enforcement_owner as 'release-gates-foundation' in the cross-platform matrix job (Lines 1021), and the workflow-conformance self-test explicitly rejects any mutation that reassigns these to 'matrix' (Lines 805-806) — this genuinely prevents the portable OS matrix from silently reclaiming DB-completeness/coverage authority.
  • Candidate-workflow read-only/no-secrets/action-pin constraints (Assert-HeadWorkflowSafety, Assert-ImmutableWorkflowActions, Lines 317-373) are real regex/text checks against the head bytes-as-data, not against executed code, and correctly reject unpinned or unapproved-but-pinned actions, secret references, and pull_request_target leaking into the test workflow.

Merge verdict

No exploitable privilege-escalation or trust-boundary bypass found in this pass — the design is fail-closed almost everywhere traced. The two MEDIUM items (label-driven cancellation griefing, and the branch-protection required-status dependency being unverifiable from code) should be explicitly acknowledged or ruled out before treating this as a fully closed security review; neither is a hard blocker to merging this PR itself, but the second one determines whether any of this machinery is actually load-bearing in production.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dc6b91c8c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/production-gates/assert-pr-authority-guard.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the R12 authority maintenance and PR authority guard scripts, tests, and evidence files, along with support for 'replacement' transition kinds in plan path ownership. The review feedback focuses on improving the robustness of the PowerShell scripts, specifically by ensuring case-insensitive Git SHA comparisons, making YAML parsing and permissions checks resilient to comments and trailing whitespace, and maintaining consistent property access using helper functions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/production-gates/assert-pr-authority-guard.ps1
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
.agent/specs/release-gates-r12/evidence/release-gates/security-review.md (1)

62-64: 🔒 Security & Privacy | 🔵 Trivial

Зафиксируйте зависимость от live branch protection.

Привязка имени required status внутри контракта не доказывает, что main действительно требует authority-guard и запрещает административный bypass. Добавьте live API evidence или явно укажите это как residual operational risk.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.agent/specs/release-gates-r12/evidence/release-gates/security-review.md
around lines 62 - 64, Update the maintenance transition evidence to verify via
live branch-protection API data that main requires the authority-guard status
and disallows administrative bypass; if this evidence cannot be provided,
explicitly record the dependency as a residual operational risk alongside the
bound required-status identity.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
@.agent/specs/release-gates-r12/evidence/release-gates/R12-AUTHORITY-MAINTENANCE.tdd.json:
- Around line 30-32: Update the workflow_conformance evidence in
R12-AUTHORITY-MAINTENANCE.tdd.json so hostile_mutations_rejected matches the
current .github/workflows/test.yml value of 71. Regenerate or refresh the
artifact from the final conformance test rather than changing unrelated verdict
data.

In
@.agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1:
- Around line 372-375: Добавьте в test-r12-authority-maintenance.ps1 (372-375)
ordinary-сценарий, который через Reset-Fixture/Push-Head изменяет файл в
.agent/specs/release-gates-r12/evidence/plan-governance/ и проверяет отказ через
Invoke-Scenario с ожидаемой ошибкой authority. В security-review.md (58-61)
уберите абсолютное утверждение о защите plan-governance до исправления guard и
регенерации evidence.

In @.github/workflows/authority-guard.yml:
- Around line 17-19: Separate the maintenance-stage concurrency from the general
authority-guard group: update the workflow’s concurrency configuration so
maintenance-label runs use a distinct group key, while preserving cancellation
behavior within that maintenance group and preventing
labeled/unlabeled/synchronize runs from canceling an owner-approved maintenance
check.

In `@scripts/production-gates/assert-plan-path-ownership.ps1`:
- Around line 842-880: Привяжите replacement evidence к $requiredBase, а не
только к формату SHA: в ветке проверки replacement для REVISE_HOLD требуйте
точное равенство rejected_head_sha и requiredBase, а для
ROOT_SELECTED_EXACT_BASE — выбранной immutable identity (integration_sha или
predecessor_head_sha) и requiredBase. Обновите Invoke-DiffEpochAuthority, чтобы
replacement проходил те же строгие проверки базовой ревизии, что и rework.
Добавьте negative mismatch self-test, подтверждающий отклонение evidence с
несовпадающим base.

In `@scripts/production-gates/assert-pr-authority-guard.ps1`:
- Around line 119-124: Update Test-ProtectedPath in
scripts/production-gates/assert-pr-authority-guard.ps1 (lines 119-124) to treat
.agent/specs/release-gates-r12/evidence/plan-governance/ as protected from
ordinary PR changes. Update the corresponding namespace allowlist in
scripts/production-gates/assert-pr-authority-maintenance.ps1 (lines 148-151) to
permit it only as a bounded owner-approved maintenance change.
- Around line 151-167: Update the pending-envelope checks so
forbidden_final_paths are enforced for prefix matches as well as exact matches.
In scripts/production-gates/assert-pr-authority-guard.ps1:151-167, validate each
prefix-covered path against the pending contract’s forbidden_final_paths before
returning pending-prefix-envelope. In
scripts/production-gates/assert-active-candidate-path-authority.ps1:364-382,
apply the same forbidden-path intersection check to exact_prefixes, preserving
authorization only when no forbidden path is matched.

---

Nitpick comments:
In @.agent/specs/release-gates-r12/evidence/release-gates/security-review.md:
- Around line 62-64: Update the maintenance transition evidence to verify via
live branch-protection API data that main requires the authority-guard status
and disallows administrative bypass; if this evidence cannot be provided,
explicitly record the dependency as a residual operational risk alongside the
bound required-status identity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a793f3a-7c13-468e-bf39-c66ef5c29786

📥 Commits

Reviewing files that changed from the base of the PR and between 8279d22 and 1dc6b91.

📒 Files selected for processing (11)
  • .agent/specs/release-gates-r12/evidence/release-gates/R12-AUTHORITY-MAINTENANCE.tdd.json
  • .agent/specs/release-gates-r12/evidence/release-gates/maintenance-simulation.json
  • .agent/specs/release-gates-r12/evidence/release-gates/security-review.md
  • .agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1
  • .agent/specs/release-gates-r12/evidence/release-gates/windows-harness.json
  • .github/workflows/authority-guard.yml
  • .github/workflows/test.yml
  • scripts/production-gates/assert-active-candidate-path-authority.ps1
  • scripts/production-gates/assert-plan-path-ownership.ps1
  • scripts/production-gates/assert-pr-authority-guard.ps1
  • scripts/production-gates/assert-pr-authority-maintenance.ps1

Comment thread .github/workflows/authority-guard.yml
Comment thread scripts/production-gates/assert-plan-path-ownership.ps1
Comment thread scripts/production-gates/assert-pr-authority-guard.ps1
Comment thread scripts/production-gates/assert-pr-authority-guard.ps1

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the R12 trusted authority maintenance and PR authority guard framework, including new PowerShell validation scripts, simulation tests, and security reviews. Feedback on the changes highlights potential runtime errors in assert-active-candidate-path-authority.ps1 where direct property access on deserialized objects under strict mode can trigger PropertyNotFoundExceptions; using the Get-PropertyValue helper is recommended. Additionally, the YAML block parser in assert-pr-authority-maintenance.ps1 should be made more robust by replacing fragile exact string matching with regular expressions to handle trailing whitespace and comments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

External-review repair is ready at exact head 22ec847. Please review the new delta and the full resulting security contract. Local evidence: AST/actionlint PASS; ledger 60 slices / 396 declarations / 0 errors; active authority PASS; plan governance PASS; workflow conformance 71 hostile mutations rejected; two consecutive isolated authority simulations PASS 22/22 each (4 accepts, 18 rejects, cleanup verified); staged gitleaks PASS. @coderabbitai review @codex review @gemini-code-assist review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
PR=405
NEW_HEAD="22ec8476f65050919820f6bdff6cf8d3573ecf8e"

echo "=== PR current head ==="
gh pr view $PR --repo $REPO --json headRefOid,commits --jq '.headRefOid'

echo "=== Compare diff between previously reviewed commit and new head ==="
gh api "repos/$REPO/compare/1dc6b91c...$NEW_HEAD" --jq '.files[].filename' 2>&1 || echo "compare failed"

echo "=== Full diff for changed files (workflows + scripts) ==="
for f in ".github/workflows/authority-guard.yml" "scripts/production-gates/assert-pr-authority-guard.ps1" "scripts/production-gates/assert-pr-authority-maintenance.ps1"; do
  echo "--- diff for $f ---"
  gh api "repos/$REPO/compare/1dc6b91c...$NEW_HEAD" --jq ".files[] | select(.filename==\"$f\") | .patch" 2>&1 | head -c 20000
  echo
done

Length of output: 31988


🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
NEW_HEAD="22ec8476f65050919820f6bdff6cf8d3573ecf8e"

for f in "scripts/production-gates/assert-active-candidate-path-authority.ps1" "scripts/production-gates/assert-plan-path-ownership.ps1"; do
  echo "--- diff for $f ---"
  gh api "repos/$REPO/compare/1dc6b91c...$NEW_HEAD" --jq ".files[] | select(.filename==\"$f\") | .patch" 2>&1 | head -c 12000
  echo
done

echo "=== security-review.md diff (check acknowledgment of prior findings) ==="
gh api "repos/$REPO/compare/1dc6b91c...$NEW_HEAD" --jq '.files[] | select(.filename=="'".agent/specs/release-gates-r12/evidence/release-gates/security-review.md"'") | .patch' 2>&1 | head -c 6000

Length of output: 21515


@thebtf Reviewed the delta at 22ec8476f65050919820f6bdff6cf8d3573ecf8e against the previously reviewed commit. Both prior findings are addressed, plus additional hardening was added beyond what was requested.

Fixes verified

MEDIUM — concurrency griefing (resolved). .github/workflows/authority-guard.yml Line 18 now keys the concurrency group on ${{ pull_request.number }}-${{ pull_request.head.sha }}-${{ event.label.name || 'no-label' }}. Unrelated label add/remove on a different head SHA or label name no longer shares a group with an in-flight owner-approved run, so it can no longer cancel it. Re-triggering with the same authority label still cancels/replaces the prior run — correctly preserved as the intended revocation path.

MEDIUM — required-status/branch-protection binding (acknowledged, not a code defect). security-review.md now explicitly discloses that live branch protection does not yet require the authority-guard check (classic protection returns 404, ruleset 13610955 has no required status checks) and states activation is "intentionally still BLOCKED" pending a main ruleset update. This confirms the concern was valid; it's correctly framed as an explicit operational release gate rather than resolved-by-code, which is the right way to handle something code review can't verify.

LOW — protected-path prefix gap (resolved). Test-ProtectedPath in both assert-pr-authority-guard.ps1 (Line 125) and assert-pr-authority-maintenance.ps1 (Line 151) now includes .agent/specs/release-gates-r12/evidence/plan-governance/, so ordinary PRs touching governance-evidence files now trip the protected-change guard.

Additional hardening noted (beyond the prior review's asks)

  • Inductive self-check on ordinary PRs: assert-pr-authority-guard.ps1 now runs assert-pr-authority-maintenance.ps1 -ValidateBaseOnly against the trusted base before authorizing an ordinary diff, re-verifying the maintenance chain/historical anchor rather than trusting it implicitly.
  • Deadlock/overlap fix: forbidden_final_paths is now checked against prefix-covered paths too (not just exact matches) in Find-Authorization and Invoke-R12ContractAudit, with regression self-tests for the prefix case.
  • Workflow skeleton pinning: Assert-HeadWorkflowSafety now diffs the entire non-comment privileged-workflow skeleton (base vs. head, masking only uses: lines) — a candidate PR can now only rotate pre-authorized action pins, never alter run logic, even cosmetically.
  • Strict JSON typing tightened further: Invoke-R12ContractAudit now uses -isnot [long]/[string] checks instead of blind [int]/[string] casts for schema_version/kind/revision/path_count, closing a residual PowerShell numeric-string coercion gap (e.g., "1" would previously have silently cast-succeeded).

Merge verdict

No new trust-boundary or privilege-escalation issue found in this delta. Both MEDIUM items and the LOW item from the previous pass are correctly resolved or explicitly and honestly flagged as a pending non-code activation step. The additional strict-typing and skeleton-diff hardening are net-positive and don't introduce new gaps I could find. From a code-review standpoint this is clear to merge; the one remaining item — actually enabling the authority-guard required status check on the live main ruleset — is an infrastructure/configuration step outside this diff's control and should happen before treating the R12 machinery as load-bearing in production.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements the R12 trusted authority maintenance security specifications, including simulation tests, verification scripts, and updated contract auditing logic. The review feedback highlights several critical improvements for the PowerShell scripts: enforcing case-sensitive SHA and blob validation using -cnotmatch instead of -notmatch, allowing both [int] and [long] types to prevent failures on PowerShell Core 7.3+, checking for consecutive slashes in canonical path validation, and making YAML block parsing and workflow validation less fragile to minor formatting variations or comments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22ec8476f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/production-gates/assert-pr-authority-guard.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-guard.ps1 Outdated
@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

R5 external-review repair is ready at exact head cc24740. Please review the new delta and the full resulting security/liveness contract independently. Evidence on the unchanged final tree: AST/actionlint PASS; ownership ledger 60 slices / 396 declarations / 0 errors; active authority PASS; R12 plan governance PASS; workflow conformance rejected all 71 hostile mutations; two consecutive isolated authority simulations PASS 24/24 each (4 accepts, 20 expected rejects, cleanup verified); evidence SHA map 14/14; staged gitleaks PASS. This revision explicitly reverses the earlier uppercase-SHA response after proving PowerShell matching is case-insensitive by default and now enforces canonical lowercase identities at runtime with -cnotmatch. Please do not infer correctness from the tests: re-check null/missing types, closed-world statuses, root-comment parsing, path aliases, privileged execution, recurring epochs, and exact workflow language. @coderabbitai review @codex review @gemini-code-assist review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
PR=405
PREV_HEAD="22ec8476f65050919820f6bdff6cf8d3573ecf8e"
NEW_HEAD="cc247402f2309b53285c88367d9ca33696ff278f"

echo "=== confirm current PR head ==="
gh pr view $PR --repo $REPO --json headRefOid --jq '.headRefOid'

echo "=== files changed in delta ==="
gh api "repos/$REPO/compare/$PREV_HEAD...$NEW_HEAD" --jq '.files[].filename'

echo "=== full patches ==="
gh api "repos/$REPO/compare/$PREV_HEAD...$NEW_HEAD" --jq '.files[] | "--- " + .filename + " ---\n" + .patch' 2>&1 | head -c 60000

Length of output: 55629


🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
NEW_HEAD="cc247402f2309b53285c88367d9ca33696ff278f"

echo "=== search for any remaining case-insensitive hex/sha matches in the 4 script files ==="
for f in "scripts/production-gates/assert-pr-authority-guard.ps1" "scripts/production-gates/assert-pr-authority-maintenance.ps1" "scripts/production-gates/assert-active-candidate-path-authority.ps1" "scripts/production-gates/assert-plan-path-ownership.ps1"; do
  echo "--- $f ---"
  gh api "repos/$REPO/contents/$f?ref=$NEW_HEAD" --jq '.content' | base64 -d | grep -nP '(?<!c)notmatch.*\[0-9a-f\]' || echo "none"
  echo
done

echo "=== check full Get-OptionalArrayProperty usage sites in guard + maintenance scripts ==="
for f in "scripts/production-gates/assert-pr-authority-guard.ps1" "scripts/production-gates/assert-pr-authority-maintenance.ps1"; do
  echo "--- $f ---"
  gh api "repos/$REPO/contents/$f?ref=$NEW_HEAD" --jq '.content' | base64 -d | grep -n "Get-OptionalArrayProperty\|Get-OptionalStringArray"
  echo
done

Length of output: 2762


@thebtf Reviewed the delta at cc247402f2309b53285c88367d9ca33696ff278f against the previous head 22ec8476f65050919820f6bdff6cf8d3573ecf8e, tracing the actual regex/comparison operators changed rather than trusting the evidence JSON.

Case-sensitivity reversal (verified correct and complete)

PowerShell's -match/-notmatch and [ValidatePattern(...)] are case-insensitive by default — your prior framing of ^[0-9a-f]{40}$ as a canonical-lowercase guarantee was indeed incomplete, since an uppercase-hex SHA (e.g. AAAA...) would previously pass every one of these checks while representing a Git identity distinct in string-equality space from its lowercase form used elsewhere for exact matching (-ceq/-cne). I traced every hex-identity comparison site across the four changed scripts and confirmed:

  • All genuine SHA/blob (^[0-9a-f]{40}$, ^[0-9a-f]{64}$) comparisons now use -cnotmatch/case-sensitive matching, in assert-pr-authority-guard.ps1, assert-pr-authority-maintenance.ps1, assert-active-candidate-path-authority.ps1, and assert-plan-path-ownership.ps1.
  • The two remaining -notmatch hits against [0-9]-only patterns I found (assert-pr-authority-maintenance.ps1 Line 506 ^r12-[0-9]{4}$, assert-active-candidate-path-authority.ps1 Line 381 ^work/[A-Za-z0-9._/-]+$) are not hex-identity patterns — they're epoch labels and branch names where the character class already spans both cases by design, so case-sensitivity is a non-issue there.
  • New runtime guards were added at the top of both assert-pr-authority-guard.ps1 and assert-pr-authority-maintenance.ps1 (-cnotmatch on BaseSha/HeadSha/ExpectedValidatorGitBlob) as defense-in-depth ahead of [ValidatePattern], so an uppercase-hex identity now fails closed before any Git operation runs.
  • A hostile self-test (('A' * 40) -cnotmatch '^[0-9a-f]{40}$') proves the regression can't silently return.

This is a legitimate, evidence-led reversal, not just a written retraction — good catch on your end.

Other findings verified as correctly closed

  • Root-comment trigger hiding: Get-RootYamlBlock now continues past bare top-level comment lines (-notmatch '^\s*#' added to the break condition) instead of terminating the on:/job block scan at the first unindented #... line. The new maintenance-test-comment-separated-target-trigger-rejected fixture (inserting a root comment then pull_request_target: right after pull_request:) correctly still trips may not use pull_request_target. I confirmed the break condition still correctly stops at real unindented keys, so this only widens tolerance for comments, not for actual content.
  • Path aliases: Assert-CanonicalPath now also rejects // (double-slash), with a matching hostile fixture (.agent//plans//...) correctly rejected as non-canonical.
  • Null/missing types: Get-OptionalArrayProperty now filters $null/whitespace entries — closes a real latent bug where @($null) on an explicit exact_prefixes: null property previously produced a one-element array containing $null, which would have been silently cast to "" downstream. The added NULLPREFIX self-test entry exercises this path.
  • Closed-world pending statuses: Invoke-R12ContractAudit now validates pending_namespaces[].status_class against the manifest's own status_classes.pending array rather than only checking for non-blank, with a hostile self-test (arbitrary-pending-status) confirming rejection. assert-pr-authority-guard.ps1's Find-Authorization also dropped its revision -ne 12 carve-out, so this closed-world check is now unconditionally enforced rather than only for other revisions.
  • JSON integer typing: Assert-JsonInteger/Invoke-R12ContractAudit now accept [int] in addition to [long]. This is a broadening, but a safe one — value equality is still enforced via cast to [long], and the explicit exclusion of [string]/[bool] is untouched, so a numeric-string type-confusion bypass is still correctly rejected (unchanged maintenance-json-numeric-string-rejected scenario still passes).
  • Successor job header parsing: Assert-HeadWorkflowSafety's job-boundary regex now tolerates a trailing comment on the authority-successor-selftest: key line and on the following job's key line, with a matching fixture mutation in test-r12-authority-maintenance.ps1 proving the safety checks still fire correctly when a comment is appended to the job header.
  • Exact workflow language: confirmed unchanged — security-review.md explicitly re-affirms rejection of loosening exact-match workflow-string checks to substring-tolerant alternatives, consistent with the fail-closed design already reviewed.

Merge verdict

No new trust-boundary, privilege-escalation, or type-confusion issue found in this delta. The case-sensitivity fix is real and closes a genuine (if narrow) identity-comparison gap; the other four additions (root-comment parsing, double-slash paths, null-prefix filtering, closed-world pending status) are each backed by a corresponding hostile fixture that fails without the fix and passes with it. From a code-review standpoint this delta is clear. The two previously-flagged non-code items remain outstanding and unaffected by this delta: (1) confirming the authority-guard required-status check is actually enabled on the live main branch-protection ruleset, and (2) the git merge-tree --write-tree runner Git-version dependency.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements the R12/B17 trusted authority maintenance system, adding new validation scripts, test suites, and simulation logs, while updating existing path authority and plan ownership checks to support case-sensitive SHA validation and replacement transitions. The review feedback highlights several critical issues: an unsafe substring operation in the prefix matching logic of assert-pr-authority-guard.ps1 that could crash the script, missing System. prefixes for CultureInfo and DateTimeStyles types in multiple files causing runtime TypeNotFound exceptions, and unhandled Remove-Item failures in finally blocks that could mask primary exceptions during cleanup.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/production-gates/assert-pr-authority-guard.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-guard.ps1 Outdated
Comment thread scripts/production-gates/assert-pr-authority-maintenance.ps1 Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc247402f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1 Outdated
Comment thread scripts/production-gates/assert-active-candidate-path-authority.ps1

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/production-gates/assert-active-candidate-path-authority.ps1 (1)

385-385: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Баг: $macroBound ложно истинен при отсутствующих/null member_slices/exact_r12_overrides.

@((Get-PropertyValue $pending 'member_slices')).Count — если свойство отсутствует или явно null, Get-PropertyValue возвращает скалярный $null, а @($null) в PowerShell создаёт массив из ОДНОГО элемента (Count=1), а не пустой массив (Count=0). Таким образом, pending-namespace с authority_mode равным macro-константе, но без реальных member_slices/exact_r12_overrides, ложно проходит -gt 0 проверку и обходит ветку "declares no bounded path" (строка 386).

Прямой эксплойт через assert-pr-authority-guard.ps1 не подтверждён (там Find-Authorization не читает member_slices/macroBound), но это брешь в полноте структурной проверки самого R12-аудита — контракт с фиктивным macro-bound namespace без реальных полномочий проходит как валидный.

Тот же паттерн уже правильно обёрнут через null-safe хелперы (Get-OptionalStringArray) в остальных местах этой же функции — здесь стоит использовать тот же подход.

🐛 Предлагаемое исправление
-        $macroBound = [string](Get-PropertyValue $pending 'authority_mode') -ceq 'bound-plan-member-union-with-exact-r12-overrides' -and @((Get-PropertyValue $pending 'member_slices')).Count -gt 0 -and @((Get-PropertyValue $pending 'exact_r12_overrides')).Count -gt 0
+        $macroBound = [string](Get-PropertyValue $pending 'authority_mode') -ceq 'bound-plan-member-union-with-exact-r12-overrides' -and @(Get-OptionalStringArray $pending 'member_slices').Count -gt 0 -and @(Get-OptionalStringArray $pending 'exact_r12_overrides').Count -gt 0
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/production-gates/assert-active-candidate-path-authority.ps1` at line
385, Исправьте вычисление $macroBound в проверке authority_mode, заменив прямые
вызовы Get-PropertyValue для member_slices и exact_r12_overrides на существующий
null-safe helper Get-OptionalStringArray. Сохраните проверку непустых массивов
через Count -gt 0, чтобы отсутствующие или null-свойства давали Count=0 и не
считались bounded path.
🧹 Nitpick comments (2)
scripts/production-gates/assert-active-candidate-path-authority.ps1 (1)

407-431: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Переиспользование автоматической переменной $matches.

$matches — зарезервированное имя (заполняется оператором -match/-cmatch). Использование его как обычной переменной для результата Where-Object (как в этом же файле для R9-ветки, где для аналогичного кода используется $matchingPending, строка 565) создаёт риск скрытой порчи данных при будущих правках, если в этой же области видимости появится вызов -match. Статический анализ (PSScriptAnalyzer, PSAvoidAssignmentToAutomaticVariable) также это отмечает.

♻️ Предлагаемое исправление
-        $matches = @($pendingContracts | Where-Object { [string](Get-PropertyValue $_ 'slice') -ceq $probeSlice })
-        if ($matches.Count -ne 1) { $errors.Add("pending probe slice '$probeSlice' has $($matches.Count) contracts, expected 1") }
-        elseif ($probeBase -cne [string](Get-PropertyValue $matches[0] 'base_anchor')) { $errors.Add("pending probe base '$probeBase' must equal frozen base anchor '$([string](Get-PropertyValue $matches[0] 'base_anchor'))'") }
+        $matchingPending = @($pendingContracts | Where-Object { [string](Get-PropertyValue $_ 'slice') -ceq $probeSlice })
+        if ($matchingPending.Count -ne 1) { $errors.Add("pending probe slice '$probeSlice' has $($matchingPending.Count) contracts, expected 1") }
+        elseif ($probeBase -cne [string](Get-PropertyValue $matchingPending[0] 'base_anchor')) { $errors.Add("pending probe base '$probeBase' must equal frozen base anchor '$([string](Get-PropertyValue $matchingPending[0] 'base_anchor'))'") }

(и аналогично заменить оставшиеся обращения к $matches[0] на $matchingPending[0] внутри этого блока, строки 419-426).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/production-gates/assert-active-candidate-path-authority.ps1` around
lines 407 - 431, Replace the local `$matches` variable in the pending-probe
block with a non-reserved name such as `$matchingPending`, and update all
references to it, including the count check and `$matchingPending[0]` accesses.
Preserve the existing contract validation and audit behavior.

Source: Linters/SAST tools

.agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1 (1)

197-311: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

New-MaintenanceHead: корректно, но обратите внимание на алиасинг exact_changes.

$manifest.exact_changes = $changes (строка 284) не создаёт копию — это та же ссылка, что и $maintenance.active_epoch.exact_changes. Любая ManifestMutation, изменяющая элементы exact_changes (например, сценарий maintenance-double-slash-path, строки 507-511), попадёт и в $successor.exact_changes при JSON round-trip на строке 290, поскольку копирование происходит уже после мутации. Сейчас это не искажает итог теста (голова с испорченным путём отбраковывается и не мержится в main), но при добавлении новых сценариев, где манифест должен отличаться от фактического состояния эпохи, это может незаметно "протечь" в состояние следующей эпохи.

♻️ Возможное исправление (глубокое копирование перед мутацией)
-        exact_changes = $changes
+        exact_changes = ($changes | ConvertTo-Json -Depth 100 | ConvertFrom-Json -Depth 100)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
@.agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1
around lines 197 - 311, В функции New-MaintenanceHead устраните aliasing между
manifest.exact_changes и maintenance.active_epoch.exact_changes: создайте
независимую глубокую копию exact_changes до вызова ManifestMutation, а манифест
собирайте из этой копии. Сохраните исходные изменения эпохи неизменными, чтобы
последующее формирование successor через JSON round-trip не перенимало мутации
манифеста.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/production-gates/assert-active-candidate-path-authority.ps1`:
- Line 385: Исправьте вычисление $macroBound в проверке authority_mode, заменив
прямые вызовы Get-PropertyValue для member_slices и exact_r12_overrides на
существующий null-safe helper Get-OptionalStringArray. Сохраните проверку
непустых массивов через Count -gt 0, чтобы отсутствующие или null-свойства
давали Count=0 и не считались bounded path.

---

Nitpick comments:
In
@.agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1:
- Around line 197-311: В функции New-MaintenanceHead устраните aliasing между
manifest.exact_changes и maintenance.active_epoch.exact_changes: создайте
независимую глубокую копию exact_changes до вызова ManifestMutation, а манифест
собирайте из этой копии. Сохраните исходные изменения эпохи неизменными, чтобы
последующее формирование successor через JSON round-trip не перенимало мутации
манифеста.

In `@scripts/production-gates/assert-active-candidate-path-authority.ps1`:
- Around line 407-431: Replace the local `$matches` variable in the
pending-probe block with a non-reserved name such as `$matchingPending`, and
update all references to it, including the count check and `$matchingPending[0]`
accesses. Preserve the existing contract validation and audit behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c85bdd96-ce9d-4e29-b13b-546b845ebca2

📥 Commits

Reviewing files that changed from the base of the PR and between 1dc6b91 and cc24740.

📒 Files selected for processing (14)
  • .agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json
  • .agent/specs/release-gates-r12/evidence/plan-governance/gates-summary.json
  • .agent/specs/release-gates-r12/evidence/plan-governance/test-r12-plan-governance.ps1
  • .agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json
  • .agent/specs/release-gates-r12/evidence/release-gates/R12-AUTHORITY-MAINTENANCE.tdd.json
  • .agent/specs/release-gates-r12/evidence/release-gates/maintenance-simulation.json
  • .agent/specs/release-gates-r12/evidence/release-gates/security-review.md
  • .agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1
  • .agent/specs/release-gates-r12/evidence/release-gates/windows-harness.json
  • .github/workflows/authority-guard.yml
  • scripts/production-gates/assert-active-candidate-path-authority.ps1
  • scripts/production-gates/assert-plan-path-ownership.ps1
  • scripts/production-gates/assert-pr-authority-guard.ps1
  • scripts/production-gates/assert-pr-authority-maintenance.ps1
🚧 Files skipped from review as they are similar to previous changes (2)
  • .agent/specs/release-gates-r12/evidence/release-gates/security-review.md
  • .agent/specs/release-gates-r12/evidence/release-gates/R12-AUTHORITY-MAINTENANCE.tdd.json

@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

Final R6 repair is ready at exact head 6a942f8. Please perform one final independent full-delta review. R6 closes field-kind confusion (and moves the live IMAGE directory to exact_prefixes), anchors all R12 status classes to literal trusted-validator sets, rejects malformed prefixes before substring logic, and preserves primary errors across cleanup failures. Final byte-exact evidence on separate GUID fixture histories: two parallel isolated simulations PASS 24/24 each (4 accepts, 20 expected rejects; durations 401.433s and 401.417s), plan governance/active authority/ledger PASS (60 slices, 396 declarations, 0 errors), 71 workflow mutations rejected, AST/actionlint PASS, SHA map 14/14, gitleaks 0. Please inspect behavior rather than trusting those results. @coderabbitai review @codex review @gemini-code-assist review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
PR=405
PREV_HEAD="cc247402f2309b53285c88367d9ca33696ff278f"
NEW_HEAD="6a942f80e8a9fba499af9e6d52898a3fa633c477"

echo "=== confirm current PR head ==="
gh pr view $PR --repo $REPO --json headRefOid --jq '.headRefOid'

echo "=== files changed in delta ==="
gh api "repos/$REPO/compare/$PREV_HEAD...$NEW_HEAD" --jq '.files[].filename'

echo "=== full patches ==="
gh api "repos/$REPO/compare/$PREV_HEAD...$NEW_HEAD" --jq '.files[] | "--- " + .filename + " ---\n" + .patch' 2>&1 | head -c 70000

Length of output: 34287


🏁 Script executed:

#!/bin/bash
set -euo pipefail
REPO="thebtf/engram"
SHA="6a942f80e8a9fba499af9e6d52898a3fa633c477"

echo "=== Normalize-AuthorityPath definition ==="
gh api "repos/$REPO/contents/scripts/production-gates/assert-active-candidate-path-authority.ps1?ref=$SHA" --jq '.content' | base64 -d | grep -n "function Normalize-AuthorityPath" -A 30

echo "=== other Substring usages on prefixes in same file ==="
gh api "repos/$REPO/contents/scripts/production-gates/assert-active-candidate-path-authority.ps1?ref=$SHA" --jq '.content' | base64 -d | grep -n "Substring\|forbidden\|exact_prefixes" 

echo "=== test-r12-authority-maintenance.ps1 surrounding errorText/exit logic ==="
gh api "repos/$REPO/contents/.agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1?ref=$SHA" --jq '.content' | base64 -d | sed -n '480,600p'

Length of output: 15555


@thebtf Reviewed the R6 delta at 6a942f80e8a9fba499af9e6d52898a3fa633c477 against the previous head cc247402f2309b53285c88367d9ca33696ff278f, tracing the actual comparison/substring logic rather than the evidence artifacts.

Claims verified against code

Field-kind confusion (resolved). In scripts/production-gates/assert-active-candidate-path-authority.ps1, Invoke-R12ContractAudit's pending-namespace loop previously iterated @($exactPaths) + @($exactPrefixes) together with only canonical/duplicate checks. It now validates each array separately (Lines 397-406) and asserts $normalized.kind -cne 'exact'/'prefix' against the corresponding declared field — a prefix token placed in exact_paths (or vice versa) is now rejected. The IMAGE evidence directory (.agent/reports/evidence/production-ready/image-remediation-r2/**) was moved from exact_paths to exact_prefixes in .agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json, consistent with it actually being a glob-style prefix. New self-test r12PrefixInExactPathsResult (Line ~725) exercises the rejection path directly.

R12 status classes anchored to literal audited sets (resolved). Lines 315-320 of the same file now hard-code the expected current/rejected/pending arrays and compare with -cne against the ordered, joined actual arrays — this is stricter than set-membership; it requires exact sequence match, closing Codex's "manifest validates itself" gap. New self-test r12SelfDeclaredStatusResult proves a self-declared/arbitrary status set is now rejected with "audited closed-world set" rather than silently accepted.

Malformed prefixes rejected before substring logic (resolved, correctly scoped). assert-pr-authority-guard.ps1's Find-Authorization previously ran ([string]$_).Substring(0, ([string]$_).Length - 2) directly on unvalidated exact_prefixes entries — a prefix without a trailing /** (e.g., a 1-character string) could throw an unhandled ArgumentOutOfRangeException mid-authorization. The new Get-CanonicalPrefixBase helper (Line 143) validates a non-empty terminal /** and canonical base before any entry is used, and is invoked to build $prefixBases up front (Line 175) — a malformed prefix now fails closed with a clear error rather than crashing. New self-test ($invalidPrefixRejected, Line ~205) confirms this. I also confirmed the base-stripping bug is fixed as a side effect: the old code stripped only 2 characters (**), leaving a trailing / inconsistency; the new helper correctly strips all 3 (/**). Note assert-active-candidate-path-authority.ps1 didn't need an equivalent fix — its Normalize-AuthorityPath (Line 125-138) already guards against empty/glob-containing prefix bases before any substring use, so the vulnerable pattern was specific to the guard script's Find-Authorization.

Cleanup failures preserve primary errors and force FAIL (resolved). Both assert-pr-authority-guard.ps1 and assert-pr-authority-maintenance.ps1 now wrap their finally-block Remove-Item in try/catch; on failure they append a cleanup error to $artifactObject.errors (creating a minimal FAIL artifact if none exists yet) and explicitly set $exitCode = 1 — the primary validation result, if any, is preserved rather than being overwritten by an unhandled cleanup exception. I traced the harness's own verdict computation too (test-r12-authority-maintenance.ps1, tail of file): $verdict requires $errorText to be null and $cleanupVerified true, so a cleanup failure there correctly flips the overall simulation to FAIL rather than being silently swallowed.

Other notes

  • The [Globalization.CultureInfo][System.Globalization.CultureInfo] change in ConvertTo-Rfc3339 is cosmetic (fully-qualified type name), matching the security-review.md's framing that Gemini's namespace-resolution concern was disproved but the qualification was kept for clarity — no behavioral change.
  • security-review.md's updated known_integration_blocker (macOS /var vs /private/var, .NET Directory.SetUnixFileMode, pre-v5 tag/image prerequisites) is explicitly scoped to PR #406 and out of this diff's control — consistent with prior framing, not a new claim needing code verification here.

Merge verdict

All four R6 claims are backed by real code changes with corresponding hostile self-tests, not just narrative in the evidence JSON. No new trust-boundary, privilege-escalation, or type-confusion defect found in this delta. The two previously-flagged non-code items remain outstanding and unaffected: (1) enabling the authority-guard required status check on the live main branch-protection ruleset, and (2) the git merge-tree --write-tree runner-Git-version dependency. From a code-review standpoint, this delta is clear to merge.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements the R12/B17 release-governance bootstrap and CI truth repair, introducing new PowerShell guard scripts, authority maintenance tests, and security reviews, while updating existing path authority and ownership scripts to enforce case-sensitive lowercase SHA checks. The review feedback highlights several critical PowerShell-specific issues where using the array subexpression operator @(...) on null or missing properties wraps $null in a single-element array. This behavior can bypass safety checks or cause fatal runtime crashes under strict mode when iterating and accessing properties on a null loop variable. It is recommended to use [array] casting or direct iteration to prevent these crashes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

if ((Get-PropertyValue $pending 'release_accepted') -isnot [bool] -or [bool](Get-PropertyValue $pending 'release_accepted')) { $errors.Add("pending '$slice' must not claim release acceptance") }
[string[]]$exactPaths = @(Get-OptionalStringArray $pending 'exact_paths')
[string[]]$exactPrefixes = @(Get-OptionalStringArray $pending 'exact_prefixes')
$macroBound = [string](Get-PropertyValue $pending 'authority_mode') -ceq 'bound-plan-member-union-with-exact-r12-overrides' -and @((Get-PropertyValue $pending 'member_slices')).Count -gt 0 -and @((Get-PropertyValue $pending 'exact_r12_overrides')).Count -gt 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

In PowerShell, the array subexpression operator @(...) wraps $null in an array of size 1 containing $null (i.e., @($null).Count is 1). If member_slices or exact_r12_overrides is null or missing, Get-PropertyValue returns $null, and @((Get-PropertyValue ...)).Count -gt 0 will incorrectly evaluate to True. This causes $macroBound to be True even when both properties are missing, bypassing the safety check on line 392.

Using [array] casting instead of @(...) safely returns a count of 0 for null values.

        $macroBound = [string](Get-PropertyValue $pending 'authority_mode') -ceq 'bound-plan-member-union-with-exact-r12-overrides' -and ([array](Get-PropertyValue $pending 'member_slices')).Count -gt 0 -and ([array](Get-PropertyValue $pending 'exact_r12_overrides')).Count -gt 0

$actualStatus = Get-OrdinalSignature $DiffEntries
$actualPaths = Get-OrdinalSignature $DiffEntries -PathsOnly
[string[]]$current = @($Contract.status_classes.current)
foreach ($candidate in @($Contract.candidates)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using @($Contract.candidates) wraps a null value in an array of size 1 containing $null if candidates is missing or null. This causes the foreach loop to execute once with a null loop variable. Under Set-StrictMode -Version Latest (active on line 17), accessing properties on $null (e.g., $candidate.status_class) will throw a fatal runtime error and crash the script.

In PowerShell, foreach loops automatically handle null values safely (by skipping execution) and also handle single objects or arrays correctly without needing the @(...) wrapper. Removing @(...) prevents potential strict mode crashes.

    foreach ($candidate in $Contract.candidates) {

if ($candidateStatus -ceq $actualStatus) { return [pscustomobject][ordered]@{ kind='current-candidate'; slice=[string]$candidate.slice; status_class=[string]$candidate.status_class } }
}
[string[]]$pendingStatuses = @($Contract.status_classes.pending)
foreach ($pending in @($Contract.pending_namespaces)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Using @($Contract.pending_namespaces) wraps a null value in an array of size 1 containing $null if pending_namespaces is missing or null. This causes the foreach loop to execute once with a null loop variable. Under Set-StrictMode -Version Latest (active on line 17), accessing properties on $null (e.g., $pending.status_class) will throw a fatal runtime error and crash the script.

In PowerShell, foreach loops automatically handle null values safely (by skipping execution) and also handle single objects or arrays correctly without needing the @(...) wrapper. Removing @(...) prevents potential strict mode crashes.

    foreach ($pending in $Contract.pending_namespaces) {

if (($currentStatuses -join "`n") -cne ($expectedCurrentStatuses -join "`n")) { $errors.Add('R12 current status classes drifted from the audited closed-world set') }
if (($rejectedStatuses -join "`n") -cne ($expectedRejectedStatuses -join "`n")) { $errors.Add('R12 rejected status classes drifted from the audited closed-world set') }
if (($pendingStatuses -join "`n") -cne ($expectedPendingStatuses -join "`n")) { $errors.Add('R12 pending status classes drifted from the audited closed-world set') }
[object[]]$candidates = @((Get-PropertyValue $ContractObject 'candidates'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If candidates is null, @((Get-PropertyValue ...)) wraps $null in an array of size 1, causing the subsequent foreach loop to execute once with a null candidate, which can lead to errors. Using [array] casting safely initializes an empty array when the property is null.

    [object[]]$candidates = [array](Get-PropertyValue $ContractObject 'candidates')

if ([string]::IsNullOrWhiteSpace([string](Get-PropertyValue $candidate 'plan_owner'))) { $errors.Add("candidate '$slice' has no plan owner") }
if ((Get-PropertyValue $candidate 'path_authority_eligible') -isnot [bool] -or -not [bool](Get-PropertyValue $candidate 'path_authority_eligible')) { $errors.Add("candidate '$slice' is not path-authority eligible") }
if ((Get-PropertyValue $candidate 'release_accepted') -isnot [bool] -or [bool](Get-PropertyValue $candidate 'release_accepted')) { $errors.Add("candidate '$slice' must not claim release acceptance") }
[object[]]$pathObjects = @((Get-PropertyValue $candidate 'paths'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If paths is null, @((Get-PropertyValue ...)) wraps $null in an array of size 1, causing the subsequent foreach loop to execute once with a null path object. Using [array] casting safely initializes an empty array when the property is null.

        [object[]]$pathObjects = [array](Get-PropertyValue $candidate 'paths')

}
}
}
[object[]]$pendingContracts = @((Get-PropertyValue $ContractObject 'pending_namespaces'))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

If pending_namespaces is null, @((Get-PropertyValue ...)) wraps $null in an array of size 1, causing the subsequent foreach loop to execute once with a null pending contract. Using [array] casting safely initializes an empty array when the property is null.

    [object[]]$pendingContracts = [array](Get-PropertyValue $ContractObject 'pending_namespaces')

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a942f80e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

$root = [System.IO.Path]::GetFullPath($Repository)
$artifactPath = [System.IO.Path]::GetFullPath((Join-Path $root $Artifact))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve absolute artifact paths

When the workflow invokes this script with -Artifact $env:RUNNER_TEMP/r12-authority-maintenance.json, this Join-Path $root $Artifact rewrites that absolute runner-temp path under the checkout instead of leaving it in ${{ runner.temp }}; the PowerShell Join-Path docs show a child beginning with a separator is still appended to the parent (path\ + \childpath -> path\childpath). The simulation can therefore pass while writing the JSON to <repo>/<runner-temp>/..., and the following upload-artifact step that looks in ${{ runner.temp }} fails with if-no-files-found: error on pull_request runs.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
scripts/production-gates/assert-active-candidate-path-authority.ps1 (3)

692-692: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Позиционные параметры при вызове Invoke-R12ContractAudit в self-test.

Static analysis отмечает использование позиционных параметров вместо именованных при нескольких вызовах Invoke-R12ContractAudit в self-test-коде.

Also applies to: 706-706, 712-712, 716-716, 721-721, 726-726

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/production-gates/assert-active-candidate-path-authority.ps1` at line
692, Update the self-test calls to Invoke-R12ContractAudit, including the
assignments to r12WrongIdentityResult and the corresponding calls at the other
referenced locations, to pass arguments using the function’s named parameter
syntax instead of positional arguments. Preserve the existing argument values
and test scenarios.

Source: Linters/SAST tools


434-435: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Смешение "not an ancestor" и настоящих git-ошибок в Probe.

git merge-base --is-ancestor возвращает статус 1, если коммит не предок, и любой другой ненулевой статус сигнализирует об ошибке (например, невалидный SHA). Здесь любой ненулевой $LASTEXITCODE трактуется одинаково как "pending probe base is not an ancestor of head", что маскирует настоящие git-ошибки неверным диагностическим сообщением.

Чуть выше в этом же файле (строки 594-598, R9-ветка) это уже сделано правильно: $ancestorExit -eq 1 обрабатывается отдельно от прочих ненулевых кодов.

♻️ Предлагаемое исправление по аналогии с R9-веткой
             try {
-                & git -C $Repository merge-base --is-ancestor $probeBase $probeHead 2>$null
-                if ($LASTEXITCODE -ne 0) { throw 'pending probe base is not an ancestor of head' }
+                & git -C $Repository merge-base --is-ancestor $probeBase $probeHead 2>$null
+                $ancestorExit = $LASTEXITCODE
+                if ($ancestorExit -eq 1) { throw "pending probe base '$probeBase' is not an ancestor of head '$probeHead'" }
+                if ($ancestorExit -ne 0) { throw "git merge-base --is-ancestor failed with exit $ancestorExit" }
                 [object[]]$entries = @(Get-GitDiffEntries $Repository $probeBase $probeHead)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/production-gates/assert-active-candidate-path-authority.ps1` around
lines 434 - 435, Update the merge-base status handling near the pending probe
validation so exit code 1 raises the existing “not an ancestor” diagnostic,
while any other nonzero $LASTEXITCODE is propagated or reported as a genuine git
error. Follow the established handling in the R9 branch around $ancestorExit,
preserving success behavior for exit code 0.

688-728: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Self-test не покрывает git-верификацию и Probe-путь R12.

Добавленные R12 self-test сценарии (строки 688-728) проверяют только identity/status/forbidden-path логику через прямые вызовы Invoke-R12ContractAudit без -VerifyGit/-RequireObjects/-Probe. Ветки, сверяющие живой git diff с замороженным контрактом (строки 354-377), и Probe-логика с merge-base --is-ancestor (строки 424-448), остаются непокрытыми тестами для revision 12 — в отличие от R9-контракта, для которого есть хотя бы $wrongBaseProbe (строка 750).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/production-gates/assert-active-candidate-path-authority.ps1` around
lines 688 - 728, Расширьте R12 self-test вокруг Invoke-R12ContractAudit, добавив
сценарии с -VerifyGit и -RequireObjects для проверки сверки живого git diff с
замороженным контрактом, а также сценарии с -Probe для проверки merge-base
--is-ancestor. Используйте валидный R12 контракт и намеренно изменённые
base/объекты или probe-данные, проверяя ожидаемые FAIL-вердикты и
соответствующие ошибки; добавьте аналог проверки успешного пути, если он
предусмотрен существующим R9-паттерном вроде $wrongBaseProbe.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
@.agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json:
- Line 19: Update the strict_authority_schema claim in verification-summary.json
so it does not present the active_contracts digest as a trusted-validator
SHA-256. Bind it to the validator artifact’s actual bytes and corresponding
digest, or rename the field to explicitly identify active_contracts if that is
the intended source; preserve the remaining schema-validation claims.

---

Nitpick comments:
In `@scripts/production-gates/assert-active-candidate-path-authority.ps1`:
- Line 692: Update the self-test calls to Invoke-R12ContractAudit, including the
assignments to r12WrongIdentityResult and the corresponding calls at the other
referenced locations, to pass arguments using the function’s named parameter
syntax instead of positional arguments. Preserve the existing argument values
and test scenarios.
- Around line 434-435: Update the merge-base status handling near the pending
probe validation so exit code 1 raises the existing “not an ancestor”
diagnostic, while any other nonzero $LASTEXITCODE is propagated or reported as a
genuine git error. Follow the established handling in the R9 branch around
$ancestorExit, preserving success behavior for exit code 0.
- Around line 688-728: Расширьте R12 self-test вокруг Invoke-R12ContractAudit,
добавив сценарии с -VerifyGit и -RequireObjects для проверки сверки живого git
diff с замороженным контрактом, а также сценарии с -Probe для проверки
merge-base --is-ancestor. Используйте валидный R12 контракт и намеренно
изменённые base/объекты или probe-данные, проверяя ожидаемые FAIL-вердикты и
соответствующие ошибки; добавьте аналог проверки успешного пути, если он
предусмотрен существующим R9-паттерном вроде $wrongBaseProbe.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c1927b45-d595-4751-a005-332a699e41cb

📥 Commits

Reviewing files that changed from the base of the PR and between cc24740 and 6a942f8.

📒 Files selected for processing (12)
  • .agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json
  • .agent/specs/release-gates-r12/evidence/plan-governance/gates-summary.json
  • .agent/specs/release-gates-r12/evidence/plan-governance/test-r12-plan-governance.ps1
  • .agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json
  • .agent/specs/release-gates-r12/evidence/release-gates/R12-AUTHORITY-MAINTENANCE.tdd.json
  • .agent/specs/release-gates-r12/evidence/release-gates/maintenance-simulation.json
  • .agent/specs/release-gates-r12/evidence/release-gates/security-review.md
  • .agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1
  • .agent/specs/release-gates-r12/evidence/release-gates/windows-harness.json
  • scripts/production-gates/assert-active-candidate-path-authority.ps1
  • scripts/production-gates/assert-pr-authority-guard.ps1
  • scripts/production-gates/assert-pr-authority-maintenance.ps1
🚧 Files skipped from review as they are similar to previous changes (7)
  • .agent/specs/release-gates-r12/evidence/plan-governance/test-r12-plan-governance.ps1
  • .agent/specs/release-gates-r12/evidence/release-gates/R12-AUTHORITY-MAINTENANCE.tdd.json
  • .agent/specs/release-gates-r12/evidence/release-gates/maintenance-simulation.json
  • .agent/specs/release-gates-r12/evidence/release-gates/windows-harness.json
  • scripts/production-gates/assert-pr-authority-guard.ps1
  • .agent/specs/release-gates-r12/evidence/release-gates/test-r12-authority-maintenance.ps1
  • scripts/production-gates/assert-pr-authority-maintenance.ps1

"two_pr_stale_loser": true,
"required_status_identity": "authority-guard plus strict JSON integer GitHub Actions integration_id 15368",
"strict_authority_schema": "the complete canonical authority manifest is bound to trusted-validator SHA-256 6665a80d30c2b45319b8c8adce05430c6f6e3913ded92313c4ebbb381f11c9f6; recursive hostile tests prove exact object keys, scalar types/values, array cardinality/order, and duplicate/case-alias rejection without requiring an unreachable predecessor Git object",
"strict_authority_schema": "the complete canonical authority manifest is bound to trusted-validator SHA-256 9776e67bb8b2bc93de8fca2ec9296f765e64ef3d2380f40b306ca2d6b193a67a; recursive hostile tests prove exact object keys, scalar types/values, array cardinality/order, and duplicate/case-alias rejection without requiring an unreachable predecessor Git object",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

for path in \
  scripts/production-gates/assert-pr-authority-guard.ps1 \
  scripts/production-gates/assert-pr-authority-maintenance.ps1 \
  .agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json
do
  printf '%s: ' "$path"
  git show "HEAD:$path" | tr -d '\r' | sha256sum
done

Repository: thebtf/engram

Length of output: 478


🏁 Script executed:

set -euo pipefail

printf '\n[files]\n'
git ls-files \
  .agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json \
  .agent/specs/release-gates-r12/evidence/plan-governance/gates-summary.json \
  .github/workflows/test.yml \
  .github/workflows/authority-guard.yml \
  scripts/production-gates/assert-pr-authority-guard.ps1 \
  scripts/production-gates/assert-pr-authority-maintenance.ps1 \
  .agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json

printf '\n[relevant excerpts]\n'
for f in \
  .agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json \
  .agent/specs/release-gates-r12/evidence/plan-governance/gates-summary.json \
  .github/workflows/test.yml \
  .github/workflows/authority-guard.yml
do
  echo "--- $f"
  nl -ba "$f" | sed -n '1,220p'
done

printf '\n[sha256 via python]\n'
python3 - <<'PY'
from pathlib import Path
import hashlib

paths = [
    Path('scripts/production-gates/assert-pr-authority-guard.ps1'),
    Path('scripts/production-gates/assert-pr-authority-maintenance.ps1'),
    Path('.agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json'),
    Path('.agent/specs/release-gates-r12/evidence/plan-governance/gates-summary.json'),
]
for p in paths:
    data = p.read_bytes().replace(b'\r\n', b'\n')
    print(f"{p}: {hashlib.sha256(data).hexdigest()}")
PY

Repository: thebtf/engram

Length of output: 721


🏁 Script executed:

set -euo pipefail

printf '\n[verification-summary]\n'
sed -n '1,120p' .agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json | cat -n

printf '\n[gates-summary]\n'
sed -n '1,140p' .agent/specs/release-gates-r12/evidence/plan-governance/gates-summary.json | cat -n

printf '\n[test.yml]\n'
sed -n '70,190p' .github/workflows/test.yml | cat -n

printf '\n[authority-guard.yml]\n'
sed -n '1,170p' .github/workflows/authority-guard.yml | cat -n

printf '\n[sha256]\n'
python3 - <<'PY'
from pathlib import Path
import hashlib

for p in [
    Path('scripts/production-gates/assert-pr-authority-guard.ps1'),
    Path('scripts/production-gates/assert-pr-authority-maintenance.ps1'),
    Path('.agent/plans/2026-07-10-engram-production-ready-active-diff-contracts.json'),
]:
    data = p.read_bytes().replace(b'\r\n', b'\n')
    print(p)
    print(hashlib.sha256(data).hexdigest())
PY

Repository: thebtf/engram

Length of output: 25331


Не смешивайте digest active_contracts с digest доверенного валидатора.
9776e67bb8b2bc93de8fca2ec9296f765e64ef3d2380f40b306ca2d6b193a67a совпадает с хэшем active-contracts JSON, а не с отдельным байтовым артефактом валидатора. Перепривяжите strict_authority_schema к правильным байтам или переименуйте поле, чтобы оно явно указывало на active_contracts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
@.agent/specs/release-gates-r12/evidence/plan-governance/verification-summary.json
at line 19, Update the strict_authority_schema claim in
verification-summary.json so it does not present the active_contracts digest as
a trusted-validator SHA-256. Bind it to the validator artifact’s actual bytes
and corresponding digest, or rename the field to explicitly identify
active_contracts if that is the intended source; preserve the remaining
schema-validation claims.

@thebtf

thebtf commented Jul 13, 2026

Copy link
Copy Markdown
Owner Author

R7 checker repair is ready at exact head f50d86d. The delta closes the PowerShell @($null) false-green in macro authority, validates JSON-origin arrays and canonical members/paths, distinguishes merge-base exit 1 from Git errors, and corrects the mislabeled evidence digest. Root replay on the exact tree: selftest PASS; R12 plan governance PASS; Git-backed active audit PASS (9 candidates, 118 paths, 0 errors); isolated authority simulation PASS 24/24 (4 allows, 20 expected rejects, cleanup verified). Please independently inspect behavior, not the reported tests, with focus on wrong JSON types, missing/duplicate macro members, schema aliases, canonical paths, and ancestry error handling. @coderabbitai review @codex review @gemini-code-assist review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request updates the release-governance and authority-maintenance scripts by introducing a new 'replacement' transition kind, adding helper functions for JSON property validation, and implementing strict case-sensitive SHA checks. It also adds new scripts and test harnesses for R12 authority maintenance and PR authority guarding. The code review feedback identifies a potential bug where an undefined variable $predecessorCount is referenced, suggests using case-sensitive -cnotmatch operators for Git/SHA validation in the new replacement transition block for consistency, and recommends validating the $Remote parameter in both the PR authority guard and maintenance scripts to prevent potential Git option injection attacks.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

elseif ($transitionKind -eq 'replacement' -and $currentIndex -ge 0) {
if ($currentIndex -eq 0) { $errors.Add("state epoch '$path' replacement transition has no predecessor") }
if ($requiredBase -notmatch '^[0-9a-fA-F]{40}$') { $errors.Add("state epoch '$path' replacement base must be a full SHA") }
if ($predecessorCount -ne $currentIndex) { $errors.Add("state epoch '$path' replacement predecessor evidence count is $predecessorCount, expected $currentIndex") }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Please verify if $predecessorCount is defined in the scope of the Get-EpochEvidenceErrors function. If it is not defined, accessing it here will return $null (or throw a runtime exception if Set-StrictMode is active), which would cause the validation to incorrectly fail or crash.\n\nIf it is not defined, you should use $predecessors.Count instead.

        if ($predecessors.Count -ne $currentIndex) { $errors.Add("state epoch '$path' replacement predecessor evidence count is $($predecessors.Count), expected $currentIndex") }

Comment on lines +844 to +874
if ($requiredBase -notmatch '^[0-9a-fA-F]{40}$') { $errors.Add("state epoch '$path' replacement base must be a full SHA") }
if ($predecessorCount -ne $currentIndex) { $errors.Add("state epoch '$path' replacement predecessor evidence count is $predecessorCount, expected $currentIndex") }
$currentStatus = [string](Get-PropertyValue $Epoch 'current_owner_status')
$currentHead = [string](Get-PropertyValue $Epoch 'current_owner_head_sha')
if ([string]::IsNullOrWhiteSpace($currentStatus) -and $currentHead -notmatch '^[0-9a-fA-F]{40}$') {
$errors.Add("state epoch '$path' replacement lacks current-owner status or immutable head identity")
}
for ($ownerIndex = 0; $ownerIndex -lt [math]::Max(0, $currentIndex); $ownerIndex++) {
$expectedOwner = $owners[$ownerIndex]
$matches = @($predecessors | Where-Object { [string](Get-PropertyValue $_ 'owner') -ceq $expectedOwner })
if ($matches.Count -ne 1) { $errors.Add("state epoch '$path' replacement predecessor '$expectedOwner' evidence count is $($matches.Count), expected 1"); continue }
$entry = $matches[0]
$checkerVerdict = [string](Get-PropertyValue $entry 'checker_verdict')
if ($checkerVerdict -ceq 'REVISE_HOLD') {
$checkerArtifact = [string](Get-PropertyValue $entry 'checker_artifact')
$checkerSha = [string](Get-PropertyValue $entry 'checker_sha256')
$rejectedHead = [string](Get-PropertyValue $entry 'rejected_head_sha')
$postReviewVerdict = [string](Get-PropertyValue $entry 'post_review_verdict')
$postReviewArtifact = [string](Get-PropertyValue $entry 'post_review_artifact')
$postReviewSha = [string](Get-PropertyValue $entry 'post_review_sha256')
$integrationSha = [string](Get-PropertyValue $entry 'integration_sha')
if ($checkerArtifact -notmatch '^\.agent/' -or $checkerSha -notmatch '^[0-9a-fA-F]{64}$') { $errors.Add("state epoch '$path' replacement predecessor '$expectedOwner' lacks exact rejecting-checker evidence") }
if ($postReviewVerdict -cne 'REVISE_HOLD' -or $postReviewArtifact -notmatch '^\.agent/' -or (-not [string]::IsNullOrWhiteSpace($postReviewSha) -and $postReviewSha -notmatch '^[0-9a-fA-F]{64}$')) { $errors.Add("state epoch '$path' replacement predecessor '$expectedOwner' lacks root post-review evidence") }
if ($rejectedHead -notmatch '^[0-9a-fA-F]{40}$') { $errors.Add("state epoch '$path' replacement predecessor '$expectedOwner' lacks rejected-head identity") }
if (-not [string]::IsNullOrWhiteSpace($integrationSha)) { $errors.Add("state epoch '$path' rejected replacement predecessor '$expectedOwner' must not claim integration") }
}
elseif ($checkerVerdict -ceq 'ROOT_SELECTED_EXACT_BASE') {
$integrationSha = [string](Get-PropertyValue $entry 'integration_sha')
$selectedHead = [string](Get-PropertyValue $entry 'predecessor_head_sha')
if ($integrationSha -notmatch '^[0-9a-fA-F]{40}$' -and $selectedHead -notmatch '^[0-9a-fA-F]{40}$') { $errors.Add("state epoch '$path' root-selected replacement predecessor '$expectedOwner' lacks an immutable integration/head identity") }
if ($integrationSha -notmatch '^[0-9a-fA-F]{40}$' -and [string](Get-PropertyValue $entry 'checker_artifact') -notmatch '^\.agent/') { $errors.Add("state epoch '$path' root-selected replacement predecessor '$expectedOwner' lacks the root selection artifact") }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In the new replacement transition validation block, several Git/SHA identity fields (such as $requiredBase, $currentHead, $checkerSha, $rejectedHead, $postReviewSha, $integrationSha, and $selectedHead) are validated using case-insensitive -notmatch with the pattern ^[0-9a-fA-F]{40}$ (or 64).\n\nTo maintain consistency with the rest of the codebase (which enforces a strict canonical lowercase contract for Git/SHA identities, as seen in the recent migration of Resolve-ExactCommit to -cnotmatch '^[0-9a-f]{40}$'), these checks should be updated to use case-sensitive -cnotmatch with lowercase [0-9a-f] patterns.

$exitCode = 1
$trustedRoot = $null
try {
if ($BaseSha -cnotmatch '^[0-9a-f]{40}$' -or $HeadSha -cnotmatch '^[0-9a-f]{40}$' -or $ExpectedValidatorGitBlob -cnotmatch '^[0-9a-f]{40}$') { throw 'base, head, and validator Git identities must be canonical lowercase full SHAs' }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-medium medium

The $Remote parameter is passed directly to git fetch without validation. If an attacker can control or manipulate the remote URL/name passed to this script, they could potentially perform a Git option injection attack by passing a value starting with a dash (e.g., --upload-pack=...).\n\nTo prevent this, consider validating that $Remote does not start with a dash.

    if ($BaseSha -cnotmatch '^[0-9a-f]{40}$' -or $HeadSha -cnotmatch '^[0-9a-f]{40}$' -or $ExpectedValidatorGitBlob -cnotmatch '^[0-9a-f]{40}$') { throw 'base, head, and validator Git identities must be canonical lowercase full SHAs' }\n    if ($Remote -like '-*') { throw 'remote must not start with a dash to prevent option injection' }

$exitCode = 1
$trustedRoot = $null
try {
if ($BaseSha -cnotmatch '^[0-9a-f]{40}$' -or $ExpectedValidatorGitBlob -cnotmatch '^[0-9a-f]{40}$' -or ($PSCmdlet.ParameterSetName -eq 'Transition' -and $HeadSha -cnotmatch '^[0-9a-f]{40}$')) { throw 'base, head, and validator Git identities must be canonical lowercase full SHAs' }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

security-medium medium

The $Remote parameter is passed directly to git fetch without validation. If an attacker can control or manipulate the remote URL/name passed to this script, they could potentially perform a Git option injection attack by passing a value starting with a dash (e.g., --upload-pack=...).\n\nTo prevent this, consider validating that $Remote does not start with a dash.

    if ($BaseSha -cnotmatch '^[0-9a-f]{40}$' -or $ExpectedValidatorGitBlob -cnotmatch '^[0-9a-f]{40}$' -or ($PSCmdlet.ParameterSetName -eq 'Transition' -and $HeadSha -cnotmatch '^[0-9a-f]{40}$')) { throw 'base, head, and validator Git identities must be canonical lowercase full SHAs' }\n    if ($Remote -like '-*') { throw 'remote must not start with a dash to prevent option injection' }

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f50d86de6a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +495 to +497
[string[]]$exactPaths = @(Get-OptionalStringArray $pending 'exact_paths')
[string[]]$exactPrefixes = @(Get-OptionalStringArray $pending 'exact_prefixes')
$macroBound = Test-R12MacroAuthority $pending $errors

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require JSON arrays for R12 pending path lists

When an R12 pending namespace uses the ordinary exact_paths/exact_prefixes fields, these lines still call Get-OptionalStringArray, which wraps any scalar property into a one-element list. A malformed contract such as "exact_paths": "internal/proxy/identity_test.go" is therefore treated as a valid bounded path and can PASS, so the checker only enforces JSON-origin arrays for the macro helper while leaving the other R12 pending authorities type-confusable.

Useful? React with 👍 / 👎.

Comment on lines +125 to +127
$memberSlicesValue = Get-JsonPropertyValue $Pending 'member_slices'
$valid = Test-RequiredCanonicalStringArray -Value $memberSlicesValue -Name 'member_slices' -Errors $Errors -MemberPattern '^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)*$'
$memberSlices = if ($valid) { @($memberSlicesValue) } else { @() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind macro members to the audited batch membership

This validates member_slices as a non-empty unique string array, but never checks that it equals the audited macro batch/scope-map membership. A contract can drop any MB1 member that has no exact override, or replace the list with just the override slices, and Test-R12MacroAuthority still returns true because the list is only used to vet override slice names; that makes macro_bound_plan_union a false positive for an incomplete macro authority set.

Useful? React with 👍 / 👎.

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.

1 participant