Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fb2c244
test(governance): pin canonical LLM owner guidance RED
seonghobae Sep 3, 2026
45f115d
chore(governance): run bounded guidance source repair
seonghobae Sep 3, 2026
dae59c4
ci(governance): remove stalled temporary guidance repair workflow
seonghobae Sep 3, 2026
853f7a6
docs(governance): align Claude LLM authority boundary
seonghobae Sep 3, 2026
75e6c09
docs(governance): preserve frontend guidance wording
seonghobae Sep 3, 2026
6ca9879
docs(governance): align agent LLM authority boundary
seonghobae Sep 3, 2026
a2b0a31
docs(governance): restore complete AGENTS guidance after bounded edit
seonghobae Sep 3, 2026
a8c3503
docs(governance): codify canonical model owner boundary
seonghobae Sep 4, 2026
38b1443
docs(agents): codify protected PR repair workflow
seonghobae Sep 4, 2026
9f890a3
docs(agents): separate merge readiness evidence
seonghobae Sep 4, 2026
5ff0f21
docs(agents): inherit lifecycle safeguards
seonghobae Sep 4, 2026
d1a0cbd
test(governance): require OpenCode orchestrator boundary
seonghobae Sep 4, 2026
c249658
fix(governance): route OpenCode through orchestrator free
seonghobae Sep 4, 2026
b0ffdf7
chore(stack): adopt updated LLM governance foundation
seonghobae Sep 4, 2026
f907468
chore(stack): restore isolated lifecycle predecessor tree
seonghobae Sep 4, 2026
9e941d7
docs(agents): codify actions capacity operations
seonghobae Sep 4, 2026
8d6257c
docs(agents): remove direct provider guidance
seonghobae Sep 4, 2026
c261dcc
docs(agents): reconcile lifecycle review boundaries
seonghobae Sep 4, 2026
b9ee877
fix(governance): align lifecycle evidence and gateway routing
seonghobae Sep 4, 2026
4bd97cd
fix(governance): document OpenCode gateway contract
seonghobae Sep 4, 2026
24a2a46
fix(governance): pin OpenCode gateway origin
seonghobae Sep 4, 2026
615be45
fix(governance): contain OpenCode gateway credentials
seonghobae Sep 5, 2026
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
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
DEBUG=false
ENABLE_PROMETHEUS_METRICS=false

# OpenCode contributor tooling only; Naruon does not read these at runtime.
# OpenCode sends this token only to the fixed loopback contextual-orchestrator
# endpoint in opencode.jsonc. Never place upstream provider keys here.
CONTEXTUAL_ORCHESTRATOR_TOKEN=
Comment on lines +9 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep the gateway token out of MCP subprocess environments

When a contributor supplies this variable so the {env:CONTEXTUAL_ORCHESTRATOR_TOKEN} interpolation works, the token is part of OpenCode's ambient process environment and is inherited by the local MCP child commands in opencode.jsonc (including three third-party npx packages); it is therefore not sent only to the fixed loopback endpoint as this comment claims. A compromised or diagnostic MCP can read and exfiltrate the owner-issued gateway bearer token, so load it through a provider-scoped credential mechanism or explicitly scrub it from every spawned tool/MCP environment.

AGENTS.md reference: AGENTS.md:L240-L243

Useful? React with 👍 / 👎.


# AI features. Leave blank to disable LLM/embedding-backed flows locally.
OPENAI_API_KEY=
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
Expand Down
184 changes: 132 additions & 52 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ in this repo.

### Code exploration

- This repo has no `.codegraph/` index, so use normal search (grep/find/ripgrep).
If a `.codegraph/` index is later added at the repo root, prefer CodeGraph
(`codegraph explore "<query>"`, or the code-review-graph MCP tools) before
grep/find when understanding or locating code — it surfaces callers, callees,
and impact that text search misses.
- When CodeGraph is available, check `codegraph status` before architecture or
symbol exploration. Initialize a missing index with `codegraph init`, repair a
stale or unhealthy index with `codegraph sync`, and use `codegraph explore`
before broad searches. Otherwise use focused `rg` and file reads. Keep graph
artifacts local unless repository policy requires them.

### Config & secrets (KV, not env)

