Skip to content

[docs] - Resync the checker skills with their scripts, the hashed-lock install and the retrieval gate - #1643

Merged
cgfixit merged 2 commits into
mainfrom
claude/skills-checker-sync
Oct 13, 2026
Merged

cgfixit merged 2 commits into
mainfrom
claude/skills-checker-sync

Conversation

@cgfixit

@cgfixit cgfixit commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Proposed changes

Skill-catalog resync, part 2 of 3 (part 1 is #1642, the loop/persona skills; part 3 is #1645, the knowledge and session skills). This one covers the nine checker skills: invariant-guard, dep-guard, config-guard, dotenv-guard, doc-sync, index-doctor, injection-redteam, otel-hardening, verify-deps. Each SKILL.md was read end to end and every claim checked against its own script, config.yaml, graph.py, the workflows and CLAUDE.md §4/§8.

Three of the findings are in the scripts, not the prose, and are fixed here because they are small and each has a self-test that proves the fix:

  • invariant-guard/verify.sh mutation B tested nothing. It sed-severed grok_fallback -> audit_logger, an edge graph.py has not had since the answer nodes converged on guardrail_output, so the file was unchanged and the assertion grep -q "reach audit_logger" matched the checker's PASS line. It now severs guardrail_output -> audit_logger, asserts the sed applied, and matches a FAIL line. Verified: the mutation is detected (all four injected violations detected, exit 2).
  • dep-guard D8 did not scan nemo-guardrails.yml, which hardcodes the torch pin (torch-cpu-2.13.0, torch==2.13.0+cpu), and listed docs/SETUP.md, which does not exist (the file is docs/work/SETUP.md). Both corrected; D8 now reports 5 CI files agreeing with the pin.
  • Small comment/string fixes: check_config.py's PyYAML hint named the retired --ignore-installed PyYAML install; its docstring described a boot validator that only range-checks (it now hard-fails the timeout margin, inline credentials, the reranker block and more); check_dotenv.py and ENVLINE_SPEC.md listed eight secret suffixes while envline.py defers to utils/secret-policy.tsv (which adds DB_URL and exact names); check_env_drift.py's header omitted E7; doctor.py cited a "CyClaw-Sandbox P13" that does not exist.

Prose corrections, by skill:

  • invariant-guard: 47 → 46 assertions (the checker prints the count; the report block now says <n>/<n>); the I2 row no longer claims a target-set check for pre_action_hook_router that the script does not perform; the stale "min_score 0.028 ≈ top-3-4 rank, 0.5 routes every query to the user gate" bullet now states the real gate (min_semantic_score + rerank veto; min_score gates the keyword-only degrade, hybrid ceiling 2/60); docs/PROPOSED_SKILLS.md → docs/work/PROPOSED_SKILLS.md.
  • dep-guard: Step 3 pointed at pip install -r requirements.txt -c constraints.txt --ignore-installed PyYAML; CLAUDE.md §8 is the hashed locks/ install. The "torch-cpu extra" gotcha described a pyproject.toml extra that does not exist (torch is a base dependency, +cpu lives in constraints.txt). "dep-guard does not track coverage wiring" contradicted its own D10 row. The verify description enumerated 8 mutations; the script runs 22. "Medium–High tier" is not a tier CLAUDE.md §7 has.
  • config-guard: C0 (inline credentials) and verify mutation E were missing from the table; C2 was described as FAIL on a sub-30 s margin (it warns; boot hard-fails); the "stricter gate belongs in 0.05–0.08" advice exceeds the RRF ceiling; C13 now mentions the bind-time refusal in gate.py.
  • dotenv-guard: the suffix rule, the empty shipped baseline, the fact that verify.sh runs in the blocking CI job, that the shell loaders do not implement ENVLINE_SPEC.md, and the chmod 000-as-root caveat.
  • index-doctor: states that doctor.py checks the RRF floor while production gates on cosine + reranker (so ci_rag_smoke remains the gate test); fixes "scores of 0.03–0.06 are normal" (the ceiling is 0.0333); /index/build exists now; cyclaw-clear-cache is a dry run without --apply; verify.sh indexes all of data/corpus/, not one file; install pointer → driver.sh venv.
  • injection-redteam: the pattern count is enforced (doc-sync D4, blocking CI job), not "documentary"; one venv note instead of two; two CLAUDE.md §4 duplicates trimmed.
  • otel-hardening: Step 4 now names CONTRACT_DIGEST / _EXPECTED_CONTRACT_DIGEST (following the old step broke gateway boot); the blocking CI jobs are invariant-guard, doc-sync and dotenv-guard, not invariant-guard alone; the Guardrails section no longer restates CLAUDE.md §3. The spawn-site paragraph (unshare → bwrap, the Keychain security binary) is deliberately not touched: [security] - Classify the Keychain CLI and uv in the telemetry egress inventory #1637 rewrites it.
  • verify-deps: the surfaces table gains the hashed locks and stops saying requirements.txt carries torch or that the Dockerfile installs requirements.txt; E5 describes the lock-based Docker contract; Step 4's dry-run block follows §8; the uv/first-index story told three times is told once; [tool.uv.sources] (not in pyproject.toml) and the pyodbc-is-undeclared claim (it is the mssql extra) are gone; the eighteen-item verify list is a paragraph (the script runs 24); --strict on extract_pins.py is documented.
  • doc-sync: the dated "Current baseline (2026-09-16)" section is removed; "Environment Quirks" → §4 "Boot semantics"; the verify description covers the D7/D9–D11 suites and test_contracts.py; a misplaced D8 parenthetical is back on D8.
  • Trim pass (4c44693, at the owner's request): verify-deps' E1/E7 narratives, the huggingface_hub/starlette promotion story and two gotchas condensed; the duplicated plain/--strict command blocks in dep-guard and config-guard merged; injection-redteam's dry-corpus paragraph shortened. No check ID, exit code or rule changed; every verify.sh still passes.

Net: 339 insertions, 372 deletions across 16 files.

Invariant / Governance Impact: none of the six invariants or I6 changes; no file outside .claude/skills/ is touched. The invariant-guard mutation test is strengthened (it now actually breaks I4 in the scratch tree). The agent instruction surface changed, which the pre-commit security gate flagged as a reminder.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Security (auth, privacy, injection, egress, redaction, or secrets)
  • Invariant / Governance refinement (use this for changes that strengthen or evolve the 6 invariants, I6 isolation, or harness phases)
  • Dependencies (added, removed, or bumped)
  • CI / infrastructure (workflows, hooks, templates, or checkers)
  • Refactor or tests (behavior-preserving, no new capability)
  • Documentation update
  • Other (none of the boxes above fit)

Scope note: Docs + audits, plus three checker-script corrections under .claude/skills/.

Benefits / why

  • An invariant-guard self-test that cannot fail proves nothing; the I4 mutation now does.
  • dep-guard now sees the one workflow that still hardcodes the torch pin outside ci.yml.
  • Every install hint in the checker skills matched a recipe the repo retired in [infra] - Park hashed pip locks in locks/ and drop temp paths from comments #1598; they now point at the hashed locks and driver.sh venv.
  • The min_score guidance in three skills (and the config-guard band) would have led an agent to a value that can never pass; it now states the RRF ceiling and the real gate.

Risks to monitor

Checklist

  • I have read docs/THREAT_MODEL.md, INVARIANTS.md and SECURITY.md (and any relevant Phase docs)
  • This change preserves all 6 security invariants and I6 module isolation (no core file touched; invariant-guard clean tree 46/46, mutation test 4/4)
  • Full sandbox validation has been run — not run; per CLAUDE.md §5 the suites run in GitHub Actions. Run directly: every touched skill's verify.sh (invariant-guard, dep-guard, config-guard, doc-sync, otel-hardening, injection-redteam, verify-deps: all OK, re-run after the trim), check_deps.py, check_config.py --strict, check_dotenv.py, check_env_drift.py --strict, check_otel.py --strict, doc_sync.py (0 drift), ruff on the touched Python (the two remaining findings predate this branch). index-doctor and dotenv-guard/verify.sh could not run here (no torch; root cannot be denied a chmod 000 read).
  • No new external network dependencies or mandatory online LLM assumptions were introduced
  • For any agentic/fsconnect change — n/a
  • Relevant architecture docs or threat model notes have been updated if core behavior or topology changed — n/a
  • Commit messages follow the title prefix convention above
  • For large or complex changes: before/after invariant matrix — n/a

Further comments

Findings deliberately left out of this PR: doctor.py still compares the fused score with min_score rather than walking the production gate (documented as a gap; changing it needs the retrieval stack installed to test); check_otel.py's KNOWN_EXTERNAL_COMPONENTS missing security is fixed by #1637; the dotenv-guard/verify.sh root caveat is documented rather than coded around.

Suggested merge order of open PRs

Trial merges verified (git merge --no-commit --no-ff + abort) against main @ 663a8bb on 2026-10-13, including this PR stacked on top of #1637's branch (the only other open PR touching a file this one edits).

#1637 · Safe ✅
Impact: otel-hardening inventory; shares otel-hardening/SKILL.md with this PR in disjoint hunks.
Action: merge anytime; this PR merges cleanly after it.

#1638 · Safe ✅
Impact: docs/audits report; independent.
Action: merge anytime.

#1640 · Safe ✅
Impact: docs/audits report; independent.
Action: merge anytime.

#1641 · Safe ✅
Impact: CI bwrap/AppArmor workflow; independent.
Action: merge anytime.

#1642 · Safe ✅
Impact: loop/persona skill files; disjoint from this PR.
Action: merge anytime.

#1643 (this PR) · Safe ✅
Impact: checker skill files only.
Action: merge after #1637 or before it; both orders trial-merged clean.

#1645 · Safe ✅
Impact: knowledge/session skill files; disjoint from this PR.
Action: merge anytime.

ELI5

The repo has nine small "inspector" scripts, each with an instruction sheet. Several sheets described inspections the scripts don't do, quoted old install commands, or gave a retrieval tuning number that could never work. Worse, one self-test for the most important inspector (invariant-guard) had been quietly passing for a while because it tried to cut a wire that no longer exists, so it never actually proved the inspector could catch a broken audit path. This PR fixes the sheets to match the scripts, makes that self-test cut a real wire, teaches the dependency inspector about one workflow it had been ignoring, and then shortens the sheets' repeated stories. Nothing in the running server changes. What could still go wrong: the sheets quote how many self-test scenarios each script runs, and those counts will drift as scripts grow; the sentences say so, and the scripts print their own tallies, so trust the tally over the sheet.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LbrgG4NUbR3sUTgNMfKXpU


Generated by Claude Code

Last updated: 2026-10-13 02:44 ET

…k install and the retrieval gate

Reads every checker skill against the code it describes and fixes what had
drifted. invariant-guard claimed 47 assertions (the checker prints 46), a
target-set check for pre_action_hook_router the script does not do, and a
mutation self-test that severed a grok_fallback -> audit_logger edge graph.py
no longer has, so the sed changed nothing and the assertion passed on the
PASS line's wording; verify.sh now severs guardrail_output -> audit_logger,
asserts the sed applied, and matches a FAIL line. dep-guard's D8 list gains
nemo-guardrails.yml (which hardcodes the torch pin and was not scanned) and
points its doc scan at docs/work/SETUP.md; its SKILL.md stops claiming a
torch-cpu extra, a requirements.txt install path, and "does not track
coverage wiring" (D10 does). config-guard documents C0 and mutation E, the
real C2 severity (FAIL only when graph_timeout <= llm_timeout), what boot
validation now covers, and the RRF ceiling instead of a 0.05-0.08 band.
dotenv-guard's suffix rule now defers to utils/secret-policy.tsv (DB_URL and
the exact names were missing from three copies), notes the empty baseline,
the blocking CI verify step, and the chmod-000-as-root caveat. index-doctor
states what doctor.py checks (RRF floor) versus the production gate
(min_semantic_score plus the rerank veto), the 2/60 score ceiling, the
/index/build route, and the dry-run default of clear_cache. verify-deps
drops the uv story told three times, the [tool.uv.sources] references, the
pyodbc-undeclared claim, the 14-site pip count, the eighteen-item verify list
and the requirements.txt-carries-torch table row, and gains the hashed locks
as the documented install surface. doc-sync loses its dated baseline section
and points at CLAUDE.md §4 "Boot semantics". Install hints everywhere point
at CLAUDE.md §8's locks or driver.sh venv, and docs/PROPOSED_SKILLS.md is
cited at its real path docs/work/.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LbrgG4NUbR3sUTgNMfKXpU
@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

PR is a complete fill of .github/PULL_REQUEST_TEMPLATE.md (every section, ticked boxes, merge order, ELI5 last, last-updated stamp, title, branch).

Condenses verify-deps' E1/E7 narratives, the huggingface_hub/starlette
promotion story and two gotchas, merges the duplicated plain/--strict
command blocks in dep-guard and config-guard, and shortens
injection-redteam's dry-corpus paragraph. No check ID, exit code or rule
changes; every verify.sh still passes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LbrgG4NUbR3sUTgNMfKXpU
@cgfixit
cgfixit marked this pull request as ready for review October 13, 2026 08:44
@cgfixit
cgfixit merged commit 659d910 into main Oct 13, 2026
60 of 61 checks passed
@cgfixit
cgfixit deleted the claude/skills-checker-sync branch October 13, 2026 08:44
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T08:59:09.409831Z 4c44693 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4c44693a58

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +38 to +40
installed. In a fresh container it is not — build it with
`bash .claude/skills/cyclaw-gotchas/driver.sh venv` (the hashed `locks/`
install from CLAUDE.md §8, torch first). The embedding model must also be

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 Run index-doctor through the created venv

In the cloud-sandbox environment this step targets, driver.sh venv creates /root/.venv-cyclaw-312 in a subprocess and cannot activate it in the caller, while the following command still uses bare python3; when the system interpreter lacks the retrieval dependencies, the documented preparation succeeds but doctor.py immediately exits 3. Invoke the doctor with the created venv's interpreter or explicitly activate that venv before Step 1.

AGENTS.md reference: AGENTS.md:L35-L37

Useful? React with 👍 / 👎.

Comment on lines +114 to +115
gate), asserts each sed actually changed the file, and asserts the checker
exits 2 and reports all four as `FAIL` lines. A checker that cannot fail

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 Require FAIL markers for every invariant mutation

