Skip to content

WS-ART-001-03B3B1: approve guide parser dependencies - #230

Merged
abiorh-claw merged 4 commits into
mainfrom
codex/ws-art-001-03b3b1-parser-dependency-approval
Jul 31, 2026
Merged

WS-ART-001-03B3B1: approve guide parser dependencies#230
abiorh-claw merged 4 commits into
mainfrom
codex/ws-art-001-03b3b1-parser-dependency-approval

Conversation

@Abiorh001

@Abiorh001 Abiorh001 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

WS-ART-001-03B3B1 PR Trust Bundle

Chunk

WS-ART-001-03B3B1 — Parser Dependency Approval.

Goal

Approve and enforce the smallest exact PDF, OOXML-safety, and image-metadata
dependency set without installing packages or changing runtime behavior.

Human-approved intent

The merged 03B3B split contract requires dependency approval before any PDF,
OOXML, or image parser implementation. The human owner explicitly started this
chunk after PR #228 merged.

What changed

  • Added a canonical allowlist for pypdf==6.14.2, defusedxml==0.7.1, and
    Pillow==12.3.0, including exact approved wheel URLs and SHA-256 hashes.
  • Added a deterministic checker for manifest shape, wheel identity/platform,
    hash-bound future declarations, prohibited packages, format-scoped imports,
    and independent exact-head GitHub approval.
  • Added focused failure tests and wired the gate before backend installation.
  • Updated the ART specification, chunk command, status, and review evidence.

Why it changed

Untrusted document parsers are a supply-chain boundary. A package name or
version alone cannot prove which bytes will later be installed, and a
repository-authored approval file cannot independently authorize itself.

Design chosen

  • PDF: pure-Python pypdf.
  • OOXML safety: pure-Python defusedxml plus later ART-owned bounded container
    and format adapters.
  • Image metadata: native Pillow, restricted to two named Python 3.11/3.12
    manylinux x86_64 wheels.
  • Future runtime declarations must use the exact approved wheel URL with its
    SHA-256 fragment. Optional/dependency-group parser declarations are denied.
  • Allowlist changes require a current approving GitHub review from an
    independent human owner/member/collaborator on the exact PR head.

Alternatives rejected

  • python-docx, python-pptx, openpyxl, lxml, and XlsxWriter: larger,
    unnecessary graphs for the bounded v0.1 OOXML extraction design.
  • Version-only pins: do not bind installed artifact bytes.
  • Repository-local approval as authority: forgeable by the proposing PR.
  • pull_request_target: an unnecessary privileged workflow boundary.

Scope control

No pyproject.toml, lockfile, dependency install, application import, parser
adapter, AUTH, Celery, submission, or product lifecycle change is included.

Product behavior

None. Project Manager guide-source handling remains distinct from contributor
one-ZIP submission handling. All parser behavior remains unimplemented.

Acceptance criteria proof

  • Canonical schema covers version, license, maintenance, advisories,
    transitive graph, native-code, malformed-input, network, cancellation,
    import, format, source, wheel URL, and hash facts.
  • Three closed scopes are present exactly once.
  • Plain pins, wrong hashes/URLs/wheels/tags/scopes, prohibited packages,
    optional-group bypasses, cross-format imports, self/bot/stale/dismissed
    approvals, and GitHub API failure all reject in focused tests.

Tests/checks run

  • Manifest checker: pass.
  • Focused pytest: 34 pass; checker coverage 92.94 percent.
  • Ruff lint and format: pass.
  • Compile, markdown links, stale artifact/wording, lightweight agent gates,
    and git diff --check: pass.

Test delta

One new focused test module; no tests removed, skipped, or weakened.

CI integrity

The gate runs before package installation. Existing backend tests, semantic
lanes, provider proof, and 78/90 percent coverage floors are unchanged. Token
permissions remain read-only: contents: read and pull-requests: read.

Reviewer results

Architecture, security, QA, product/ops, senior engineering, CI integrity,
reuse/dedup, and test delta pass after valid findings were repaired. Docs
review is rerun on the staged evidence.

External review

CodeRabbit and hosted GitHub checks have not run yet. Their exact PR-head
results remain required external evidence.

