fix(governance): materialize policies/sacred-paths.yaml as generated canonical manifest #806
Labels
No labels
W6d-automerge-calibration
agent/claude-code
agent/codex
agent/hermes
agent/iskra
agent/ollama
agent/patchwarden
automerge-candidate
class/security-sensitive
cutover-gate
dependency/blocked
dependency/blocks-others
dependency/cross-repo
dependency/needs-confirmation
domain:agents
domain:ci
domain:docs
domain:forgejo
domain:infra
domain:memory
domain:runtime
domain:signal
domain:ux
flow/architecture
flow/blocked
flow/deployed
flow/done
flow/implementation
flow/intake
flow/maintained
flow/observed
flow/ready
flow/refining
flow/retired
flow/review
iterating
judge/codex-candidate
judge/hermes-candidate
judge/low-confidence
judge/needs-refinement
judge/operator-needed
judge/p0
judge/p1
judge/p2
judge/p3
judge/park
judge/patchwarden-candidate
judge/stale-priority
kind/adr
kind/bug
kind/chore
kind/feature
kind/infra
kind/ops
kind/refactor
kind/research
large-impact
merge/auto
merge/manual
merge/manual-dependency-conflict
merge/manual-failing-tests
merge/manual-merge-conflict
merge/manual-missing-review
merge/manual-operator-preference
merge/manual-red-zone
merge/manual-security-sensitive
merge/manual-unclear-scope
merge/manual-unknown
meta
mode:operator-only
mode:patchwarden-iskra-approved
mode:safe-auto
needs-operator-decision
needs-triage
not-ready
observed/erroring
observed/needs-followup
observed/pending
observed/retire-candidate
observed/unused
observed/used
operator-emotional
owner-attention
phase/02
phase/03
priority:p0
priority:p1
priority:p2
priority:p3
proposed
ready-for-agent
ready-for-operator
recovery
review:claude-reviewed
review:codex-reviewed
review:dziadek-reviewed
review:needs-human
risk/exposure
risk/process
risk/product
risk/runtime
safety:external-write
safety:no-prod-mutation
safety:prod-impact
safety:secret-touch
size/large
size/medium
size/small
size/tiny
size/unknown
source/adr
source/agent-generated
source/manual
source/operator-chat
source/voice-note
status:blocked
status:codex-ready
status:merged:pending-evidence
status:needs-evidence
status:operator-needed
status:parked
tier/full
tier/lite
tier/stacked
tier:0-platform-substrate
tier:1-iskra-value-layer
tier:2-tools-products-modules
type:bug
type:chore
type:docs
type:feat
type:policy
type:research
No milestone
No project
No assignees
5 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pdurlej/platform!806
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "claude/sacred-paths-canonical-manifest"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
PLATFORM_CHARTER.md§11 andMAP.mdboth promisepolicies/sacred-paths.yamlas the canonical sacred-path list — but the file does not exist on
main(
policies/holds onlyagent-capabilities.yaml+mcp-registry/). The reallist lives only as hardcoded constants in
control-plane/platformctl/safety.py.Found in the platform health audit (2026-06-15).
Severity finding (step 1) — NOT a fail-open hole
The audit hypothesis was a latent fail-open in the sacred-path gate. Disproven.
control-plane/platformctl/ci/pr_sanity.py:94(
SENSITIVE_PREFIXES) and:113(
SECURITY_SENSITIVE_PREFIXES) reference the path as a protected prefix,consumed by
deterministic_findings()(
:204) for prefix-matchingagainst
files_changed. No code opens the file (repo-wide grep: only docsinert/dead — they simply never fired. The gate stays fail-closed on the
real paths (
apply.py,safety.py,identity/,transport/, charter, …),which emit a
blockersecurity-sensitive-label-missingfinding when theclass/security-sensitivelabel is absent.a dangling source-of-truth pointer + the canonical list being auditable only by
reading Python, contradicting the charter's own single-source-of-truth claim.
Resolution (step 2) — operator-approved direction: code stays truth
The charter's own wording — "generated from
module.yaml… + repo-wide rules" —says code/manifests are upstream and the YAML is a generated view. So:
control-plane/platformctl/ci/generate_sacred_paths.py— generator thatbuilds the manifest from
safety.pyrepo-wide rules + everymodule.yamlowned_paths/shared_paths. Idempotent; deterministic ordering.policies/sacred-paths.yaml— the checked-in generated artifact. It is nowthe live, protected file: the previously-dead
pr_sanity.pyreferencesbecome active (this PR adds the file → the gate now requires the label for it,
which is exactly why this PR carries
class/security-sensitive— the mechanismis validated end-to-end).
safety.pyremains the runtime source of truth — the live gate(
is_sacred_path/check_target) is not rewired to load YAML, so no newfail-open surface is introduced.
PLATFORM_CHARTER.md§11 /MAP.md: wording made precise(
owned_paths/shared_paths+safety.py; regenerate command added to charter).control-plane/pyproject.toml: register the generator in the pyfallowentrylist.
Test (step 3) — fail-closed drift guard
control-plane/platformctl/tests/test_generate_sacred_paths.py:regenerating breaks CI);
--checkmode agrees with the committed file;safety.pyconstants;manifest.py's invariant).Run by
python-ci.yml(pytest control-plane/platformctl/testsoncontrol-plane/**). Local run: 177 passed (new test +test_pr_sanity+test_safety_phase3). The 14 unrelated collection errors in the full suite arepre-existing local-env noise (
clicknot installed in this interpreter; CIinstalls via
pip install -e ./control-plane[dev]).Out of scope (follow-up)
control-plane/platformctl/memory.py:20keeps a third, independentSACRED_PATH_PATTERNSregex list for memory destructive-op guarding — a separatedrift worth reconciling, but left untouched here to keep this PR coherent.
Review tier
class/security-sensitive(touches the sacred-path gate surface) →full canary 3+3 + operator manual merge per ADR-0007. Committed as actor
claude(notpdurlej).Patchwarden PR sanity
Operator signal: ✅ GO - Patchwarden can hand this exact head to the approval controller.
Automerge signal: 🟡 CONTROLLER ONLY - approval-ready, but outside the narrow safe-docs/status automerge lane.
Verdict: ✅ PASS - deterministic checks and configured reviewers are clean.
Next step: Continue through required Forgejo approval and the automerge controller.
806dd3d702fc7865db2a722aca03c6529c2a398ca24eligible_sanity_cleancleanpresentglm-5.2:cloud,deepseek-v4-pro:cloud,kimi-k2.7-code:cloudWhat I checked
6cleannot_reported3Approval Handoff
ready_for_external_controller_reviewSignal Board
cleannot reportedcleanreadyineligiblenot neededMAP.md,PLATFORM_CHARTER.md,control-plane/platformctl/ci/generate_sacred_paths.py,control-plane/platformctl/tests/test_generate_sacred_paths.py, ... (+2 more)class/security-sensitive,tier/fullclass/security-sensitiveis present.🧭 Merge authority: branch protection and automerge controller remain authoritative.
Required Fixes
No deterministic blockers.
Non-blocking Notes
infosensitive-path-touchedSensitive path touched -PLATFORM_CHARTER.mdPLATFORM_CHARTER.mdinfosensitive-path-touchedSensitive path touched -policies/sacred-paths.yamlpolicies/sacred-paths.yamlReviewer Details
Model reviewer lanes
global-glm/glm-5.2:cloudStatus:
okVerdict:
OKlowByte-match drift guard depends on PyYAML serialization stabilitycontrol-plane/platformctl/ci/generate_sacred_paths.py:118-125 renders viayaml.safe_dump(doc, sort_keys=False, default_flow_style=False, width=4096, allow_unicode=True); test_generate_sacred_paths.py:33-39 assertsactual == expectedbytyaml.safe_loadon both sides in addition to byte equality), so a serializer patch doesn't break the drift guard.lowShared module paths are not checked against sacred-path settest_generate_sacred_paths.py:60-66 only iteratesentry.get("owned", [])and assertsnot matchedviasafety.is_sacred_path.sharedentries (e.g.,compose/apps/compose.yamlfor iskra-things-sync, kan-mcp, pogodowa-babcia) are skippentry.get("shared", []), extracting thepathfield when entries are dicts, and assert non-sacred — mirroring the owned-path check.lowfind_modules_dirimport unverified in this diffgenerate_sacred_paths.py:19 importsfrom platformctl.manifest import find_modules_dir; output_path():107 and build_document():81 fall back to it. The symbol's existence/behavior is not shown in the diff, and--checkmode relies on it replatformctl.manifest.find_modules_direxists and resolves to<repo>/moduleson the CI runner; if not, the--checkentrypoint andoutput_path()default will diverge from the test fixture path.global-deepseek/deepseek-v4-pro:cloudokOKredteam/kimi-k2.7-code:cloudStatus:
okVerdict:
OKmediumDrift guard skips shared-path sacred-path validationcontrol-plane/platformctl/tests/test_generate_sacred_paths.py:60-62 only checks entry.get('owned', []); it never extracts the 'path' value from shared_paths dicts. The generator emits shared paths in policies/sacred-paths.yaml (e.g., iskra-Policy notes
Iskra judgment
pdurlej/platform#pull_request#806judge/p1,judge/patchwarden-candidateiskraviaopenclawRationale: This PR appears to materialize a promised canonical governance manifest and reduce drift around sacred-path policy without claiming a fail-open security fix.
Caveat: The packet summarizes evidence but does not include full diff or test output, so security-sensitive review should verify generated-manifest parity.
Structured openclaw.judge.v0 payload
Iskra judgment
pdurlej/platform#pull_request#806judge/p1,judge/patchwarden-candidateiskraviaopenclawRationale: The PR addresses a security-sensitive governance/docs-to-policy mismatch with a canonical generated manifest, so it remains high-priority and review-worthy after the target changed.
Caveat: The packet excerpt does not include the full diff or test output, so manifest parity and generator behavior still need verification.
Structured openclaw.judge.v0 payload
Operator live approval present for #806: branch is current and all latest CI/Patchwarden contexts are green. Approval recorded by Iskra as merge actor for the canonical sacred-path manifest PR.
Operator approval relayed from live Codex merge-fest scope: platform PR queue only.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.