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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/afipc-hourly-review-repair.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ on:
# html4tree (15), nonnest2 (16), orchestrator (17), newsdom-api (18),
# noema (19), github (21), Clearfolio (23), accounting-information-platform (27),
# Keyverse (29), Scopeweave (31), contextual-orchestrator (34), DiskSage (37), Appguardrail (41),
# governance-risk-compliance (43), Inkspan (47), fast-mlsirm (49),
# BandScope (53), orgmetra (58), and semantic-data-portal (59).
# governance-risk-compliance (43), fast-mlsirm (49), BandScope (53),
# Inkspan (56), orgmetra (58), and semantic-data-portal (59).
- cron: "2 * * * *"

concurrency:
Expand Down
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 @@ -10,6 +10,7 @@ on:
- .github/workflows/contextual-orchestrator-hourly-review-repair.yml
- .github/workflows/clearfolio-hourly-review-repair.yml
- .github/workflows/disksage-hourly-review-repair.yml
- .github/workflows/inkspan-hourly-review-repair.yml
- .github/workflows/fast-mlsirm-hourly-review-repair.yml
- .github/workflows/github-hourly-review-repair.yml
- .github/workflows/governance-risk-compliance-hourly-review-repair.yml
Expand All @@ -23,6 +24,7 @@ on:
- scripts/ci/pr_review_autofix_context.py
- tests/test_bandscope_hourly_review_caller.py
- tests/test_disksage_hourly_review_caller.py
- tests/test_inkspan_hourly_review_caller.py
- tests/test_fast_mlsirm_hourly_review_caller.py
- tests/test_github_hourly_conflict_repair.py
- tests/test_governance_risk_compliance_hourly_review_caller.py
Expand Down Expand Up @@ -50,6 +52,7 @@ on:
- docs/doctoring/clearfolio-hourly-review-caller.md
- docs/doctoring/conflict-control-evidence-isolation.md
- docs/doctoring/disksage-hourly-review-caller.md
- docs/doctoring/inkspan-hourly-review-caller.md
- docs/doctoring/fast-mlsirm-hourly-review-caller.md
- docs/doctoring/github-hourly-conflict-repair.md
- docs/doctoring/governance-risk-compliance-hourly-review-caller.md
Expand All @@ -69,6 +72,7 @@ on:
- .github/workflows/contextual-orchestrator-hourly-review-repair.yml
- .github/workflows/clearfolio-hourly-review-repair.yml
- .github/workflows/disksage-hourly-review-repair.yml
- .github/workflows/inkspan-hourly-review-repair.yml
- .github/workflows/fast-mlsirm-hourly-review-repair.yml
- .github/workflows/github-hourly-review-repair.yml
- .github/workflows/governance-risk-compliance-hourly-review-repair.yml
Expand All @@ -82,6 +86,7 @@ on:
- scripts/ci/pr_review_autofix_context.py
- tests/test_bandscope_hourly_review_caller.py
- tests/test_disksage_hourly_review_caller.py
- tests/test_inkspan_hourly_review_caller.py
- tests/test_fast_mlsirm_hourly_review_caller.py
- tests/test_github_hourly_conflict_repair.py
- tests/test_governance_risk_compliance_hourly_review_caller.py
Expand Down Expand Up @@ -109,6 +114,7 @@ on:
- docs/doctoring/clearfolio-hourly-review-caller.md
- docs/doctoring/conflict-control-evidence-isolation.md
- docs/doctoring/disksage-hourly-review-caller.md
- docs/doctoring/inkspan-hourly-review-caller.md
- docs/doctoring/fast-mlsirm-hourly-review-caller.md
- docs/doctoring/github-hourly-conflict-repair.md
- docs/doctoring/governance-risk-compliance-hourly-review-caller.md
Expand Down Expand Up @@ -168,6 +174,7 @@ jobs:
tests/test_pr_review_conflict_scope.py \
tests/test_bandscope_hourly_review_caller.py \
tests/test_disksage_hourly_review_caller.py \
tests/test_inkspan_hourly_review_caller.py \
tests/test_fast_mlsirm_hourly_review_caller.py \
tests/test_github_hourly_conflict_repair.py \
tests/test_governance_risk_compliance_hourly_review_caller.py \
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/inkspan-hourly-review-repair.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Inkspan Hourly Review Repair
Comment thread
seonghobae marked this conversation as resolved.

