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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/hourly-nvidia-nim-review-repair.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ on:
- .github/workflows/governance-risk-compliance-hourly-review-repair.yml
- .github/workflows/hourly-nvidia-nim-review-repair.yml
- .github/workflows/nonnest2-hourly-review-repair.yml
- .github/workflows/naruon-hourly-review-repair.yml
- .github/workflows/orgmetra-hourly-review-repair.yml
- .github/workflows/originweave-hourly-review-repair.yml
- .github/workflows/quarantine-sandbox-hourly-review-repair.yml
Expand All @@ -26,6 +27,7 @@ on:
- tests/test_governance_risk_compliance_hourly_review_caller.py
- tests/test_hourly_scheduler_runtime_budget.py
- tests/test_nonnest2_hourly_review_caller.py
- tests/test_naruon_hourly_review_caller.py
- tests/test_orgmetra_hourly_review_caller.py
- tests/test_originweave_hourly_review_caller.py
- tests/test_quarantine_sandbox_hourly_review_caller.py
Expand All @@ -51,6 +53,7 @@ on:
- docs/doctoring/governance-risk-compliance-hourly-review-caller.md
- docs/doctoring/hourly-nvidia-nim-autofix.md
- docs/doctoring/nonnest2-hourly-review-caller.md
- docs/doctoring/naruon-hourly-review-caller.md
- docs/doctoring/orgmetra-hourly-review-caller.md
- docs/doctoring/originweave-hourly-review-caller.md
- docs/doctoring/quarantine-sandbox-hourly-review-caller.md
Expand All @@ -67,6 +70,7 @@ on:
- .github/workflows/governance-risk-compliance-hourly-review-repair.yml
- .github/workflows/hourly-nvidia-nim-review-repair.yml
- .github/workflows/nonnest2-hourly-review-repair.yml
- .github/workflows/naruon-hourly-review-repair.yml
- .github/workflows/orgmetra-hourly-review-repair.yml
- .github/workflows/originweave-hourly-review-repair.yml
- .github/workflows/quarantine-sandbox-hourly-review-repair.yml
Expand All @@ -79,6 +83,7 @@ on:
- tests/test_governance_risk_compliance_hourly_review_caller.py
- tests/test_hourly_scheduler_runtime_budget.py
- tests/test_nonnest2_hourly_review_caller.py
- tests/test_naruon_hourly_review_caller.py
- tests/test_orgmetra_hourly_review_caller.py
- tests/test_originweave_hourly_review_caller.py
- tests/test_quarantine_sandbox_hourly_review_caller.py
Expand All @@ -104,6 +109,7 @@ on:
- docs/doctoring/governance-risk-compliance-hourly-review-caller.md
- docs/doctoring/hourly-nvidia-nim-autofix.md
- docs/doctoring/nonnest2-hourly-review-caller.md
- docs/doctoring/naruon-hourly-review-caller.md
- docs/doctoring/orgmetra-hourly-review-caller.md
- docs/doctoring/originweave-hourly-review-caller.md
- docs/doctoring/quarantine-sandbox-hourly-review-caller.md
Expand Down Expand Up @@ -161,6 +167,7 @@ jobs:
tests/test_governance_risk_compliance_hourly_review_caller.py \
tests/test_hourly_scheduler_runtime_budget.py \
tests/test_nonnest2_hourly_review_caller.py \
tests/test_naruon_hourly_review_caller.py \
tests/test_orgmetra_hourly_review_caller.py \
tests/test_originweave_hourly_review_caller.py \
tests/test_quarantine_sandbox_hourly_review_caller.py \
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/naruon-hourly-review-repair.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Naruon Hourly Review Repair

on:
schedule:
# Minute 11 is reserved for naruon in the central hourly queue.
- cron: "11 * * * *"

concurrency:
group: naruon-hourly-review-repair
cancel-in-progress: false

permissions:
contents: read