The new claim that all four mutations are reported as FAIL is not enforced by verify.sh: only the audit assertion searches for FAIL.*, while the import, retrieve-edge, and path-map greps also match their normal PASS lines. If any of those three checker rules regresses, mutation B still supplies exit 2 and the harness falsely prints that all four violations were detected; require a FAIL marker for each assertion and verify each sed applied.

AGENTS.md reference: AGENTS.md:L24-L31

Useful? React with 👍 / 👎.

Comment on lines +202 to +204
pip install --dry-run --require-hashes --no-deps -r locks/requirements-torch-lock-linux.txt --index-url https://download.pytorch.org/whl/cpu
pip install --dry-run --require-hashes -r locks/requirements-lock-linux.txt
pip install --dry-run --require-hashes -r locks/requirements-test-lock-linux.txt

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 Resolve the lock files in one dry-run

In the fresh venv prescribed above, the first --dry-run only plans the torch installation and does not install it, so the next invocation runs with torch absent. Because the runtime lock deliberately omits torch while packages such as sentence-transformers depend on it, pip under --require-hashes must resolve an unhashed dependency and the documented verification can fail on valid locks. Combine the lock files into one dry-run with the CPU index, or actually install torch before separately dry-running the remaining locks.

AGENTS.md reference: AGENTS.md:L35-L37