on:
schedule:
# Minute 56 avoids every existing hourly heartbeat minute and the
# half-hourly merge scheduler ticks.
- cron: "56 * * * *"
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.

concurrency:
group: inkspan-hourly-review-repair
# The queue scan is bounded and the worker has its own exact-head lease. Do not
# discard an in-flight RCA merely because the next hourly heartbeat arrives.
cancel-in-progress: false

permissions:
contents: read
Comment thread
seonghobae marked this conversation as resolved.

jobs:
dispatch-review-repair:
uses: ./.github/workflows/pr-review-fix-scheduler.yml
Comment thread
seonghobae marked this conversation as resolved.
permissions:
contents: read
id-token: write
with:
target_repository: ContextualWisdomLab/inkspan
base_branch: main
max_prs: "50"
max_dispatches: "1"
# Central OpenCode/NVIDIA NIM work can legitimately approach two hours.
# A two-hour same-head floor avoids duplicate writers without freezing the
# next eligible PR or confusing provider latency with a source-code defect.
retry_hours: "2"
Comment thread
seonghobae marked this conversation as resolved.
secrets:
PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/nonnest2-hourly-review-repair.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
# DiagramWeave (12), pg-erd-cloud (13), mhtml-etl-gateway (14),
# html4tree (15), orchestrator (17), noema (19), Clearfolio (23),
# Keyverse (29), Scopeweave (31), contextual-orchestrator (34), DiskSage (37), Appguardrail (41),
# newsdom-api (43), Inkspan (47), fast-mlsirm (49), BandScope (53),
# newsdom-api (43), fast-mlsirm (49), BandScope (53), Inkspan (56),
# and semantic-data-portal (59).
- cron: "16 * * * *"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/originweave-hourly-review-repair.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
# psychometrics-commons (9), naruon (11), pg-erd-cloud (13),
# orchestrator (17), noema (19), Clearfolio (23), Keyverse (29),
# Scopeweave (31), contextual-orchestrator (34), DiskSage (37), Appguardrail (41), newsdom-api (43),
# Inkspan (47), fast-mlsirm (49), BandScope (53), and
# fast-mlsirm (49), BandScope (53), Inkspan (56), and
# semantic-data-portal (59).
- cron: "10 * * * *"

Expand Down
59 changes: 59 additions & 0 deletions docs/doctoring/inkspan-hourly-review-caller.md
Comment thread
seonghobae marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Inkspan hourly review-repair caller

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

## Decision

ContextualWisdomLab operates one protected hourly caller for
`ContextualWisdomLab/inkspan` (deterministic Markdown/HTML authoring and
bounded document/evidence contracts). The caller runs at minute 56, delegates
to the product-neutral central review-fix scheduler, inspects at most 50 open
pull requests targeting protected `main`, and dispatches at most one bounded
repair per heartbeat.

A paying buyer of commercial-grade editor tooling would feel live Inkspan pull
requests stalling while the hourly NVIDIA NIM repair loop scanned only other
products in the organization. Live heads such as ContextualWisdomLab/inkspan#299
(stacked-PR CI gates), ContextualWisdomLab/inkspan#362 (editor contrast and keyboard focus), and the
writing-diagnostics stack sit in exactly that blind spot when their checks are
green but central review evidence is missing or stale.