jobs:
dispatch-review-repair:
permissions:
contents: read
id-token: write
uses: ./.github/workflows/pr-review-fix-scheduler.yml
with:
target_repository: ContextualWisdomLab/naruon
base_branch: develop
max_prs: "50"
max_dispatches: "1"
retry_hours: "2"
secrets:
PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ Materialize accepts only exact SHA-256 pins or a bounded relative `-r` include (
Conflict-scope roots fail closed when the immediate parent directory is a symbolic link.
OriginWeave hourly NVIDIA NIM repair is a thin caller at minute 10. See [`docs/doctoring/originweave-hourly-review-caller.md`](docs/doctoring/originweave-hourly-review-caller.md).
nonnest2 hourly NVIDIA NIM repair is a thin caller at minute 16. See [`docs/doctoring/nonnest2-hourly-review-caller.md`](docs/doctoring/nonnest2-hourly-review-caller.md).
naruon hourly NVIDIA NIM repair is a thin caller at minute 11. See [`docs/doctoring/naruon-hourly-review-caller.md`](docs/doctoring/naruon-hourly-review-caller.md).
The materialization contract is also covered by [`docs/doctoring/exact-artifact-sbom-attestation.md`](docs/doctoring/exact-artifact-sbom-attestation.md).
47 changes: 47 additions & 0 deletions docs/doctoring/naruon-hourly-review-caller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# naruon hourly review-repair caller

검토 기준일: **2026-08-19**

## Decision

ContextualWisdomLab operates one protected hourly caller for
`ContextualWisdomLab/naruon`, the email-first knowledge-graph workspace. The
caller runs at minute 11, delegates to the product-neutral central review-fix
scheduler, inspects at most 50 open pull requests targeting protected
`develop`, and dispatches at most one bounded repair per heartbeat.

The caller does not implement review or mutation logic. It keeps naruon
standalone while privileged automation remains in `ContextualWisdomLab/.github`.
The two-hour same-head retry floor prevents duplicate writer pressure when
OpenCode, security checks, or attachment-parser validation outlasts one
heartbeat. Queued checks and missing independent approval remain merge gates;
the repair worker cannot manufacture either result.

## Credential and authority boundary

The caller exposes only `contents: read` and job-scoped `id-token: write`. It
maps `PR_REVIEW_MERGE_TOKEN` and `OPENCODE_APPROVE_TOKEN` explicitly, and never
forwards `NVIDIA_NIM_API_KEY`, `COPILOT_GITHUB_TOKEN`, or `secrets: inherit`.
The reusable scheduler validates the exact target and dispatch authority before
materializing mutation credentials.

## Verification and rollback

Contract tests pin the minute 11 cadence, target repository, `develop` base,
single dispatch, two-hour retry floor, explicit secret scope, and central
quality-workflow path filters. Scheduled execution is the operational
acceptance check; source tests alone do not prove a protected-branch merge.

Rollback removes this caller, its contract test, doctoring, and path-filter
entries. It does not change the reusable scheduler or other product callers.

## APA 7th references

GitHub, Inc. (n.d.). *Events that trigger workflows*. GitHub Docs.
https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#schedule

GitHub, Inc. (n.d.). *Reuse workflows*. GitHub Docs.
https://docs.github.com/en/actions/how-tos/sharing-automations/reuse-workflows

GitHub, Inc. (n.d.). *Automatic token authentication*. GitHub Docs.
https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication
6 changes: 3 additions & 3 deletions requirements-pip-audit-ci-hashes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,9 @@ packaging==26.2 \
# via
# pip-audit
# pip-requirements-parser
pip==26.1.2 \
--hash=sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab \
--hash=sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605
pip==26.2.1 \
--hash=sha256:71138adf1f4ca900cdb7d289c21b7494329f2332b6d85f0e1c42108c0384ed3e \
--hash=sha256:f6ad667e89a1fe78046c8f13232b247200f5258d7828f3f7883d660878e0813f
Comment on lines +216 to +218

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 Unrelated pip hash bump bundled in

requirements-pip-audit-ci-hashes.txt bumps pip 26.1.2 to 26.2.1, unrelated to scheduling the naruon caller. Confirm the lock was regenerated via the recorded uv pip compile command rather than hand-edited.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

# via pip-api
pip-api==0.0.34 \
--hash=sha256:8b2d7d7c37f2447373aa2cf8b1f60a2f2b27a84e1e9e0294a3f6ef10eb3ba6bb \
Expand Down
73 changes: 73 additions & 0 deletions tests/test_naruon_hourly_review_caller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Contract tests for naruon's bounded hourly review-repair caller."""

from pathlib import Path


CALLER = Path(".github/workflows/naruon-hourly-review-repair.yml")
DOCTORING = Path("docs/doctoring/naruon-hourly-review-caller.md")
QUALITY_WORKFLOW = Path(".github/workflows/hourly-nvidia-nim-review-repair.yml")


def _read(path: Path) -> str:
"""Return one repository contract file as UTF-8 text."""
return path.read_text(encoding="utf-8")


def test_naruon_caller_is_hourly_bounded_and_non_cancelling() -> None:
"""naruon gets one protected-develop repair heartbeat per hour."""
caller = _read(CALLER)

assert 'cron: "11 * * * *"' in caller
assert "group: naruon-hourly-review-repair" in caller
assert "cancel-in-progress: false" in caller
assert "uses: ./.github/workflows/pr-review-fix-scheduler.yml" in caller
assert "target_repository: ContextualWisdomLab/naruon" in caller
assert "base_branch: develop" in caller
assert 'max_prs: "50"' in caller
assert 'max_dispatches: "1"' in caller
assert 'retry_hours: "2"' in caller


def test_naruon_caller_keeps_token_and_secret_scope_explicit() -> None:
"""The caller forwards only established scheduler credentials."""
caller = _read(CALLER)
workflow_scope, jobs_scope = caller.split("\njobs:\n", maxsplit=1)

assert "\npermissions:\n contents: read\n" in workflow_scope
assert "\n permissions:\n contents: read\n id-token: write\n" in jobs_scope
assert "PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}" in caller
assert "OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}" in caller
assert "secrets: inherit" not in caller
assert "NVIDIA_NIM_API_KEY" not in caller
assert "COPILOT_GITHUB_TOKEN" not in caller
for forbidden in (
"actions: write",
"contents: write",
"issues: write",
"pull-requests: write",
"statuses: write",
):
assert forbidden not in caller


def test_naruon_contract_and_doctoring_are_path_filtered() -> None:
"""The central contract gate follows caller and doctoring changes."""
quality = _read(QUALITY_WORKFLOW)
for path in (
".github/workflows/naruon-hourly-review-repair.yml",
"docs/doctoring/naruon-hourly-review-caller.md",
):
assert quality.count(path) == 2
assert quality.count("tests/test_naruon_hourly_review_caller.py") == 3

doctoring = _read(DOCTORING)
for phrase in (
"ContextualWisdomLab/naruon",
"minute 11",
"base",
"two-hour same-head retry floor",
"NVIDIA_NIM_API_KEY",
"COPILOT_GITHUB_TOKEN",
"independent approval",
):
assert phrase in doctoring
Loading