Expand Down Expand Up @@ -136,51 +136,12 @@ in this repo.
`.github/workflows/opencode-review.yml`, `.github/workflows/strix.yml`,
`.github/workflows/strix-selftest.yml`, or
`.github/workflows/pr-review-merge-scheduler.yml`.
- The central Strix Security Scan uses GitHub Models by default through
`STRIX_GITHUB_MODELS_TOKEN`, `STRIX_LLM=openai/gpt-5`, and
`LLM_API_BASE_FILE` pointing at a trusted file containing
`https://models.github.ai/inference`; GitHub Models scans must try the
configured GPT-5-or-newer model first and may fall back to the explicit
workflow fallback list, currently
`github_models/deepseek/deepseek-r1-0528` and
`github_models/deepseek/deepseek-v3-0324`, when GitHub Models provider
capacity or model availability blocks the primary run. The Strix gate must
route these fallback names through the GitHub Models endpoint with
OpenAI-compatible child model names such as
`openai/deepseek/deepseek-r1-0528`, not the public DeepSeek API. Do not use
GPT-4.1 or weaker GitHub Models fallbacks for Strix or OpenCode PR review
evidence. Keep the GitHub Models endpoint in a trusted input file and pass
the token only through
the provider-scoped Strix child-process key path. Legacy `STRIX_LLM` secrets
must not override PR, push, or scheduled Strix defaults. Vertex remains
available only for manual
`workflow_dispatch` evidence when the `strix_llm` input
explicitly selects `vertex_ai/gemini-3.1-pro-preview-customtools` or
`vertex_ai/gemini-2.5-flash` with `GCP_SA_KEY`; expose Google/Vertex
credentials only for Vertex provider mode. Direct OpenAI GPT-5.4-or-newer
scans remain supported only for manual `strix_llm` selections with
`STRIX_OPENAI_API_KEY`. Do not silently fall back between providers, and
do not treat timeout-class provider infrastructure failures as clean PR
evidence even when Strix printed zero vulnerabilities before failing. Disable
silent Vertex fallback models in the workflow unless a future PR proves a new
exact fallback contract with no Timeout/Fatal/Warn/Denied output. Record
provider evidence in the PR. Known third-party Strix/Pydantic
serializer warnings must be filtered narrowly inside the Strix gate child
process, not as a visible workflow env entry, so Warn-class logs are not
accepted as clean evidence and warning-filter variable names do not pollute
GitHub logs. Strix workflow runtime budget keys should be exported inside the
execution shell, not listed as visible step `env:` timeout names, so clean runs
do not carry stale timeout-signal strings. Keep PR-scope process budgets large
enough for Strix to finalize reports after the scanner emits completion
events; a wrapper timeout after `vulnerability_count: 0` is still failed
evidence, not a pass. PR evidence must present the full scannable changed-file
set from the PR head, plus allowlisted trusted context files, to Strix in one
scanner invocation; do not split changed files into separate scanner runs or
copy the entire PR-head repository tree by default because either breaks
Strix's required whole-context and bounded-input contract. Keep architecture
docs and reusable Strix gate tests aligned with this rule so stale
Vertex-default, OpenAI-only, unavailable-model, blanket-warning, or generic-key
examples cannot re-enter copied workflow guidance.
- Central LLM review workflows use
`contextual-orchestrator/orchestrator/free`; do not restore direct GitHub
Models, Vertex, OpenAI, OpenRouter, or provider-specific fallback credentials.
Preserve whole-context Strix input, bounded job runtime, ZDR-only
private-source routing, and fail-closed `Timeout`/`Fatal`/`Warn`/`Denied`
artifact checks.
Comment thread
seonghobae marked this conversation as resolved.
- HMAC fallback sessions are local/control-plane compatibility credentials, not
authoritative workspace-membership evidence. Sensitive tenant security posture
surfaces must require OIDC/JWKS-backed membership or an explicit dependency
Expand All @@ -189,6 +150,120 @@ in this repo.

## PR automation and review defaults

### Agent PR lifecycle playbook

- When available, use `autoresearch` for an autonomous review-repair loop,
`babysit-pr` for protected-merge observation, and `git-commit-format` before
committing. If one is unavailable, perform the same steps directly: keep an
evidence log, poll current-head checks without treating pending work as a
failure, and use the repository's conventional commit history as the format
contract. Use CodeGraph before broad source searches when an index exists;
apply `humanize-korean` to Korean prose when that shared skill is available.
Prefer repository-local
`fix-development-mistakes`, `github-actions-privileged-pr-scan`, and
`github-robot-review-gate` skills for their matching repair, privileged
scanner, and review-gate work; read the selected `SKILL.md` completely.
- Apply the mutation loop only to implementation, remediation, and landing
tasks. Review-only agents stop after publishing evidence-backed findings and
must not edit, execute project code, push, approve, or merge.
- For every open PR, repeat: fetch the exact remote base and head, inspect
current-head reviews and unresolved threads, reproduce failed checks from
their logs, repair the canonical owner, run focused tests plus the applicable
contract/security suite, push without force, and re-fetch evidence. A new
head invalidates earlier reviews and checks.
Comment thread
seonghobae marked this conversation as resolved.
- Before creating a worktree or restacking a branch, compare `git ls-remote`
with the local remote-tracking ref and start from the verified 40-character
SHA. Never guess or manually extend abbreviated SHAs in commits, PR bodies,
release evidence, or gap baselines.
- Create a conventional commit with truthful agent attribution. Add a
cryptographic signature or `Signed-off-by` footer when repository rules or
contributor policy require it; verify that evidence before claiming the
commit satisfies that policy. Immediately before updating an existing remote
branch without force, fetch it and require its head to equal the reviewed
parent. For an initial push, first verify that the exact remote ref is absent,
then create it with a normal non-force push. Generated GitHub merge refs are
transport evidence, not authored commits; verify their parent and tree SHAs
rather than rewriting them.
- Treat concurrent commits and pushes as lineage to reconcile, not as grounds
for force-pushing. Merge the updated prerequisite into the same stacked
branch, preserve its complete delta, rerun focused checks, and retarget only
when the resulting dependency order is verified.
- Preserve unrelated dirty or untracked files. If a command changes the wrong
checkout, stop before editing or pushing, record the reflog evidence, restore
only the affected branch with a non-destructive detached-head and branch-ref
move, and verify the original checkout and untracked files afterward.
- Tests invoked with `--noconftest` must bootstrap every required setting in
the test or trusted workflow step. Use explicit test-only values and fresh
random secrets; do not weaken production validation or depend on a developer
shell's environment.
- Exact changed-line review evidence must be generated only from real
current-head added or modified lines. Do not invent line 1 for deleted-only,
binary, oversized, or otherwise ineligible files, and do not relax the
validator to accept a fabricated receipt; fail closed or repair the canonical
receipt producer.
- Do not present a heuristic as a security, AI-quality, or completion
guarantee. State its evidence boundary and replace it at the canonical owner
when the workflow requires an enforceable contract.
- Pending or queued reviews and checks are wait states. Continue safe work on
another gap. Before calling a PR merge-ready, freshly verify the exact head
and base, live rulesets, required checks, unresolved threads, and applicable
current-head CodeRabbit or structured OpenCode fallback evidence. After the
merge, verify the merge commit and protected target branch.
- Audit workflow triggers and concurrency as parsed YAML behavior, not by text
search. PR review and repair groups use
`<workflow>-<repository>-<PR number>` with `cancel-in-progress: true`, so a
new head cancels only the older run for the same workflow, repository, and
PR. Metadata-only PR Governance is the deliberate exception: it serializes
the same PR's state publication with `cancel-in-progress: false`. Release,
deployment, migration, and provenance jobs also remain serialized and are not
canceled by review concurrency.
- Prefer central required or reusable workflows over repository-local copies.
Remove duplicate scanners, arbitrary sleeps, runner-held polling, and
per-PR organization queue sweeps once a current-head dispatcher or central
control-plane workflow owns that job. On `converted_to_draft`, `closed`, or
an obsolete head, revalidate the live PR state before canceling queued or
running review work; `ready_for_review` must start fresh current-head work.
- A queued workflow record is not proof of an occupied runner. Inspect jobs and
preserve current-head release, deployment, image, migration, SBOM,
provenance, and security evidence. Do not use administrative merge bypass.
The only permitted temporary required-context adjustment is the documented
stale-context procedure in `docs/development/merge-gate-policy.md`: capture
equivalent current-head evidence, make a reversible ruleset change, restore
the context after protected-branch repair, and rerun its evidence. It does not
authorize suppressing a product or security finding.
- Model-backed OpenCode, Strix, and Noema workflows request only
`contextual-orchestrator/orchestrator/free` with the gateway credential.
Provider discovery, capability routing, and fallback belong to the
orchestrator; consumer workflows do not carry provider names, direct-provider
credentials, or paid fallbacks. Verify the requested logical model, endpoint,
Comment thread
seonghobae marked this conversation as resolved.
served-model metadata, and terminal response in the same run.
- Keep private-source review fail closed and ZDR-only. Never log or copy bearer
tokens, provider credentials, request payloads, or secret-derived values.
Repair shared sidecar startup, credential bootstrap, timeout handling, and
response normalization where all review paths converge.
- Do not impose a shared application, agent, or gateway wall-clock timeout on
model work. The default is unset; only explicit user cancellation, a provider
terminal result, or a configured administrator limit ends it. OpenCode,
Strix, and Noema jobs must permit at least two hours, but that job budget is
not a model timeout and does not create a three-hour maximum.
- On GitHub 401, 403, rate limit, or repeatedly truncated responses, fail closed
instead of inferring current state. Use bounded retry and archive validation,
then continue only work grounded in already fetched exact SHAs until access is
restored.
- Do not close a PR merely to reach zero open PRs. Close only with explicit user
direction, no valid delta, a malicious change, or a verified successor that
carries the predecessor's complete delta and records the lineage.