The caller does not implement review or mutation logic itself. Inkspan remains
standalone and embeddable; hosts consume `@contextualwisdomlab/cwl-editor`
without owning privileged automation. All mutation authority stays sealed in
`ContextualWisdomLab/.github` behind `PR_REVIEW_MERGE_TOKEN` /
`OPENCODE_APPROVE_TOKEN`.

## Root-cause analysis and remediation feasibility

The reusable worker performs exact-head root-cause analysis, tests remediation
feasibility, and edits only when one small reversible action can change the
diagnosed cause inside its sealed writer authority. It follows the shared
transitions documented in the central scheduler contract: refetch live state,
establish the causal chain, enumerate materially distinct minimal remedies,
reject infeasible ones, and dispatch at most one repair per heartbeat.

Minute 56 (this caller) shares no heartbeat minute with any other hourly
caller: the occupied minutes are 2, 10, 14, 16, 21, 23, 27, 34, 37, 43, 49,
53, and 58, so runner capacity is not contested at dispatch time.

## Consequences

- Inkspan gains parity with disksage, nonnest2, Clearfolio, afipc, and
fast-mlsirm for bounded hourly unattended review-repair throughput.
- The two-hour same-head retry floor prevents duplicate writers while keeping
unrelated PR lanes moving every hour.
- No COPILOT_GITHUB_TOKEN is used; existing review-agent key chains are
untouched.
- The reusable job receives `id-token: write` and `contents: read`, enabling
its documented OIDC fallback while preserving least privilege.

The protected merge path still requires an independent non-author approval at
the exact head. The workflow forwards the existing `PR_REVIEW_MERGE_TOKEN` and
`OPENCODE_APPROVE_TOKEN`; the NVIDIA model credential is supplied by the
central worker as `NVIDIA_NIM_API_KEY` and is never embedded in this caller.

## APA 7th references

GitHub. (n.d.). *OpenID Connect in GitHub Actions*. Retrieved August 25, 2026,
from https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect
77 changes: 77 additions & 0 deletions tests/test_inkspan_hourly_review_caller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""Contract tests for Inkspan's bounded hourly review-repair caller."""

from pathlib import Path


CALLER = Path(".github/workflows/inkspan-hourly-review-repair.yml")
DOCTORING = Path("docs/doctoring/inkspan-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_inkspan_caller_is_hourly_bounded_and_non_cancelling() -> None:
"""Inkspan receives one bounded repair opportunity without overlap cancellation."""
caller = _read(CALLER)

assert 'cron: "56 * * * *"' in caller
assert "group: inkspan-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/inkspan" in caller
assert "base_branch: main" in caller
assert 'max_prs: "50"' in caller
assert 'max_dispatches: "1"' in caller
assert 'retry_hours: "2"' in caller


def test_inkspan_caller_preserves_credentials_and_oidc_scope() -> None:
"""The caller grants only reusable-worker read/OIDC permissions."""
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_inkspan_doctoring_records_governance_and_research_bounds() -> None:
"""Operators retain RCA, credential, approval, and citation contracts."""
doctoring = _read(DOCTORING)

for phrase in (
"root-cause analysis",
"remediation feasibility",
"two-hour same-head retry floor",
"independent non-author approval",
"NVIDIA_NIM_API_KEY",
"COPILOT_GITHUB_TOKEN",
"ContextualWisdomLab/inkspan#299",
"ContextualWisdomLab/inkspan#362",
"APA 7th references",
):
assert phrase in doctoring


def test_focused_quality_workflow_tracks_inkspan_caller_contracts() -> None:
"""Caller and doctoring edits rerun exact-head scheduler verification."""
quality = _read(QUALITY_WORKFLOW)

assert quality.count(".github/workflows/inkspan-hourly-review-repair.yml") == 2
assert quality.count("docs/doctoring/inkspan-hourly-review-caller.md") == 2
assert quality.count("tests/test_inkspan_hourly_review_caller.py") == 3
Comment thread
seonghobae marked this conversation as resolved.
Loading