Useful? React with 👍 / 👎.

Comment on lines +139 to 142
- **WARN is intentional friction, not a bug.** A changed `rrf_k`, a sub-30 s
timeout margin, or an operator changing the shipped provider posture are legitimate — the
WARN exists so the change is conscious and documented, not silent. Use
`--strict` only where you want the shipped defaults locked.

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 Do not bless a timeout margin that boot rejects

When an operator sets a positive but sub-30-second timeout margin, the documented default checker emits only a warning and exits 0, and this paragraph now explicitly calls that setting legitimate. validate_boot_timeout_config, however, unconditionally raises ConfigError for the same values, so the suggested interpretation can approve a configuration that cannot boot unless the operator happened to add --strict. Treat this C2 condition as a failure or at least stop describing it as an acceptable warning.

AGENTS.md reference: AGENTS.md:L5-L7

Useful? React with 👍 / 👎.

| C5 | FAIL | `personality.soul_max_chars` is positive and **<** `retrieval.max_context_tokens * _CHARS_PER_TOKEN` (3 — mirrors `graph.py CHARS_PER_TOKEN`, the worst-case chars/token floor used to derive the character budget) so the soul cannot crowd out retrieved context |
| C6 | FAIL | `api.rate_limit.max_requests` / `window_seconds` are positive integers |
| C7 | WARN | `retrieval.min_score` stays on the RRF scale (≤ 0.1) — **the acknowledged trap**; a stricter gate belongs in 0.05–0.08, never the cosine-scale 0.5 |
| C7 | WARN | `retrieval.min_score` stays on the RRF scale (≤ 0.1) — **the acknowledged trap**. The hybrid ceiling is 2/60 ≈ 0.033 and the keyword-only degrade tops out at 1/60 ≈ 0.017, so anything above ~0.033 can never pass; a stricter vault-hit gate is `min_semantic_score` (cosine), never a bigger `min_score` |

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 Align C7 with the actual RRF ceiling