Remaining risks

  • Live GitHub review-event/check semantics require hosted proof.
  • Review submitted/dismissed events rerun the full Backend job; this is an
    accepted low operational cost for the v0.1 fail-closed required check.
  • defusedxml is a stable, slow-release security utility; its isolation and
    bounded OOXML use remain mandatory in later chunks.

Follow-up work

After this chunk merges, WS-ART-001-03B3B2 may install only the approved PDF
wheel and implement bounded PDF extraction. Later OOXML and image chunks remain
separate and require explicit starts.

Human review focus

Confirm the three-package minimum, wheel URL/hash selection, native Pillow
platform bounds, prohibited package set, and independent exact-head approval
semantics.

Human merge ownership

Only the human owner may approve and merge this PR. The PR must receive an
independent qualifying GitHub approval on its exact final head; this agent will
not merge it.

Summary by CodeRabbit

  • Security

    • Added strict validation for approved document and image-processing dependencies, including exact versions, package hashes, supported platforms, and prohibited packages.
    • Dependency policy changes now require independent approval on the final pull-request revision.
  • Reliability

    • Added fail-closed checks for unapproved dependencies, unsafe imports, invalid package metadata, and stale or invalid approvals.
    • CI now enforces dependency-policy validation for relevant changes.
  • Testing

    • Expanded automated coverage for dependency validation, approval workflows, artifact integrity, and failure scenarios.
  • Documentation

    • Documented supported formats, runtime requirements, security constraints, and approved package artifacts.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e761406-2c50-4159-bedc-5068e6a7769f

📥 Commits

Reviewing files that changed from the base of the PR and between 92cceee and 6e5e697.

📒 Files selected for processing (7)
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/REVIEW_LOG.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/STATUS.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-external-review-response.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-pr-trust-bundle.md
  • .github/workflows/backend.yml
  • backend/scripts/check_guide_extractor_dependencies.py
  • backend/tests/test_guide_extractor_dependencies.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/STATUS.md
  • .github/workflows/backend.yml
  • backend/tests/test_guide_extractor_dependencies.py
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-external-review-response.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-pr-trust-bundle.md
  • backend/scripts/check_guide_extractor_dependencies.py

📝 Walkthrough

Walkthrough

The change adds a hashed parser dependency manifest, validates dependency and import boundaries, enforces exact-head pull-request approval, wires the checks into CI, and adds focused tests, documentation, and review records.

Changes

Parser dependency governance

Layer / File(s) Summary
Allowlist and parser validation
backend/config/guide_extractor_dependencies.json, backend/scripts/check_guide_extractor_dependencies.py
Defines approved pypdf, defusedxml, and Pillow artifacts. Validates hashes, platforms, scopes, imports, dependency declarations, and prohibited packages.
Approval and CI enforcement
backend/scripts/check_guide_extractor_dependencies.py, .github/workflows/backend.yml
Detects allowlist changes, checks exact-head independent approval, retrieves GitHub reviews, and runs the gate in backend CI.
Test coverage and lane wiring
backend/tests/test_guide_extractor_dependencies.py, backend/scripts/run_test_lanes.py, .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/chunks/WS-ART-001-03B3B1-parser-dependency-approval.md
Adds validation tests, assigns them to shared_foundations, and updates verification commands.
Specification and review records
docs/spec_artifact_storage_service.md, .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/...
Documents the dependency policy, approval requirements, test evidence, review outcomes, and implementation scope.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant DependencyChecker
  participant Allowlist
  participant GitHubReviews
  GitHubActions->>DependencyChecker: Run dependency validation
  DependencyChecker->>Allowlist: Load and hash manifest
  DependencyChecker->>DependencyChecker: Compare base and head allowlist
  DependencyChecker->>GitHubReviews: Fetch pull-request reviews
  GitHubReviews-->>DependencyChecker: Return review payloads
  DependencyChecker-->>GitHubActions: Return gate status
Loading

Possibly related PRs

Suggested reviewers: abiorh-claw

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the dependency approval change and matches the main purpose of the pull request.
Description check ✅ Passed The description covers the goal, design, scope, evidence, tests, risks, reviewer status, and merge requirements; minor template differences do not block review.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/ws-art-001-03b3b1-parser-dependency-approval

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@Abiorh001
Abiorh001 requested a review from abiorh-claw July 30, 2026 20:09
@Abiorh001

