Skip to content
Draft
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
16 changes: 7 additions & 9 deletions .github/workflows/hourly-review-repair.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,10 @@ on:
# central merge scheduler to consume the queue.
# -- Orgmetra (formerly orgmetra-hourly-review-repair.yml)
- cron: "58 15 * * *"
# Minute 59 is reserved for semantic-data-portal in the organization
# caller ledger and is unique among product heartbeats. GitHub may delay
# scheduled runs, so this is a heartbeat rather than a minute-zero surge
# avoidance guarantee.
# -- semantic-data-portal (formerly semantic-data-portal-hourly-review-repair.yml)
# Minute 59 remains a single daily semantic-plane recovery trigger. It
# fans out to semantic-data-portal and ConceptWeave through independent
# per-repository concurrency groups; neither product owns the other's work.
# -- semantic-data-portal + ConceptWeave
- cron: "59 16 * * *"

# Coalesce admissions before resolve-target needs a runner.
Expand Down Expand Up @@ -213,9 +212,8 @@ jobs:
TARGETS='[{"name":"orgmetra","target_repository":"ContextualWisdomLab/Orgmetra","base_branch":"develop","retry_hours":"2","concurrency_group":"orgmetra-hourly-review-repair"}]'
;;
"59 16 * * *")
# 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.
TARGETS='[{"name":"semantic-data-portal","target_repository":"ContextualWisdomLab/semantic-data-portal","base_branch":"main","retry_hours":"2","concurrency_group":"semantic-data-portal-hourly-review-repair"}]'
# Keep the ontology owner and catalog/governance consumer in separate leases.
TARGETS='[{"name":"semantic-data-portal","target_repository":"ContextualWisdomLab/semantic-data-portal","base_branch":"main","retry_hours":"2","concurrency_group":"semantic-data-portal-hourly-review-repair"},{"name":"conceptweave","target_repository":"ContextualWisdomLab/ConceptWeave","base_branch":"main","retry_hours":"2","concurrency_group":"conceptweave-hourly-review-repair"}]'
;;
*)
echo "::error::Unrecognized schedule '$SCHEDULE'; no target repository is configured for it." >&2
Expand Down Expand Up @@ -266,4 +264,4 @@ jobs:
resolve_unreviewed_conflicts: true
secrets:
PR_REVIEW_MERGE_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
43 changes: 43 additions & 0 deletions docs/doctoring/conceptweave-review-repair-target-enrollment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# ConceptWeave bounded review-repair target enrollment

Date: 2026-09-20

## Problem

`ContextualWisdomLab/ConceptWeave` has valid exact-head review findings but was absent from the protected central `hourly-review-repair.yml` target lookup and from the source-controlled mirror of `OPENCODE_REPOSITORY_DISPATCH_TARGETS`. Mention-triggered OpenCode is review-only, so an `@opencode-agent` comment is not a source-writer handoff. The edit-capable owner remains the central `pr_review_fix_scheduler.py -> pr-review-autofix.yml` path.

ConceptWeave PR #46 exact `974972e2885baa956af9b728fee158b1782704d1` is the concrete consumer case: its executable relation-kind/index-ownership RED needs a bounded same-head writer, not a second product-local workflow.

## Decision

Enroll ConceptWeave in the existing consolidated central recovery caller instead of creating a repository-local caller or widening review-agent permissions.

The existing `59 16 * * *` daily missed-event recovery is shared with `semantic-data-portal`. The matrix keeps separate `target_repository` and `concurrency_group` values, so sharing the trigger does not merge product ownership or cancellation leases. ConceptWeave uses protected base `main`, `retry_hours = 2`, `max_dispatches = 1`, and the existing central scheduler/autofix implementation.

The source-controlled dispatch-target mirror also includes the exact `ContextualWisdomLab/ConceptWeave` repository name. The live repository variable remains a separate deployment prerequisite because source control cannot mutate that configuration by itself.

## RED -> repair trace

- Protected base: `.github/main@e6334e229581a918e2f22de18733b76fa65d7e71`.
- RED commit: `b530783d09a656fe4ddc324243dd15de193eee86` adds `tests/test_conceptweave_review_repair_target.py`; protected source contains neither the caller target nor mirror entry, so the contract is unsatisfied before enrollment.
- Mirror repair: `a84da81b6a7e822923f3414379db9072a4c41fde`.
- Consolidated caller repair: `18109ca0b84a554caafe1e72f18cf52e74a0c3cf`, minimized by ordinary-forward successor `796adc4393b6e83553ad330afc38e52a3b1544dd`.
- Existing consolidated-caller contract is extended on the same branch so schedule resolution and the dispatch-target mirror remain one acceptance surface.

No product-local `conceptweave-hourly-review-repair.yml` is introduced. No provider/model/group override, paid fallback, workflow-token write grant, approval, merge, release, protection mutation, or source-neutral wake is added.