For a value such as retrieval.min_score: 0.05, C7 currently reports no warning because _RRF_SANITY_CEILING remains 0.1, even though the newly documented 2/60 ceiling means no hybrid result can clear that value and the keyword-only path tops out even lower. This leaves the checker silent for the entire 0.033–0.1 range that the same row says can never pass; derive the warning ceiling from rrf_k or lower it to the real fused-score maximum.

AGENTS.md reference: AGENTS.md:L5-L7

Useful? React with 👍 / 👎.

# Each query is answerable by the committed corpus (data/corpus/cyclaw_overview.md),
# phrased near corpus headings so it clears the gate at stable runtime. The
# "one sentence" probe mirrors CyClaw-Sandbox P13, the canonical vault-hit test.
# "one sentence" probe mirrors the vault-hit check CyClaw-Sandbox/smoke.sh runs.

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 Correct the claimed shared vault-hit probe

The sandbox smoke does not run the one-sentence query: its direct local-path request is What is RRF fusion in CyClaw?, followed by What is CyClaw? on the explicitly declined-online path. Consequently, a regression specific to Describe CyClaw in one sentence. is covered only by index-doctor despite this comment and the matching SKILL.md text claiming duplicate smoke coverage; either use the actual shared query or add this probe to smoke.sh.

AGENTS.md reference: AGENTS.md:L49-L49

