Agents: read the master context FIRST. Before any work, read
docs/CWL-MASTER-CONTEXT.md(mission · naruon-as-platform + inter-component UML · cross-cutting disciplines · conventions · roadmap · current state), the live GitHub Project #1 https://github.com/orgs/ContextualWisdomLab/projects/1 (work/roadmap source of truth), the full spec ContextualWisdomLab/naruon#974, the live gap snapshotdocs/product-technical-gap-baseline.md(not merge authorization; Figma File ID for this repo is N/A perdocs/adr/0002-product-technical-gap-baseline.md), and operate the Project perdocs/agent-github-project-protocol.md. The repo/Project — not any private agent memory — is the source of truth. The standing autonomous operating directive for the continuous PR review→fix→merge→develop loop across the ecosystem isdocs/product-goal-directive.md— a/goalsession's 4000-character pointer refers to it; read the full directive before running or configuring any such loop.
Materialize accepts only exact SHA-256 pins, a bounded relative -r include
(no ./..), or an organization-owned HTTPS Git source pinned to a full
commit and exposed without running build hooks; a lone --require-hashes
directive is not trust evidence. See
docs/doctoring/opencode-exact-vcs-dependency-evidence.md.
Conflict-scope roots fail closed when the immediate parent directory is a symbolic link.
All 18 product hourly review-repair callers (OriginWeave at minute 10, nonnest2 at minute 16, and 16 others) are one file, .github/workflows/hourly-review-repair.yml, a github.event.schedule lookup table rather than 18 near-copy-pasted files. See docs/doctoring/hourly-review-repair-single-file-consolidation.md; the per-repository doctoring records (e.g. docs/doctoring/originweave-hourly-review-caller.md, docs/doctoring/nonnest2-hourly-review-caller.md) remain as historical background per repository.
Organization edge runtimes use Cloudflare Pingora. Do not add or preserve active Nginx containers, packages, commands, service/config files, or Kubernetes Nginx ingress annotations/classes. Read docs/policies/PINGORA_EDGE_POLICY.md and ADR-0019 before changing HTTP edge, static-serving, ingress, TLS, or proxy deployment behavior.
Semgrep hosted scans bind one job-level SEMGREP_IMAGE digest for log evidence, manifest inspection, and docker run. See docs/doctoring/semgrep-image-digest-single-source.md.
OpenCode may repair only trusted path:line bindings on LLM probes that already carry an independent proof and source-line digest. See docs/doctoring/opencode-llm-review-publication.md.
Central review routes through the vendored contextual-orchestrator gateway
sidecar (scripts/ci/contextual_orchestrator_review_sidecar.sh). The five
provider secrets (BYTEZ_API_KEY, NVIDIA_NIM_API_KEY,
NVIDIA_NIM_API_KEY_SUB, OPENROUTER_API_KEY, OPENAI_API_KEY) enter its KV
as bootstrap transport in the same process that discovers models and serves;
OpenCode, Noema, and Strix all use the fail-closed zero-cost pool
orchestrator/free. Strix was switched onto orchestrator/free on
2026-08-30, superseding the prior orchestrator/auto (provider-diverse,
non-free-admitting) default; private targets still require ZDR-compliant
routes under scripts/ci/zdr_policy.py. That
switch was made by an autonomous agent session, not per any owner decision —
see docs/adr/0003-contextual-orchestrator-vendored-free-zdr.md's
2026-08-30 amendment and its 2026-08-31 correction, which retracts an earlier
false claim of explicit owner direction and records the resulting
availability risk as open and unreviewed, not accepted.
Sidecar diagnostics may retain only a server-generated request_id matching
exactly 32 lowercase hexadecimal characters, plus the producer's explicit -
or <omitted> marker where that event contract permits it. Keep free-form
provider errors omitted; malformed, uppercase, short, long, or otherwise
unbounded identifiers must not pass the sanitizer.
HTTP success summaries are narrower still: preserve correlation only for the
review sidecar's fixed health, chat-completions, and responses paths. Never
allowlist arbitrary request paths merely because the producer stripped queries.
The materialization contract is also covered by docs/doctoring/exact-artifact-sbom-attestation.md.
- Use
github-actions-privileged-pr-scanwhen a PR scanner can reach secrets, and usegithub-robot-review-gateplusbabysit-prwhen diagnosing or monitoring a protected PR. If a named skill is unavailable, preserve its fail-closed trust boundary and exact-current-head evidence rules manually. - PR-triggered workflow concurrency must be trigger-aware. Group by workflow,
target repository, and pull request number with
cancel-in-progress: true; do not include the head SHA, because that prevents a new head from cancelling its predecessor. Non-PR triggers need an explicit collision-safe fallback. - Put concurrency at workflow scope when queued jobs must be coalesced before a runner is admitted. Job-level concurrency cannot relieve a saturated runner queue because it is evaluated only after job admission.
- Keep cleanup repository-local and event-driven. Do not restore an
organization-wide queue sweep, polling
sleep, or another scheduled scan to compensate for incorrect concurrency. Cancel only runs proven to belong to a superseded head of the same PR, then verify each accepted cancellation reachescompleted/cancelled. - Classify a run's PR head by event-specific evidence before cancellation.
pull_requestmay use the run's top-levelhead_sha, butpull_request_targetrecords the trusted base there; use its PR association and immutable run name/event payload instead. Arepository_dispatchrun also executes on the control-plane branch, so bind it to the validated target repository, PR number, and target-head SHA from its payload or run name. Never compare either event's top-levelhead_shadirectly with the live PR head. If a current-head dispatch is cancelled while deduplicating, enqueue exactly one replacement for that PR and workflow and verify the replacement carries the same live target head. - Before every review, retry, push, or merge claim, re-fetch the PR's exact head SHA, base SHA, review threads, required checks, and ruleset result. A push invalidates earlier checks and reviews. Never self-approve, dismiss reviews, force-push, disable a security gate, or use admin bypass for product or security changes.
- producer가 안전한 로그 필드를 추가하면 exact revision 쌍으로 consumer sanitizer를 통과시켜 allowlist의 누락을 확인한다. producer 단위 테스트 성공만으로 CI artifact 보존을 주장하지 않으며, 연결 검증에서도 raw 본문 비출력을 유지한다.
Many agent sessions work this organization concurrently under the same standing brief. Silence is not evidence: "I have not touched X" describes one session's history, never the organization's actual state.
- Before calling an item "not started" or a dependency "not adopted", check
beyond your own session. Search organization-wide (
gh search prs --owner ContextualWisdomLab "<keyword>"— note it returns 30 results by default, so it is a lead, not an exhaustive sweep), check whether a dedicated repository already owns the responsibility, then clone the target repository and read the real integration surface: compose files, the module that would consume the dependency, its docstrings and comments. A PR-title survey cannot see infrastructure already deployed with no PR trail, nor a deliberate non-adoption decision recorded only in a code comment. Both failures are documented indocs/doctoring/egressweave-wardnet-adoption-audit-contextual-orchestrator-20260903.md. - A negative capability claim — "library X cannot do Y" — needs X's own source, not its README. Clone the library and read its policy/configuration code and its test suite, which often carries the clearest worked example of the edge case in question. A feature-list summary is not sufficient evidence for a negative claim, least of all when that claim becomes a "do not adopt" recommendation other agents will treat as settled. The record above is an instance: a documented, tested configuration override was missed by reading only the README.
- A peer restating a claim is not corroboration of it. If two sessions both rely on the same summary, that is one check, not two. Independent verification means each examines the primary evidence — the code, the API response, the log — from a different vantage point.
- Prefer a different model family for adversarial review of your own
conclusions. Sessions here share a model and tend to share blind spots. A
read-only
codex exec -s read-only -C <dir> "<prompt>"pass has already caught a factual error in this very section that same-family review missed.
docs/org-required-workflow-rollout.md allows retiring a PR "only after verified
complete successor carryover of every unique valid delta; redundancy alone is not
a close instruction." Verify that carryover against the tree, not against how
convincing the closing comment reads. These commands narrow it down; none of
them alone proves succession.
- Read what the branch actually contributes with a three-dot diff:
git diff --stat origin/main...<head>. Two-dot (origin/main <head>) also reports changesmaingained that the branch lacks, which on a stale PR reads as large phantom deletions by the PR. A long-lived branch's title records what it was opened for, so it is not evidence of current scope either. - Look for each claimed-inherited piece by content:
git grep -lF "<string>" origin/main --(use-F;git greptreats the pattern as a regex otherwise). No output means that exact string is absent frommain— strong evidence the delta is missing, but not proof, since a successor may have renamed or restructured the same behaviour. Conversely a match is not proof of inheritance: the same name can carry different behaviour. git show origin/main:<path>tells you whether the path exists onmainnow. A non-zero exit does not mean the content never landed — it may have landed and later been deleted — and success does not mean the successor kept the predecessor's changes to it.- Ancestry is the wrong tool here.
git merge-base --is-ancestor <commit> mainanswers "was this commit object merged", not "is this content onmain". This repository mixes squash merges with real merge commits, so a squash-carried delta reports false while a later-reverted one still reports true. - When the delta is provably absent and no successor accounts for it, reopen
(
gh api repos/<owner>/<repo>/pulls/<n> -X PATCH -f state=open) and comment the commands and their output. Missing evidence is not the same as disproven succession: if the check is merely inconclusive, say so and ask, rather than reopening or letting the closure stand unexamined.
- When a large PR is narrowed into successors, verify the union of those
successors against the original's full diff — not merely that each successor's
own tests pass.
#1871was closed in favor of#1877plus#1879; both successors were green, but neither carried#1871's coverage/docstring delta, so the required 100% gate stayed broken onmainuntil#1883recovered it. "Each piece works" and "the pieces together still cover the original's scope" are different questions, and only the second one needs a diff against the original. - Use the per-delta commands in "Verifying a 'superseded — closing' claim" above against each successor, then ask the question those commands cannot: does anything in the original's scope survive in none of them? A split fails differently from a single bad closure — no individual successor looks wrong.
- A closure or narrowing is not self-verifying, and neither is a note recording
it. Git-level checks show whether the text moved; they do not show whether the
behaviour is restored. Finish by re-running the gate the original PR existed to
fix and confirming it passes on
mainitself from a fresh clone. - Never endorse a timeout, retry budget, or other numeric constant on a
model-invocation path without first reading
docs/product-goal-directive.mdsection 8, which states that central OpenCode, Strix, and Noema accept taking more than two hours per model ("중앙 OpenCode, Strix, Noema는 모델당 두 시간 이상 걸릴 수 있음을 수용한다") and that speed is not a core consideration, accuracy is ("속도는 핵심 고려사항이 아니며 정확성을 우선한다").#1889,#1890, and#1892each capped a model step at 900 seconds on real evidence of a multi-hour hang, and all three were reverted (#1891,#1895). Compelling hang evidence does not exempt a change from that contract: runner occupancy is repaired at the admission/continuation boundary or by an explicit provider terminal signal, never by converting elapsed inference time into a model-failure verdict. - Verify a citation before you rely on it, including your own. The first draft of
the bullet above cited a section number that does not exist in that file and
attributed a "timeout defaults to null" sentence to it that appears only in
#1891's PR body — both caught by grepping the file instead of trusting the summary that introduced them.
- A red
tests, coverage, orinterrogategate on your pull request is not proof that your diff caused it. Full-suite execution on a push tomainis not guaranteed: the workflows that runpytest testson push arepaths:-filtered, so a pairing broken outside their declared paths reachesmainwith no full-suite run. The breakage then surfaces on the next pull request whose review dispatch does run the suite, and fails it regardless of that request's own diff. This procedure covers the suite gates only; a red Semgrep, CodeQL, Strix, or Scorecard check is a different diagnosis. - Reproduce a suspect failure on a clean baseline before repairing it. Run
git worktree add /tmp/baseline <the PR's base ref> --detach, thencd /tmp/baselineand runpython3 -m pytest tests -q; that takes roughly four minutes and needs no virtualenv. You mustcdinto the worktree: over thirty test files read repository files through working-directory-relative paths such asPath(".github/workflows/..."), so pointing pytest at the baseline directory from your own checkout silently tests your tree and reports a green baseline that proves nothing. Baseline the pull request's actual base or merge-base rather thanorigin/mainoncemainhas moved past it. If the failure reproduces on the baseline it is pre-existing: repair it as its own pull request and name the change that introduced it. - When you change a workflow file or a
scripts/ci/module, grep the wholetests/tree for every literal you touched — event-type strings, cron expressions, environment-variable names, tuple members, pinned digests — not only the obviously named sibling test. A change can satisfy one oracle and still leave a second, independent one stale. - Read a stale pull request's own changes with a three-dot diff —
git diff <base>...<head>— or withgh pr diff, which is already three-dot. A two-dotgit diff <base> <head>renders everything the base gained since the fork point as though this branch deleted it, so an untouched branch reads as a mass revert. - Content-hash pins exist under
tests/; find them before editing a workflow. Rungrep -rn 'hash-object' tests/— today that is thegit hash-objectpin of.github/workflows/opencode-review-dispatch.yml. Any byte change to a pinned file makes its constant stale and fails a required gate for every open pull request, reverts included, because a revert restores the original bytes while the pin stays on the reverted value. Recompute only withgit hash-object <path>, and only for a constant you have confirmed is a blob pin. Nearly every other forty-hex literal undertests/is something else — a pinned action SHA, a vendored-revision pin, a synthetic fixture head, or an assertion that a SHA appears in a document — and pointinghash-objectat any of those produces a wrong value that breaks what it replaces. A second contract re-derives the dispatch pin by regular expression from the first, so keep the assignment on one line and correct it in one place. - Production code under
scripts/ci/branches onGITHUB_ACTIONS, and pytest inherits that variable in CI, so a failure class exists that cannot reproduce locally. Before calling a scheduler change clean, run the affected tests both ways, includingGITHUB_ACTIONS=true python3 -m pytest <paths>.