Evidence basis: Souppaya, M., Scarfone, K., & Dodson, D. (2022). *Secure
Software Development Framework (SSDF) Version 1.1: Recommendations for
Mitigating the Risk of Software Vulnerabilities* (NIST SP 800-218). National
Institute of Standards and Technology. https://doi.org/10.6028/NIST.SP.800-218.
SSDF PS.1 and PS.3 ground accountable protected changes and retained integrity
and provenance evidence without prescribing repository-specific tooling. The
redistributable NIST publication is retained at
`docs/papers/nist-sp-800-218.pdf`; NIST states that SP 800 publications are not
subject to U.S. copyright, while attribution remains required.

- Follow `docs/development/merge-gate-policy.md` for PR gate interpretation.
- PR Governance must stay metadata-only: no PR-head checkout, no admin merge, no
review dismissal, and no security-check suppression.
Expand Down Expand Up @@ -707,14 +782,19 @@ in this repo.

## Phase 10 development rules

- **Stepwise execution**: Each phase requires an atomic PR, GitHub PR Tracking, Push, and Robot Review. A phase only ends when merged. Do not proceed without merge.
- **Stepwise execution**: Each phase requires an atomic PR, GitHub PR Tracking,
Push, and Robot Review. A phase ends only when its PR is protected-merged or a
successor's exact tree, effective diff, tests, and lineage record independently
prove complete-delta succession. While it waits, continue independent work
that does not consume or contradict the pending delta.
- **TDD + DDD**: Practice TDD, micro TDD, nano TDD, Domain Driven Development, and Context Driven Development.
- **API Wiring**: Always work with API wiring completed.
- **Collaboration**: Respect other agents' concurrent work; do not overwrite or dismiss unfamiliar changes.
- **Subagent Delegation**: Actively delegate tasks to Subagents.
- **UI/Browser Testing**: Use a real browser for testing (do not rely on assumptions).
- **Strict Errors**: Treat `Timeout`, `Fatal`, `Warn`, and `Denied` outputs as hard failures.
- **Goal**: Actively manage tasks to ensure open PR counts converge to 0.
- **Goal**: Converge open PRs through protected merges or verified full-delta
succession, never by count-only closure.

- When the gate exhausts fallbacks after the primary model produces a finding at or above threshold and then fails with a retryable error (like `NOT_FOUND`), ensure the final output explicitly reports `Strix quick scan failed with a non-recoverable error.` to prevent downgrading the finding to pass or misleadingly reporting an unavailability error.

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ mail/calendar/file systems.
auto-merge, and mechanical merge actions run as the target repository's
`github-actions[bot]` through the central workflow. Pending CodeRabbit or
required-check evidence is a wait state, not a hard blocker.
- Local OpenCode contributor runs use contextual-orchestrator's fixed loopback
OpenAI-compatible endpoint at `http://127.0.0.1:8100/v1`. Set a short-lived
owner-issued `CONTEXTUAL_ORCHESTRATOR_TOKEN`; do not substitute an upstream
Comment on lines +53 to +55

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Document how to start the required loopback gateway

Fresh evidence beyond the earlier setup comment is that a repo-wide search of Docker Compose files, scripts, and documentation finds no service definition or bootstrap command that binds contextual-orchestrator to 127.0.0.1:8100; the README only supplies the address and says to obtain an owner-issued token. Consequently, a contributor following the checkout instructions still gets a connection failure after OpenCode switches exclusively to this provider unless they already know how to install and launch a separate repository. Add the exact install/start command or a link to an authoritative setup procedure for the required gateway.

AGENTS.md reference: AGENTS.md:L778-L781

Useful? React with 👍 / 👎.