Useful? React with 👍 / 👎.

"CLAUDE.md",
"AGENTS.md",
"docs/SETUP.md",
"docs/work/SETUP.md",

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 Scan the canonical setup guide for Torch drift

D8 now scans docs/work/SETUP.md, but that file only points readers back to the root guide; the actual setup-guide.md contains multiple hardcoded torch==2.13.0 and torch==2.13.0+cpu installation claims and is absent from _TORCH_DOC_FILES. A Torch bump can therefore leave the canonical platform instructions stale while dep-guard reports that all documentation agrees, so add setup-guide.md to the scanned paths.

AGENTS.md reference: AGENTS.md:L35-L37

Useful? React with 👍 / 👎.

Comment on lines +140 to +141
single pip path (no `||` fallback, no stderr redirect), never installs the
test lock into the image, and that the torch the torch lock pins is the

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 Actually reject the hashed test lock in Docker

The newly documented E5 guarantee is not implemented: check_docker_install_contract() only searches for requirements-test\.txt, which does not match locks/requirements-test-lock-linux.txt. If a separate COPY and pip install --require-hashes -r locks/requirements-test-lock-linux.txt are added to the Dockerfile, the checker still exits 0 and reports that the image is test-tool-free; extend the rejection and its mutation test to cover the hashed test-lock filename.

Useful? React with 👍 / 👎.

cgfixit added a commit that referenced this pull request Oct 13, 2026
…-13)

High-signal since 3fe8217 (#1619): #1637 telemetry/egress inventory completion (fail-closed kill block, full spawn-site table for PowerShell/pip/brew/git-remote cat-3, agent-tooling boundary, OLLAMA_HOST pin, secret-env wrappers); #1643/#1645 docs resyncs correcting I6/harness and checker skill drifts. Graph remains 12 nodes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants