From 3c81a636031664a147bcf4985da187b702a0799c Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 03:51:04 -0700 Subject: [PATCH 1/7] chore(agentops): onboard policy federation artifacts Sync harness/task-domain policy onboarding artifacts into cliproxyapi++. Co-authored-by: Codex --- .github/scripts/security-guard.sh | 30 +++ .github/workflows/security-guard.yml | 25 ++ .pre-commit-config.yaml | 10 + AGENTS.md | 5 + CLAUDE.md | 5 + docs/agent-policy/effective-policy.json | 323 ++++++++++++++++++++++++ docs/agent-policy/sources.json | 10 + 7 files changed, 408 insertions(+) create mode 100755 .github/scripts/security-guard.sh create mode 100644 .github/workflows/security-guard.yml create mode 100644 docs/agent-policy/effective-policy.json create mode 100644 docs/agent-policy/sources.json diff --git a/.github/scripts/security-guard.sh b/.github/scripts/security-guard.sh new file mode 100755 index 0000000000..063b36d7ea --- /dev/null +++ b/.github/scripts/security-guard.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +if command -v ggshield >/dev/null 2>&1; then + GGSHIELD=(ggshield) +elif command -v uvx >/dev/null 2>&1; then + GGSHIELD=(uvx ggshield) +elif command -v uv >/dev/null 2>&1; then + GGSHIELD=(uv tool run ggshield) +else + echo "ERROR: ggshield not installed. Install with: pipx install ggshield or uv tool install ggshield" >&2 + exit 1 +fi + +echo "[security-guard] Running ggshield secret scan" +"${GGSHIELD[@]}" secret scan pre-commit + +if command -v codespell >/dev/null 2>&1; then + changed_files=$(git diff --cached --name-only --diff-filter=ACM || true) + if [ -z "${changed_files}" ]; then + changed_files=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || true) + fi + + if [ -n "${changed_files}" ]; then + echo "[security-guard] Running optional codespell fast pass" + echo "${changed_files}" | grep -E '\.(md|txt|py|ts|tsx|js|go|rs|kt|java|yaml|yml)$' | xargs -r codespell -q 2 -L "hte,teh" || true + fi +fi diff --git a/.github/workflows/security-guard.yml b/.github/workflows/security-guard.yml new file mode 100644 index 0000000000..7afa02e487 --- /dev/null +++ b/.github/workflows/security-guard.yml @@ -0,0 +1,25 @@ +name: Security Guard + +on: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: + - "**" + +permissions: + contents: read + +jobs: + guard: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run pre-commit guard checks + uses: pre-commit/action@v3.0.1 + with: + extra_args: --hook-stage pre-commit --config .pre-commit-config.yaml --show-diff-on-failure diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18ea0308ec..d1f1a27741 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,3 +13,13 @@ repos: language: system pass_filenames: false stages: [pre-push] + +# Local security and fast gate hooks for pre-commit and pre-push stages + - repo: local + hooks: + - id: security-guard-pre-commit-pre-push + name: security-guard pre-commit/pre-push + entry: .github/scripts/security-guard.sh + language: script + pass_filenames: false + stages: [pre-commit, pre-push] diff --git a/AGENTS.md b/AGENTS.md index dd4bcf6720..7491cfefd7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -108,3 +108,8 @@ kush/ ├── parpour/ # Spec-first planning └── pheno-sdk/ # Python SDK ``` + +## Child-Agent and Delegation Policy +- Use child agents liberally for scoped discovery, audits, multi-repo scans, and implementation planning before direct parent-agent edits. +- Prefer delegating high-context or high-churn tasks to subagents, and keep parent-agent changes focused on integration and finalization. +- Reserve parent-agent direct writes for the narrowest, final decision layer. diff --git a/CLAUDE.md b/CLAUDE.md index ba5ca54432..e42b1b6b7f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3599,3 +3599,8 @@ result = await workflow.execute({"source_url": "https://api.example.com/data"}) --- This guide should be updated as the project evolves and new patterns are established. + +## Child-Agent and Delegation Policy +- Use child agents liberally for scoped discovery, audits, multi-repo scans, and implementation planning before direct parent-agent edits. +- Prefer delegating high-context or high-churn tasks to subagents, and keep parent-agent changes focused on integration and finalization. +- Reserve parent-agent direct writes for the narrowest, final decision layer. diff --git a/docs/agent-policy/effective-policy.json b/docs/agent-policy/effective-policy.json new file mode 100644 index 0000000000..8ba252bffb --- /dev/null +++ b/docs/agent-policy/effective-policy.json @@ -0,0 +1,323 @@ +{ + "applied_layers": [ + { + "policy": { + "agent_governance": { + "ci": { + "dry_run_first": true, + "require_gates": true + }, + "consent_rules": { + "destructive_actions": "ask", + "network_access": "ask_on_unknown_hosts" + }, + "policy_files": { + "must_read": [ + "AGENTS.md", + "CLAUDE.md" + ], + "required_sections": [ + "security", + "testing", + "deployment", + "handoff" + ] + }, + "required_mode": "production_ready" + }, + "telemetry": { + "capture": true, + "retention_days": 90 + } + } + }, + { + "policy": { + "compliance": { + "sensitive_file_guard": [ + "secrets.yml", + "config/secrets.json", + ".env" + ] + }, + "security": { + "allow_branch_force_push": false, + "allow_destructive_commands": false, + "allow_root_writes": false, + "secret_scan": true + } + } + }, + { + "policy": { + "agent_governance": { + "auto_loop": true, + "default_prompt_depth": "full", + "handoff_note": "handoff_required_on: [tooling_change, governance_change]", + "research_first": true + }, + "ci": { + "require_gates": true, + "smoke_first": true + } + } + }, + { + "policy": { + "harness": { + "capabilities": { + "executor": "task", + "parallel_agents": "high" + }, + "name": "Factory-Droid", + "routing": { + "escalation_on": [ + "token_budget", + "policy_violation" + ], + "escalation_to": "human" + }, + "tool_contracts": { + "shell": { + "forbidden_default": [ + "git commit --amend", + "git push --force" + ], + "requires_signed_artifact": true + } + } + } + } + }, + { + "policy": { + "repo": { + "governance": { + "policy_federation": { + "enforced": true, + "required": true + } + }, + "policy_hints": { + "default_scope": "agentops", + "managed_by": "agent-devops-setups" + } + } + } + }, + { + "policy": { + "task_domain": { + "name": "devops", + "pipelines": { + "ci": { + "must_have_witness": true, + "required_gate_state": "pass" + }, + "release": { + "require_artifact_trace": true, + "require_changelog": false + } + } + } + } + }, + { + "policy": { + "extensions": { + "codex-gate": { + "agent_governance": { + "command_policy": { + "require_closure_check": true, + "required_readme_updates": true + }, + "handoff": { + "auto_summary": true + } + }, + "telemetry": { + "track_pipeline": true + } + } + } + } + }, + { + "policy": { + "extensions": { + "agentops-ci": { + "ci": { + "artifact_retention_days": 60, + "default_matrix_size": "small", + "required_checks": [ + "policy-gate", + "lint", + "test", + "types" + ] + }, + "policy": { + "audit_before_merge": true + } + } + } + } + } + ], + "audit": { + "files": [ + "system/base.json", + "system/security-guard.json", + "user/core-operator.json", + "harness/factory-droid.json", + "repo/default.json", + "task-domain/devops.json", + "extensions/manifests/codex-gate.json", + "extensions/manifests/agentops-ci.json" + ], + "generated_at": "2026-03-02T08:03:24.250589+00:00", + "policy_digest": "a41a9f5202906e7af00f298514375adee1bfb5646a074b9d7e5aae78d55ae2ad", + "policy_signature": "" + }, + "policy": { + "agent_governance": { + "auto_loop": true, + "ci": { + "dry_run_first": true, + "require_gates": true + }, + "consent_rules": { + "destructive_actions": "ask", + "network_access": "ask_on_unknown_hosts" + }, + "default_prompt_depth": "full", + "handoff_note": "handoff_required_on: [tooling_change, governance_change]", + "policy_files": { + "must_read": [ + "AGENTS.md", + "CLAUDE.md" + ], + "required_sections": [ + "security", + "testing", + "deployment", + "handoff" + ] + }, + "required_mode": "production_ready", + "research_first": true + }, + "ci": { + "require_gates": true, + "smoke_first": true + }, + "compliance": { + "sensitive_file_guard": [ + "secrets.yml", + "config/secrets.json", + ".env" + ] + }, + "extensions": { + "agentops-ci": { + "ci": { + "artifact_retention_days": 60, + "default_matrix_size": "small", + "required_checks": [ + "policy-gate", + "lint", + "test", + "types" + ] + }, + "policy": { + "audit_before_merge": true + } + }, + "codex-gate": { + "agent_governance": { + "command_policy": { + "require_closure_check": true, + "required_readme_updates": true + }, + "handoff": { + "auto_summary": true + } + }, + "telemetry": { + "track_pipeline": true + } + } + }, + "harness": { + "capabilities": { + "executor": "task", + "parallel_agents": "high" + }, + "name": "Factory-Droid", + "routing": { + "escalation_on": [ + "token_budget", + "policy_violation" + ], + "escalation_to": "human" + }, + "tool_contracts": { + "shell": { + "forbidden_default": [ + "git commit --amend", + "git push --force" + ], + "requires_signed_artifact": true + } + } + }, + "repo": { + "governance": { + "policy_federation": { + "enforced": true, + "required": true + } + }, + "policy_hints": { + "default_scope": "agentops", + "managed_by": "agent-devops-setups" + } + }, + "security": { + "allow_branch_force_push": false, + "allow_destructive_commands": false, + "allow_root_writes": false, + "secret_scan": true + }, + "task_domain": { + "name": "devops", + "pipelines": { + "ci": { + "must_have_witness": true, + "required_gate_state": "pass" + }, + "release": { + "require_artifact_trace": true, + "require_changelog": false + } + } + }, + "telemetry": { + "capture": true, + "retention_days": 90 + } + }, + "resolver_version": "agent-devops-setups/federation-v1", + "scope": { + "extensions": [ + "codex-gate", + "agentops-ci" + ], + "harness": "factory-droid", + "repo": "cliproxyapi++", + "system": "base,security-guard", + "task_domain": "devops", + "user": "core-operator" + } +} diff --git a/docs/agent-policy/sources.json b/docs/agent-policy/sources.json new file mode 100644 index 0000000000..c724fa978f --- /dev/null +++ b/docs/agent-policy/sources.json @@ -0,0 +1,10 @@ +[ + "system/base.json", + "system/security-guard.json", + "user/core-operator.json", + "harness/factory-droid.json", + "repo/default.json", + "task-domain/devops.json", + "extensions/manifests/codex-gate.json", + "extensions/manifests/agentops-ci.json" +] From 7abcc58e422d297bea1877d52ede342a785b1a84 Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 13:44:15 -0700 Subject: [PATCH 2/7] chore(agentops): refresh required check manifest for policy federation Co-authored-by: Codex --- .github/required-checks.txt | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/.github/required-checks.txt b/.github/required-checks.txt index c9cbf6eab7..a19906c362 100644 --- a/.github/required-checks.txt +++ b/.github/required-checks.txt @@ -1,16 +1,6 @@ # workflow_file|job_name -pr-test-build.yml|go-ci -pr-test-build.yml|quality-ci -pr-test-build.yml|quality-staged-check -pr-test-build.yml|fmt-check -pr-test-build.yml|golangci-lint -pr-test-build.yml|route-lifecycle -pr-test-build.yml|provider-smoke-matrix -pr-test-build.yml|provider-smoke-matrix-cheapest -pr-test-build.yml|test-smoke -pr-test-build.yml|pre-release-config-compat-smoke -pr-test-build.yml|distributed-critical-paths -pr-test-build.yml|changelog-scope-classifier -pr-test-build.yml|docs-build -pr-test-build.yml|ci-summary +pr-test-build.yml|build pr-path-guard.yml|ensure-no-translator-changes +required-check-names-guard.yml|verify-required-check-names +codeql.yml|Analyze (Go) +docs.yml|Build Docs From 24266c93b57ab04fac3e4a0519aedbb7e07fbb35 Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 16:07:42 -0700 Subject: [PATCH 3/7] ci: align translator guard check-name and remove local go replace Co-authored-by: Codex --- .github/workflows/pr-path-guard.yml | 1 + go.mod | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pr-path-guard.yml b/.github/workflows/pr-path-guard.yml index 37f8518d38..3722d87c7d 100644 --- a/.github/workflows/pr-path-guard.yml +++ b/.github/workflows/pr-path-guard.yml @@ -9,6 +9,7 @@ on: jobs: ensure-no-translator-changes: + name: ensure-no-translator-changes runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/go.mod b/go.mod index 2dcc93bab7..c7f27372c6 100644 --- a/go.mod +++ b/go.mod @@ -111,5 +111,3 @@ require ( modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect ) - -replace github.com/KooshaPari/phenotype-go-kit => ../../template-commons/phenotype-go-kit From e341f9370dc4c8a223ea57225528bc91aeef5263 Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 16:16:54 -0700 Subject: [PATCH 4/7] docs: simplify triage table cells for vitepress markdown parsing Co-authored-by: Codex --- docs/troubleshooting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 8b29b69424..1b61ca8541 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -218,8 +218,8 @@ If non-stream succeeds but stream chunks are delayed/batched: | Channel toggle works on non-stream only (`CPB-0787`) | stream bootstrap path misses toggle | compare stream vs non-stream same prompt | align bootstrap settings and re-run parity probe | | Antigravity stream returns stale chunks (`CPB-0788`) | request-scoped translator state leak | run two back-to-back stream requests | reset per-request stream state and verify isolation | | Sonnet 4.5 rollout confusion (`CPB-0789`, `CPB-0790`) | feature flag/metadata mismatch | `cliproxyctl doctor --json` + `/v1/models` metadata | align flag gating + static registry metadata | -| Gemini thinking stream parity gap (`CPB-0791`) | reasoning metadata normalization splits between CLI/translator and upstream, so the stream response drops `thinking` results or mismatches non-stream output | `curl -sS -X POST http://localhost:8317/v1/chat/completions -H "Authorization: Bearer demo-client-key" -H "Content-Type: application/json" -d '{"model":"gemini-2.5-pro","messages":[{"role":"user","content":"reasoning normalization probe"}],"reasoning":{"effort":"x-high"},"stream":false}' | jq '{model,usage,error}'` then `curl -N -X POST http://localhost:8317/v1/chat/completions -H "Authorization: Bearer demo-client-key" -H "Content-Type: application/json" -d '{"model":"gemini-2.5-pro","messages":[{"role":"user","content":"reasoning normalization probe"}],"reasoning":{"effort":"x-high"},"stream":true}'` | align translator normalization and telemetry so thinking metadata survives stream translation, re-run the reasoning probe, and confirm matching `usage` counts in stream/non-stream outputs | -| Gemini CLI/Antigravity prompt cache drift (`CPB-0792`, `CPB-0797`) | prompt cache keying or executor fallback lacks validation, letting round-robin slip to stale providers and emit unexpected usage totals | re-run the `gemini-2.5-pro` chat completion three times and repeat with `antigravity/claude-sonnet-4-5-thinking`, e.g. `curl -sS -X POST http://localhost:8317/v1/chat/completions -H "Authorization: Bearer demo-client-key" -H "Content-Type: application/json" -d '{"model":"","messages":[{"role":"user","content":"cache guard probe"}],"stream":false}' | jq '{model,usage,error}'` | reset prompt caches, enforce provider-specific cache keys/fallbacks, and alert when round-robin reroutes to unexpected providers | +| Gemini thinking stream parity gap (`CPB-0791`) | reasoning metadata normalization splits between CLI/translator and upstream, so stream responses can drop `thinking` results or mismatch non-stream output | Run dedicated stream and non-stream reasoning probes for `gemini-2.5-pro` and compare model, usage, and error fields. | Align translator normalization and telemetry so thinking metadata survives stream translation, then verify usage parity across stream/non-stream probes. | +| Gemini CLI/Antigravity prompt cache drift (`CPB-0792`, `CPB-0797`) | prompt cache keying or executor fallback lacks validation, letting round-robin slip to stale providers and emit unexpected usage totals | Repeat non-stream probes for `gemini-2.5-pro` and `antigravity/claude-sonnet-4-5-thinking` and compare usage/error output consistency. | Reset prompt caches, enforce provider-specific cache keys/fallbacks, and alert when round-robin reroutes to unexpected providers. | | Docker compose startup error (`CPB-0793`) | service boot failure before bind | `docker compose ps` + `/health` | inspect startup logs, fix bind/config, restart | | AI Studio auth status unclear (`CPB-0795`) | auth-file toggle not visible/used | `GET/PATCH /v0/management/auth-files` | enable target auth file and re-run provider login | | Setup/login callback breaks (`CPB-0798`, `CPB-0800`) | callback mode mismatch/manual callback unset | inspect `cliproxyctl setup/login --help` | use `--manual-callback` and verify one stable auth-dir | From e45f58054095254cd86cafc0bb15259e227b7c9e Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 16:23:43 -0700 Subject: [PATCH 5/7] fix(docs): remove missing CategorySwitcher registration Unblocks VitePress build by removing import/registration for a component not present on this branch. Co-authored-by: Codex --- docs/.vitepress/theme/index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index bcbfb693b6..6ede95810d 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,13 +1,9 @@ import DefaultTheme from 'vitepress/theme' import type { Theme } from 'vitepress' -import CategorySwitcher from './components/CategorySwitcher.vue' import './custom.css' const theme: Theme = { ...DefaultTheme, - enhanceApp({ app }) { - app.component('CategorySwitcher', CategorySwitcher) - }, Layout: DefaultTheme.Layout } From 0ec7856bb9d7fe6997c873aaaf3d925aa88fc1e5 Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 16:48:14 -0700 Subject: [PATCH 6/7] fix(docs): remove unresolved theme stylesheet import Drops custom.css import from VitePress theme index to unblock docs bundle resolution. Co-authored-by: Codex --- docs/.vitepress/theme/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 6ede95810d..7766dce0f1 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,6 +1,5 @@ import DefaultTheme from 'vitepress/theme' import type { Theme } from 'vitepress' -import './custom.css' const theme: Theme = { ...DefaultTheme, From 7c7a25ab2930fa4543f410078465196bf963c88f Mon Sep 17 00:00:00 2001 From: Koosha Paridehpour Date: Mon, 2 Mar 2026 16:56:28 -0700 Subject: [PATCH 7/7] fix(ci): deploy docs pages only on main Prevents Deploy Pages failures on feature/PR branch pushes while keeping docs build validation active. Co-authored-by: Codex --- .github/workflows/docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5b2d50e5cc..6b50b2bc57 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -49,6 +49,7 @@ jobs: deploy: name: Deploy Pages needs: build + if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: name: github-pages