provider key. OpenCode sends it as the standard `Authorization` header, which
the Fetch transport removes on a cross-origin redirect. This value configures
OpenCode only, not Naruon.
- Topic intelligence is not currently a live Naruon capability. The lexical
`keyword_extractor` is metadata only; Naruon fails closed rather than present
keyword, embedding, or LLM labels as Structural Topic Modeling. The product,
Expand Down
34 changes: 34 additions & 0 deletions backend/tests/test_release_governance.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,40 @@ def read_repo_text(relative_path: str) -> str:
return path.read_text(encoding="utf-8")


def test_agent_lifecycle_governance_artifacts_stay_aligned() -> None:
"""Keep lifecycle policy, model routing, and research evidence consistent."""
guidance = read_repo_text("AGENTS.md")
opencode_config = read_repo_text("opencode.jsonc")
environment_example = read_repo_text(".env.example")
readme = read_repo_text("README.md")
research_artifact = REPO_ROOT / "docs/papers/nist-sp-800-218.pdf"

assert '"model": "contextual-orchestrator/orchestrator/free"' in opencode_config
assert '"enabled_providers": ["contextual-orchestrator"]' in opencode_config
assert '"baseURL": "http://127.0.0.1:8100/v1"' in opencode_config
assert (
'"Authorization": "Bearer {env:CONTEXTUAL_ORCHESTRATOR_TOKEN}"'
in opencode_config
)
assert '"apiKey"' not in opencode_config
assert "CONTEXTUAL_ORCHESTRATOR_BASE_URL" not in opencode_config
assert opencode_config.count('"timeout": false') == 1
assert "STRIX_GITHUB_MODELS_TOKEN" not in opencode_config
assert "CONTEXTUAL_ORCHESTRATOR_BASE_URL" not in environment_example
assert "CONTEXTUAL_ORCHESTRATOR_BASE_URL" not in readme
assert "CONTEXTUAL_ORCHESTRATOR_TOKEN=" in environment_example
assert "CONTEXTUAL_ORCHESTRATOR_TOKEN" in readme
assert "http://127.0.0.1:8100/v1" in readme
assert "short-lived" in readme
assert "owner-issued" in readme
assert "docs/development/merge-gate-policy.md" in guidance
assert "prove complete-delta succession" in guidance
Comment thread
coderabbitai[bot] marked this conversation as resolved.
assert "Do not use administrative merge bypass" in guidance
assert "stale-context procedure" in guidance
assert "successor's exact tree, effective diff, tests, and lineage record" in guidance
assert research_artifact.read_bytes().startswith(b"%PDF-")


def assert_dockerfile_stage_from(dockerfile: str, image: str, stage_alias: str) -> None:
pattern = (
rf"^FROM {re.escape(image)}@sha256:[0-9a-f]{{64}} AS {re.escape(stage_alias)}$"
Expand Down
Binary file added docs/papers/nist-sp-800-218.pdf
Binary file not shown.
43 changes: 16 additions & 27 deletions opencode.jsonc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "https://opencode.ai/config.json",
"model": "github-models/openai/gpt-5",
"small_model": "github-models/deepseek/deepseek-v3-0324",
"enabled_providers": ["github-models"],
"model": "contextual-orchestrator/orchestrator/free",
"small_model": "contextual-orchestrator/orchestrator/free",
"enabled_providers": ["contextual-orchestrator"],
"mcp": {
"codegraph": {
"type": "local",
Expand Down Expand Up @@ -37,38 +37,27 @@
}
},
"provider": {
"github-models": {
"contextual-orchestrator": {
"npm": "@ai-sdk/openai-compatible",
"name": "GitHub Models",
"name": "Contextual Orchestrator",
"options": {
"baseURL": "https://models.github.ai/inference",
"apiKey": "{env:STRIX_GITHUB_MODELS_TOKEN}"
"baseURL": "http://127.0.0.1:8100/v1",
"headers": {
"Authorization": "Bearer {env:CONTEXTUAL_ORCHESTRATOR_TOKEN}"
},
"timeout": false
},
"models": {
"openai/gpt-5": {
"name": "OpenAI GPT-5",
"orchestrator/free": {
"name": "Orchestrator Free",
"tool_call": true,
"reasoning": true,
"options": {
"reasoningEffort": "high"
},
"limit": {
"context": 200000,
"output": 100000
}
},
"deepseek/deepseek-r1-0528": {
"name": "DeepSeek R1 0528",
"tool_call": true,
"reasoning": true,
"limit": {
"context": 128000,
"output": 4096
}
},
"deepseek/deepseek-v3-0324": {
"name": "DeepSeek V3 0324",
"tool_call": true,
"limit": {
"context": 128000,
"output": 4096
"output": 32768
}
}
}
Expand Down
Loading