Copy link
Copy Markdown
Collaborator Author

@abiorh-claw The WS-ART-001-03B3B1 dependency allowlist is ready for independent review at exact head 66ac70e6. Please approve only if the three-package set, wheel URLs/SHA-256 hashes, prohibited package set, and fail-closed CI gate are acceptable. After exact-head approval, the Backend review-event run will validate the approval and execute the hosted suite.

abiorh-claw
abiorh-claw previously approved these changes Jul 31, 2026
@Abiorh001

Copy link
Copy Markdown
Collaborator Author

@abiorh-claw CI repair is pushed at exact head 92cceee1: the new dependency-gate test is now registered in the existing shared_foundations semantic lane. The focused dependency and exact inventory checks pass, and CI/test-delta re-reviews pass. Please re-review and approve this new exact head so the fail-closed Backend gate can run.

@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: 4

🧹 Nitpick comments (7)
backend/tests/test_guide_extractor_dependencies.py (2)

306-321: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

test_github_review_fetch_returns_valid_payload does not verify the request sent to GitHub.

This test calls the real gate.fetch_reviews, but the urlopen stub accepts and ignores *_args, **_kwargs. The test confirms that fetch_reviews parses a response correctly, but it does not confirm that fetch_reviews builds the correct URL, HTTP method, or Authorization header for the GitHub reviews endpoint. A regression in request construction (wrong path, missing token header) would not be caught here.

Capture the Request object passed to urlopen and assert on its full_url and headers.

🤖 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 `@backend/tests/test_guide_extractor_dependencies.py` around lines 306 - 321,
Update test_github_review_fetch_returns_valid_payload to capture the Request
argument received by the urlopen stub instead of ignoring it, then assert that
the request full_url targets the expected repository, pull request, and reviews
endpoint and that its headers contain the correct Authorization token and HTTP
method. Keep the existing response parsing assertion.

62-119: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Positional indexing into data["dependencies"] couples tests to manifest ordering.

The mutation table uses data["dependencies"][0] for pypdf-specific cases and data["dependencies"][2] for the native-wheel python_version mismatch (Line 86). If the manifest entries are ever reordered, these tests silently mutate a different package than intended, and a failure message can point to the wrong root cause without the test itself failing to compile or immediately signal the mismatch.

Look up the target entry by name instead of by list position.

♻️ Proposed fix
+def _dependency(data: dict[str, object], name: str) -> dict[str, object]:
+    return next(d for d in data["dependencies"] if d["name"] == name)
+
+
 `@pytest.mark.parametrize`(
     ("mutation", "failure"),
     [
         (
-            lambda data: data["dependencies"][0].update(version=">=6"),
+            lambda data: _dependency(data, "pypdf").update(version=">=6"),
             "guide_dependency_version_unpinned",
         ),
         ...
         (
-            lambda data: data["dependencies"][2]["approved_artifacts"][0].update(
+            lambda data: _dependency(data, "pillow")["approved_artifacts"][0].update(
                 python_version="3.13"
             ),
             "guide_dependency_artifact_platform_mismatch",
         ),
         ...
     ],
 )
🤖 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 `@backend/tests/test_guide_extractor_dependencies.py` around lines 62 - 119,
Update the mutation cases in
test_manifest_rejects_unpinned_hash_drifted_or_wrong_scope_entries to locate
dependency entries by their name instead of positional indices, including the
pypdf and native-wheel cases; keep each mutation targeting the same intended
package and preserve the existing failure expectations.
backend/scripts/check_guide_extractor_dependencies.py (4)

457-461: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

One transient GitHub error blocks the merge.

Any single 5xx response, rate-limit response, or socket error raises guide_dependency_github_reviews_unavailable and fails the required check. Add a small bounded retry with backoff for retryable statuses, and keep the fail-closed result after the retries.

🤖 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 `@backend/scripts/check_guide_extractor_dependencies.py` around lines 457 -
461, Update the GitHub review request flow around the urllib.request.urlopen
call to retry transient failures, including 5xx responses, rate-limit responses,
and socket/OSError failures, using a small bounded retry count and backoff.
After retries are exhausted, preserve the existing fail-closed
DependencyGateError("guide_dependency_github_reviews_unavailable") behavior; do
not retry non-retryable errors.

371-391: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Dynamic imports bypass the parser import boundary.

The AST walk inspects only Import and ImportFrom nodes. A parser module can reach an unapproved package through importlib.import_module or __import__, because importlib is a stdlib name. Consider rejecting importlib.import_module and __import__ calls inside the parser modules.

🤖 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 `@backend/scripts/check_guide_extractor_dependencies.py` around lines 371 -
391, The AST validation around the existing Import and ImportFrom handling must
also reject dynamic imports in parser modules. Extend the ast.walk checks to
detect calls to importlib.import_module and __import__, while retaining the
current approved-import validation for static imports and allowing unrelated
calls.

274-290: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Native entries do not need to cover every approved Python version.

Each artifact is checked against approved_python_versions, but no check requires a wheel for each approved version. A manifest with only a cp311 wheel passes, and a hash-pinned install on 3.12 then fails. Require full coverage per native package.

♻️ Proposed check after the artifact loop
+        if entry["native_code"]:
+            require(
+                {artifact["python_version"] for artifact in artifacts}
+                == set(policy["approved_python_versions"]),
+                "guide_dependency_artifact_python_coverage_incomplete",
+            )
         by_name[canonical_name] = entry
🤖 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 `@backend/scripts/check_guide_extractor_dependencies.py` around lines 274 -
290, Update the native artifact validation around the native-entry loop to
require every native package to provide a wheel for each version in
policy["approved_python_versions"], while preserving the existing filename and
platform checks. Track the versions encountered per native package and add a
post-loop validation that rejects incomplete coverage, using the existing
guide_dependency_artifact_platform_mismatch error.

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

Use the keyword form for maxsplit in _dependency_name.

re.split accepts maxsplit positionally now, but CPython 3.13 treats it as deprecated. Pass maxsplit=1 so the backend script is not flagged in future Python versions.

♻️ Proposed change
-    return normalize_package_name(re.split(r"[<>=!~\s;\[]", requirement.strip(), 1)[0])
+    return normalize_package_name(
+        re.split(r"[<>=!~\s;\[]", requirement.strip(), maxsplit=1)[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 `@backend/scripts/check_guide_extractor_dependencies.py` around lines 301 -
302, Update the re.split call in _dependency_name to pass the split limit with
the maxsplit=1 keyword argument instead of positionally, preserving the existing
parsing behavior.
backend/config/guide_extractor_dependencies.json (1)

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

Approved artifacts cover only manylinux x86_64.

require_hashes is true and only x86_64 manylinux Pillow wheels are approved. When parser code declares the hash-bound direct reference, installation fails on macOS and on arm64 Linux. Decide now whether contributor and arm64 environments need approved wheels, or record that only the hosted x86_64 runner installs parser dependencies.

Also applies to: 109-118

🤖 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 `@backend/config/guide_extractor_dependencies.json` around lines 74 - 84,
Update the Pillow artifacts in the dependency guide so the hash-bound approvals
support every required contributor and runtime platform, including macOS and
arm64 Linux, rather than only manylinux x86_64. Add the corresponding
platform-specific wheel entries with their exact filenames, Python versions,
SHA-256 hashes, and URLs; if those environments are intentionally unsupported,
explicitly document that the parser dependencies install only on the hosted
x86_64 runner.
🤖 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-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-external-review-response.md:
- Around line 16-20: Document that fresh independent approval of the repaired
final PR head is pending in the “Human decisions needed” section of
.agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-external-review-response.md
(lines 16-20), replacing “None”; in
.agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/STATUS.md (lines
70-74), replace “exact allowlist head” with “exact final PR head” so both
records require approval on the repaired final head.

In @.github/workflows/backend.yml:
- Around line 63-78: Update the “Guide extractor dependency approval” workflow
step so pull_request_review events validate the pull-request head checkout
rather than the default-branch ref. Ensure the referenced WORKSTREAM_PR_BASE_SHA
and WORKSTREAM_PR_HEAD_SHA commits are available, including for fork PRs, before
invoking check_guide_extractor_dependencies.py with --require-pr-approval;
alternatively restrict this step to pull_request events and preserve separate
approval enforcement for review events.

In `@backend/scripts/check_guide_extractor_dependencies.py`:
- Around line 233-236: Update validate_manifest at
backend/scripts/check_guide_extractor_dependencies.py lines 233-236 so
release_uploaded_at is passed through _string with
guide_dependency_release_timestamp_invalid before calling endswith("Z"). Apply
the same validation at lines 259-262 for artifact["sha256"], using _string with
guide_dependency_artifact_hash_invalid before SHA256_PATTERN.fullmatch.
- Around line 413-436: Update the review aggregation before the candidate filter
so latest_by_reviewer is updated only for state-bearing reviews, excluding
COMMENTED entries that should not replace an existing approval. Preserve the
existing per-reviewer deduplication and exact-head approval checks in the
candidates loop, ensuring a later non-state-bearing comment cannot erase a valid
APPROVED review.

---

Nitpick comments:
In `@backend/config/guide_extractor_dependencies.json`:
- Around line 74-84: Update the Pillow artifacts in the dependency guide so the
hash-bound approvals support every required contributor and runtime platform,
including macOS and arm64 Linux, rather than only manylinux x86_64. Add the
corresponding platform-specific wheel entries with their exact filenames, Python
versions, SHA-256 hashes, and URLs; if those environments are intentionally
unsupported, explicitly document that the parser dependencies install only on
the hosted x86_64 runner.

In `@backend/scripts/check_guide_extractor_dependencies.py`:
- Around line 457-461: Update the GitHub review request flow around the
urllib.request.urlopen call to retry transient failures, including 5xx
responses, rate-limit responses, and socket/OSError failures, using a small
bounded retry count and backoff. After retries are exhausted, preserve the
existing fail-closed
DependencyGateError("guide_dependency_github_reviews_unavailable") behavior; do
not retry non-retryable errors.
- Around line 371-391: The AST validation around the existing Import and
ImportFrom handling must also reject dynamic imports in parser modules. Extend
the ast.walk checks to detect calls to importlib.import_module and __import__,
while retaining the current approved-import validation for static imports and
allowing unrelated calls.
- Around line 274-290: Update the native artifact validation around the
native-entry loop to require every native package to provide a wheel for each
version in policy["approved_python_versions"], while preserving the existing
filename and platform checks. Track the versions encountered per native package
and add a post-loop validation that rejects incomplete coverage, using the
existing guide_dependency_artifact_platform_mismatch error.
- Around line 301-302: Update the re.split call in _dependency_name to pass the
split limit with the maxsplit=1 keyword argument instead of positionally,
preserving the existing parsing behavior.

In `@backend/tests/test_guide_extractor_dependencies.py`:
- Around line 306-321: Update test_github_review_fetch_returns_valid_payload to
capture the Request argument received by the urlopen stub instead of ignoring
it, then assert that the request full_url targets the expected repository, pull
request, and reviews endpoint and that its headers contain the correct
Authorization token and HTTP method. Keep the existing response parsing
assertion.
- Around line 62-119: Update the mutation cases in
test_manifest_rejects_unpinned_hash_drifted_or_wrong_scope_entries to locate
dependency entries by their name instead of positional indices, including the
pypdf and native-wheel cases; keep each mutation targeting the same intended
package and preserve the existing failure expectations.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f0d6003-de29-4f5c-9338-6c67f9760bec

📥 Commits

Reviewing files that changed from the base of the PR and between 3b2b216 and 92cceee.

📒 Files selected for processing (11)
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/REVIEW_LOG.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/STATUS.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/chunks/WS-ART-001-03B3B1-parser-dependency-approval.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-external-review-response.md
  • .agent-loop/initiatives/WS-ART-001-immutable-artifact-storage/reviews/WS-ART-001-03B3B1-pr-trust-bundle.md
  • .github/workflows/backend.yml
  • backend/config/guide_extractor_dependencies.json
  • backend/scripts/check_guide_extractor_dependencies.py
  • backend/scripts/run_test_lanes.py
  • backend/tests/test_guide_extractor_dependencies.py
  • docs/spec_artifact_storage_service.md

Comment on lines +63 to +78
- name: Guide extractor dependency approval
working-directory: backend
env:
GITHUB_TOKEN: ${{ github.token }}
WORKSTREAM_PR_AUTHOR: ${{ github.event.pull_request.user.login }}
WORKSTREAM_PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
WORKSTREAM_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
WORKSTREAM_PR_NUMBER: ${{ github.event.pull_request.number }}
shell: bash
run: |
set -euo pipefail
approval_args=()
if [[ "${GITHUB_EVENT_NAME}" != "push" ]]; then
approval_args+=(--require-pr-approval)
fi
python scripts/check_guide_extractor_dependencies.py "${approval_args[@]}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect workflow triggers, checkout inputs, and identity assertions for event coupling.
set -uo pipefail
fd -t f 'backend.yml' .github/workflows --exec rg -n -C4 'on:|pull_request|checkout|ref:|fetch-depth|GITHUB_SHA|tree_sha|require-pr-approval'

Repository: Flow-Research/workstream

Length of output: 3403


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Candidate files"
fd -t f 'check_guide_extractor_dependencies.py|guide_extractor|guide.*dependency|dependency' .

echo
echo "## workflows backend relevant lines"
sed -n '36,86p;250,290p;420,435p' .github/workflows/backend.yml

echo
echo "## scripts outline"
for f in $(fd -t f 'check_guide_extractor_dependencies.py' .); do
  echo "--- $f"
  wc -l "$f"
  sed -n '1,260p' "$f"
done

echo
echo "## Diff semantics references in repo"
rg -n "allowlist_changed|git diff|guide_dependency_git_diff_failed|pull request head|head_sha|base_sha|require-pr-approval|dependency" scripts .github/workflows backend -S

Repository: Flow-Research/workstream

Length of output: 50047


On pull_request_review, the dependency approval gate checks out the default branch while comparing against the pull-request head.

pull_request_review sets ${{ github.sha }} to the default-branch ref, but this job enables --require-pr-approval for ${{ github.event.pull_request.head.sha }} and the script runs git diff ${base_sha}...${head_sha} -- guide_extractor_dependencies.json. The approved head_sha can pass while the checked-out workflow actually validates default-branch artifacts.

For a fork PR, the head commit is missing from the clone, so git diff base...head -- guide_extractor_dependencies.json exits non-zero and the script fails with guide_dependency_git_diff_failed.

Use the pull-request head checkout for review events, or restrict this step to pull_request events and enforce approval by head separately.

🤖 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 @.github/workflows/backend.yml around lines 63 - 78, Update the “Guide
extractor dependency approval” workflow step so pull_request_review events
validate the pull-request head checkout rather than the default-branch ref.
Ensure the referenced WORKSTREAM_PR_BASE_SHA and WORKSTREAM_PR_HEAD_SHA commits
are available, including for fork PRs, before invoking
check_guide_extractor_dependencies.py with --require-pr-approval; alternatively
restrict this step to pull_request events and preserve separate approval
enforcement for review events.

Comment thread backend/scripts/check_guide_extractor_dependencies.py
Comment thread backend/scripts/check_guide_extractor_dependencies.py
@Abiorh001

Copy link
Copy Markdown
Collaborator Author

@abiorh-claw Final CodeRabbit repair is pushed at exact head a5f86839. Three valid findings were fixed with regression tests; the workflow-checkout finding was rejected using hosted review-event evidence. Focused dependency tests plus exact lane inventory pass (38 tests total, 93.07% checker coverage), and security/CI/QA re-reviews pass. Please approve this exact final head so Backend can proceed.

…to codex/ws-art-001-03b3b1-parser-dependency-approval
@abiorh-claw
abiorh-claw self-requested a review July 31, 2026 07:39
@abiorh-claw
abiorh-claw merged commit 54bcee0 into main Jul 31, 2026
5 checks passed
@abiorh-claw
abiorh-claw deleted the codex/ws-art-001-03b3b1-parser-dependency-approval branch July 31, 2026 08:15
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.

2 participants