## Acceptance and rollout boundary

Source acceptance requires the focused caller contracts and repository workflow validation to pass on the exact PR head. Runtime acceptance additionally requires all of the following after protected integration:

1. `OPENCODE_REPOSITORY_DISPATCH_TARGETS` in `ContextualWisdomLab/.github` contains the exact `ContextualWisdomLab/ConceptWeave` entry and is re-read after mutation.
2. An unchanged-head ConceptWeave canary with an autofixable file-scoped review finding produces a central `PR Review Autofix ContextualWisdomLab/ConceptWeave#...@<sha>` worker.
3. The worker revalidates the live PR/head/base before model work and before publication, writes only sealed reviewed paths, and ordinary-forwards the same head branch.
4. A stale-head canary fails closed before publication. Queued, cancelled, or failed checks are never normalized into success.
5. ConceptWeave contains no duplicate local review-repair workflow.

Until those conditions are observed, enrollment is Proposed rather than operationally Accepted. Source GREEN cannot substitute for the live repository-variable update or canary evidence.

## Rollback

If the central caller causes target-specific admission or isolation regressions, remove only the ConceptWeave matrix entry and mirror entry, restore the previous exact target set, and leave the product repository unchanged. Do not replace the rollback with a local writer. If the live allowlist variable was updated, remove the same exact ConceptWeave entry there in the same rollback and re-read the variable before declaring rollback complete.
1 change: 1 addition & 0 deletions scripts/ci/opencode_repository_dispatch_targets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"$comment": "Mirrors the live ContextualWisdomLab/.github repository variable OPENCODE_REPOSITORY_DISPATCH_TARGETS, which gates ALLOWED_TARGET_REPOSITORIES in pr-review-merge-scheduler.yml/pr-review-fix-scheduler.yml and the agent-mention dispatch allowlist. There is no API to commit an org/repo variable's value to source control, so this file is a hand-maintained mirror -- update it AND run `gh variable set OPENCODE_REPOSITORY_DISPATCH_TARGETS --repo ContextualWisdomLab/.github` in the same PR whenever a repository is added. tests/test_hourly_review_repair_callers.py::test_every_hourly_caller_target_is_in_the_dispatch_targets_mirror locks every repository hourly-review-repair.yml dispatches to as a subset of this list -- see docs/doctoring/scheduler-target-list-drift-20260902.md for the incident history (governance-risk-compliance, nonnest2, quarantine-sandbox-runtime all silently failed their hourly heartbeat because this sync was missed) that this file and test exist to catch before it recurs.",
"targets": [
"ContextualWisdomLab/.github",
"ContextualWisdomLab/ConceptWeave",
"ContextualWisdomLab/ContextualWisdomLab.github.io",
"ContextualWisdomLab/DiagramWeave",
"ContextualWisdomLab/EgressWeave",
Expand Down
32 changes: 32 additions & 0 deletions tests/test_conceptweave_review_repair_target.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Coverage contract for ConceptWeave's canonical bounded review-repair target."""

from __future__ import annotations

import json
import re
from pathlib import Path


_CALLER = Path(".github/workflows/hourly-review-repair.yml")
_DISPATCH_TARGETS_MIRROR = Path("scripts/ci/opencode_repository_dispatch_targets.json")
_TARGET = "ContextualWisdomLab/ConceptWeave"


def test_conceptweave_has_exactly_one_canonical_review_repair_target() -> None:
"""ConceptWeave resolves once through the central caller and dispatch allowlist mirror."""
caller = _CALLER.read_text(encoding="utf-8")
matches = re.findall(
r'\{"name":"conceptweave","target_repository":"ContextualWisdomLab/ConceptWeave",'
r'"base_branch":"main","retry_hours":"2",'
r'"concurrency_group":"conceptweave-hourly-review-repair"\}',
caller,
)
assert len(matches) == 1

mirror = json.loads(_DISPATCH_TARGETS_MIRROR.read_text(encoding="utf-8"))
assert mirror["targets"].count(_TARGET) == 1


def test_conceptweave_target_uses_shared_caller_without_a_duplicate_workflow() -> None:
"""Enrollment stays in the consolidated central caller rather than a new thin workflow."""
assert not Path(".github/workflows/conceptweave-hourly-review-repair.yml").exists()
7 changes: 7 additions & 0 deletions tests/test_hourly_review_repair_callers.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@
"retry_hours": "2",
"concurrency_group": "semantic-data-portal-hourly-review-repair",
},
{
"name": "conceptweave",
"target_repository": "ContextualWisdomLab/ConceptWeave",
"base_branch": "main",
"retry_hours": "2",
"concurrency_group": "conceptweave-hourly-review-repair",
},
],
}

Expand Down
Loading