-
Notifications
You must be signed in to change notification settings - Fork 0
Knowledge-as-CGS-substrate: grounding ledger, CGS metrics, insight sync, lint, Obsidian audit vault #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Knowledge-as-CGS-substrate: grounding ledger, CGS metrics, insight sync, lint, Obsidian audit vault #35
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
59f1e3a
deps: bump agent-core to the insight-collector rev
Svaag d9607c1
grounding: CGS metrics + per-concept grounding ledger core
Svaag 886d4b0
exports: grounding ledger in exports/sqlite + grounding lint
Svaag 2ce26f2
retrieval: flag-gated grounding tie-break
Svaag 9a8730b
insights: collector sync + metrics CLI, budgeted loop phase-2
Svaag 8bd85b2
ci: guarded auto-merge for nightly refresh PRs (off by default)
Svaag ed4fcb7
km: lint operation, Obsidian audit vault, auto-memory bridge
Svaag 4706127
ci: onboard the advisory PR-Agent review loop
Svaag 254045d
docs: document the IDQ / CGS / Learning Lift metrics end to end
Svaag 1600915
deps: pin agent-core to the v0.8.0 release tag
Svaag 7ff9865
review: close the six Codex findings on the grounding substrate
Svaag File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| name: auto-merge | ||
|
|
||
| # Graduated gate relaxation for the nightly knowledge refresh PRs: when the | ||
| # repo variable KNOWLEDGE_AUTO_MERGE is "on", bot PRs whose diff is confined to | ||
| # regenerable projections (okf/generated, okf/observed, exports, reports) and | ||
| # whose quality report does not regress are queued for auto-merge. The actual | ||
| # gate stays branch protection: `gh pr merge --auto` merges only after every | ||
| # required check (validate: ruff/mypy/pytest/validate/quality/export/eval/ | ||
| # ledger/lifecycle/scan-secrets) succeeds. Anything touching okf/curated, | ||
| # ledger/, src/, tests/, evals/, schema/, or .github/ never auto-merges — | ||
| # curated knowledge and the production insight stream stay human-reviewed. | ||
| # | ||
| # KNOWLEDGE_AUTO_MERGE: off (default) | dry_run (comment only) | on | ||
| # Runbook: network-operations/docs/runbooks/knowledge-auto-merge.md | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| auto-merge: | ||
| runs-on: ubuntu-latest | ||
| if: > | ||
| (vars.KNOWLEDGE_AUTO_MERGE == 'on' || vars.KNOWLEDGE_AUTO_MERGE == 'dry_run') && | ||
| (startsWith(github.event.pull_request.head.ref, 'bot/knowledge-loop') || | ||
| startsWith(github.event.pull_request.head.ref, 'bot/knowledge-refresh')) && | ||
| endsWith(github.event.pull_request.user.login, '[bot]') | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | ||
| MODE: ${{ vars.KNOWLEDGE_AUTO_MERGE }} | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ github.event.pull_request.head.sha }} | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Enforce regenerable-path confinement | ||
| run: | | ||
| set -euo pipefail | ||
| # Both sides of a rename must satisfy the allowlist: a refresh that | ||
| # renames okf/curated/... or ledger/... INTO an allowed path would | ||
| # otherwise delete human-reviewed content unreviewed. | ||
| gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" \ | ||
| --paginate --jq '.[] | .filename, (.previous_filename // empty)' > changed-files.txt | ||
| echo "Changed files:" | ||
| cat changed-files.txt | ||
| blocked=0 | ||
| while IFS= read -r path; do | ||
| case "$path" in | ||
| okf/generated/*|okf/observed/*|exports/*|reports/*) ;; | ||
| *) | ||
| echo "::error::'$path' is outside the auto-merge allowlist" | ||
| blocked=1 | ||
| ;; | ||
| esac | ||
| done < changed-files.txt | ||
| if [ "$blocked" -ne 0 ]; then | ||
| echo "Diff touches human-reviewed paths; leaving the PR for review." >> "$GITHUB_STEP_SUMMARY" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Enforce quality non-regression | ||
| run: | | ||
| set -euo pipefail | ||
| git show "${BASE_SHA}:reports/coverage.json" > base-coverage.json | ||
| python3 - <<'PY' | ||
| import json, sys | ||
|
|
||
| base = json.load(open("base-coverage.json")) | ||
| head = json.load(open("reports/coverage.json")) | ||
| failures = [] | ||
| if int(head.get("critical_count", 1)) != 0: | ||
| failures.append(f"head critical_count={head.get('critical_count')} (must be 0)") | ||
| if int(head.get("warning_count", 0)) > int(base.get("warning_count", 0)): | ||
| failures.append( | ||
| f"warnings regressed {base.get('warning_count')} -> {head.get('warning_count')}" | ||
| ) | ||
| floor = 0.8 * int(base.get("concept_count", 0)) | ||
| if int(head.get("concept_count", 0)) < floor: | ||
| failures.append( | ||
| f"concept_count {head.get('concept_count')} fell below 80% of base " | ||
| f"{base.get('concept_count')} (mass-deletion guard)" | ||
| ) | ||
| if failures: | ||
| for failure in failures: | ||
| print(f"::error::{failure}") | ||
| sys.exit(1) | ||
| print("quality non-regression ok") | ||
| PY | ||
|
|
||
| - name: Dry-run comment | ||
| if: env.MODE == 'dry_run' | ||
| run: | | ||
| gh pr comment "$PR_NUMBER" --body \ | ||
| "auto-merge dry-run: this PR satisfies the path-confinement and quality non-regression guards and **would auto-merge** once KNOWLEDGE_AUTO_MERGE=on (required checks still gate the merge)." | ||
|
|
||
| - name: Queue auto-merge behind required checks | ||
| if: env.MODE == 'on' | ||
| run: | | ||
| gh pr merge "$PR_NUMBER" --auto --squash | ||
| gh pr comment "$PR_NUMBER" --body \ | ||
| "auto-merge queued: path confinement + quality non-regression passed; GitHub merges automatically once all required checks succeed." | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| --- | ||
| name: pr-agent | ||
|
|
||
| # Advisory AI PR review (same loop as network-operations/noc-agent). Runs on | ||
| # the UNPRIVILEGED `hyrule-public-pr` runner only, with read + PR/issue-comment | ||
| # permissions and our own OpenRouter key. Never deploys, never writes code, | ||
| # never auto-merges. Config (model/fallback/instructions): .pr_agent.toml. | ||
| # Design: network-operations/docs/ci/pr-agent.md. | ||
| # | ||
| # Org prerequisites (one-time, done 2026-07-10): repo is in the public-pr | ||
| # runner group and in OPENROUTER_API_KEY's selected repositories. | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened, ready_for_review] | ||
| issue_comment: | ||
| types: [created] | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| issues: write | ||
|
|
||
| # Group by event name too: the push-triggered review posts comments, and each | ||
| # comment fires an issue_comment run that would otherwise share this group and | ||
| # cancel the in-flight check run ("higher priority waiting request", | ||
| # network-operations#408). Same-event storms still dedupe. | ||
| concurrency: | ||
| group: pr-agent-${{ github.event_name }}-${{ github.event.pull_request.number || github.event.issue.number }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| pr-agent: | ||
| # Public-fork policy: auto-review ONLY for same-repo (internal) PRs, and | ||
| # slash commands ONLY from trusted authors. This keeps OPENROUTER_API_KEY | ||
| # off untrusted fork PRs and stops anyone from burning the OpenRouter | ||
| # budget via /ask, /improve, etc. | ||
| if: > | ||
| (github.event_name == 'pull_request' && | ||
| github.event.pull_request.head.repo.full_name == github.repository) || | ||
| (github.event_name == 'issue_comment' && | ||
| github.event.issue.pull_request && | ||
| startsWith(github.event.comment.body, '/') && | ||
| contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) | ||
| runs-on: [self-hosted, linux, x64, hyrule-public-pr] | ||
| timeout-minutes: 12 | ||
| steps: | ||
| - name: PR-Agent | ||
| uses: The-PR-Agent/pr-agent@8e4d32e5497defd43c023a404f73560c62728961 # v0.39.0 | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| # PR-Agent reads the OpenRouter key from openrouter__key; litellm also | ||
| # honours OPENROUTER_API_KEY. Set both from the org secret. | ||
| OPENROUTER__KEY: ${{ secrets.OPENROUTER_API_KEY }} | ||
| OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} | ||
| # Model pin via dynaconf env (SECTION__KEY). .pr_agent.toml is only | ||
| # honoured from the DEFAULT branch (no checkout step in the action), | ||
| # so until this PR merges the toml is invisible and PR-Agent would | ||
| # fall back to its packaged gpt-5.5 default. Keep the env pin even | ||
| # after the toml lands (belt and braces; custom models require | ||
| # custom_model_max_tokens). | ||
| CONFIG__MODEL: openrouter/deepseek/deepseek-v4-flash | ||
| CONFIG__FALLBACK_MODELS: '["openrouter/minimax/minimax-m2.7"]' | ||
| CONFIG__CUSTOM_MODEL_MAX_TOKENS: "128000" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # PR-Agent (advisory) configuration for AS215932/knowledge. | ||
| # Replaces hosted Sourcery. Runs only on the unprivileged hyrule-public-pr | ||
| # runner with read/comment-only perms, on our OpenRouter key. | ||
| # Design: network-operations/docs/ci/pr-agent.md. | ||
|
|
||
| [config] | ||
| git_provider = "github" | ||
| # deepseek-v4-flash / minimax-m2.7 are custom models -> need custom_model_max_tokens. | ||
| model = "openrouter/deepseek/deepseek-v4-flash" | ||
| fallback_models = ["openrouter/minimax/minimax-m2.7"] | ||
| custom_model_max_tokens = 128000 | ||
| temperature = 0.2 | ||
| use_repo_settings_file = true | ||
| publish_output = true | ||
|
|
||
| [github_action_config] | ||
| auto_review = true | ||
| auto_describe = false | ||
| auto_improve = true | ||
|
|
||
| [pr_reviewer] | ||
| require_security_review = true | ||
| require_tests_review = true | ||
| require_score_review = true | ||
| require_estimate_effort_to_review = true | ||
| extra_instructions = """ | ||
| This is the AS215932 knowledge repo: the OKF bundle (okf/generated regenerable, | ||
| okf/curated human-reviewed institutional knowledge, okf/observed evidence-only), | ||
| deterministic exports, the learning/insight ledgers, and the read-only | ||
| Knowledge MCP. HIGHEST RISK is corpus integrity and determinism. Flag, with | ||
| specifics: | ||
| - nondeterminism in exports (wall-clock, unsorted iteration, uncommitted | ||
| inputs) — `export --check` and the loop's volatile-churn detection depend on | ||
| byte-stable regeneration; | ||
| - hand edits to okf/generated/** (regenerated over) or exports/** without the | ||
| matching source change; | ||
| - curated/ledger content lacking citations/source_refs, or authority/ | ||
| review_status escalation without review (A0-A5 tier integrity); | ||
| - sanitization violations: raw logs, secrets, packet captures, command output, | ||
| or live telemetry payloads entering ledger/insight rows (learning_ledger_v1 | ||
| forbidden keys/classes); | ||
| - policy evaluator (knowledge-policy.yml) or redaction weakening — | ||
| deny-by-default must hold; | ||
| - auto-merge workflow guard weakening (path allowlist, quality non-regression, | ||
| bot/branch checks); | ||
| - unpinned GitHub Actions, broad GITHUB_TOKEN permissions, added | ||
| pull_request_target, or pull_request jobs on privileged runner labels. | ||
| Do not restate the diff; surface risk, determinism breaks, missing tests. | ||
| """ | ||
|
|
||
| [pr_description] | ||
| publish_description_as_comment = true |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In
.github/workflows/auto-merge.yml, the non-regression gate compares the PR's checked-inreports/coverage.json. The requiredquality --checkonly marks reports stale whencritical_countorconcept_countdiffer (quality.py:211), so a bot refresh with a stale or incorrectwarning_countcan bypass this warning-regression guard while changing only allowlisted generated/report paths. Recompute coverage in this job, or makequality --checkvalidatewarning_count, before queuing auto-merge.Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7ff9865:
quality --checknow treats a differingwarning_countas stale reports (alongside critical_count/concept_count), so the required check itself guarantees the coverage.json the auto-merge gate compares is current — a bot refresh with a stale warning_count fails the required checks before the gate matters.