From 4b9b83bfc81467bda0ccfd09b6816f645c9f7ddd Mon Sep 17 00:00:00 2001 From: rldyourmnd Date: Mon, 7 Sep 2026 12:03:03 +0500 Subject: [PATCH 1/2] feat(policy): select advisory CI for the GDS repository Signed-off-by: rldyourmnd --- .gds/repository.yaml | 1 + AGENTS.md | 7 +++ CHANGELOG.md | 4 ++ docs/runbooks/github-ruleset-reconcile.md | 53 +++++++++++------------ 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/.gds/repository.yaml b/.gds/repository.yaml index 9cbda2c..42210ef 100644 --- a/.gds/repository.yaml +++ b/.gds/repository.yaml @@ -65,6 +65,7 @@ policy: - "repository-default" - "public-module" - "github-device-sync" + - "continuous-development" rollout_ring: "standard" git: diff --git a/AGENTS.md b/AGENTS.md index c68d614..00aa9ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,6 +37,13 @@ checkout. - Keep secrets, runtime state, caches, logs and generated evidence untracked. - Generated fixtures under `tests/golden` change only through their generator. +## Continuous development + +This repository selects the continuous-development policy. Treat broad GitHub +CI as asynchronous evidence for ordinary integration, preserve actual outcomes, +and run checks relevant to the changed behavior. Release integrity, dependency +identity and provider transaction controls remain required. + ## Verification - Lint: `scripts/validate_shell.sh`. diff --git a/CHANGELOG.md b/CHANGELOG.md index df7f3e8..fd8519a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ Versioning. ## [Unreleased] +- Select continuous development for the GDS repository itself and document + explicit ruleset removal plus cautious readback after ambiguous write errors. + Generic policy defaults remain opt-in for other consumers. + - Publish unsuccessful completed self-workflow attempts as unassigned, repository-local CI evidence; preserve actual conclusions and exact attempts. diff --git a/docs/runbooks/github-ruleset-reconcile.md b/docs/runbooks/github-ruleset-reconcile.md index 4d20d90..76ee7d4 100644 --- a/docs/runbooks/github-ruleset-reconcile.md +++ b/docs/runbooks/github-ruleset-reconcile.md @@ -9,25 +9,20 @@ and live state disagreeing with nothing to reconcile them. ## What the command owns, and what it must not touch -GDS owns the `required_status_checks` rule **wholesale**: the desired state it -sends replaces the live list entirely. A context missing from the desired state -is a context deleted. - -That matters because the tracked contract at `.github/rulesets/branch-main.json` -holds only what `generate_required_checks.py` produces. It has to — the generator -compares against that file and would otherwise report every platform-emitted -context as drift. Contexts the platform emits therefore never appear there. - -`requirements/external-required-checks.json` closes the gap. Every context that -lives on the ruleset but is not generated by GDS is declared there with its -owner, and the planner merges those into the desired state so a reconcile carries -them through. Two rules keep the declaration honest: - -- a declaration naming a context the generator already produces is rejected — - otherwise two sources of truth claim the same context with no way to tell which - wins; -- an entry missing either its name or its owner is rejected, because an unowned - exception is indistinguishable from a typo. +When a desired `required_status_checks` rule is present, GDS owns its contents +wholesale. An omitted rule is preserved unless the compiled delivery profile +projects explicit `remove_required_status_checks` intent into the plan. + +The repository-owned baseline is `.github/rulesets/branch-main.json`. +`requirements/external-required-checks.json` adds contexts with declared owners +to that baseline. A duplicate generated context or an entry without a context +name and owner is rejected. + +Selecting `continuous-development` deliberately removes the entire required +status-check rule from the selected repository ruleset, including declared +external contexts. Review the plan's explicit removal flag and exact before/after +state. PR/signature rules, other rulesets, classic protection and environment +gates remain separate contracts; profile selection alone performs no write. Before any apply, read the plan's own diff rather than trusting either file: @@ -102,9 +97,10 @@ re-approving rather than overwriting. **`GDS_OPERATION_STEP_FAILED`, mutation attempted, not completed.** Preconditions verified and the handler was called. The operation journal records the step -failure but not the provider's error text, so diagnose from the mutation runtime: -check `gds context` for `mutations.runtime` first. Live state is unchanged — -the engine does not leave partial ruleset writes. +failure. Check `gds context` for `mutations.runtime` and read the live ruleset +again before deciding whether to retry. A failed response or post-write read +can follow an accepted provider update; failure alone does not prove unchanged +live state. Never blindly repeat the write. Read any operation's journal with: @@ -117,8 +113,8 @@ faster than re-deriving it. ## Renaming a required context -A workflow change that renames a check — moving a job to a different runner label -renames a required check — needs the live ruleset +A workflow change that renames a check, such as changing a matrix value used in +the job name, needs the live ruleset swapped **while the pull request is open**, not after it merges: 1. open the pull request carrying the workflow and tracked-ruleset change; @@ -134,11 +130,12 @@ trying to land. Other open pull requests will need a branch update afterwards. ## Verification `gds github ruleset --verify "$OPERATION_ID"` re-reads live state for a completed -operation. For a read-only check at any time, without credentials or a plan: +operation. To observe drift without a provider write, use the same configured +runtime and exact repository options: ```bash -python3 scripts/report_ruleset_drift.py --ruleset-id +gds github ruleset --plan "${COMMON[@]}" --json ``` -It separates owned drift from externally owned contexts and exits non-zero only -on the former. +This may store a local plan when drift exists. It does not apply that plan; +provider writing still requires its signed approval and one-shot enablement. From 2bc58d023c6ed61efe2f5302960ee16b904540e6 Mon Sep 17 00:00:00 2001 From: rldyourmnd Date: Mon, 7 Sep 2026 12:05:36 +0500 Subject: [PATCH 2/2] chore(projections): materialize the GDS advisory policy Signed-off-by: rldyourmnd --- .gds/bundle.lock.yaml | 12 ++++++------ .gds/compiled-policy.json | 20 +++++++++++++++++++- .github/workflows/gds-ci.yml | 5 +++-- docs/runbooks/github-ruleset-reconcile.md | 2 +- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/.gds/bundle.lock.yaml b/.gds/bundle.lock.yaml index 53895b1..5c17c89 100644 --- a/.gds/bundle.lock.yaml +++ b/.gds/bundle.lock.yaml @@ -5,14 +5,14 @@ bundle: version: "0.8.0-dev" release_sequence: 0 channel: "development" - source_tree_digest: "sha256:a2b5ad7bdb6a7198d0de86e3de879062c71df5e86ff2f257257693aee319aa4a" - digest: "sha256:010d85cbeeeb4b010e438b0ffcbe5c9211f86d8f170b66e187aa35b23480fc17" + source_tree_digest: "sha256:27c680c6d2fa6dbdb297d8902b19bccd2e9114449d0494fd4866df78b149631e" + digest: "sha256:71191a1e73172a41ffb3a1d1c17a97306d9fd7cc488a9d023f29513e5329c097" projection: - input_digest: "sha256:f914cbb8b69051475867d7fe14977debf309cb4ee1bd9bcddd6e64c7098bd886" - output_digest: "sha256:0a7d6b71492567ed5728b5b49c40225fab549fc3f7c252920f781aa9a671aa3a" + input_digest: "sha256:66e0e6e6b2788574f5a52479e921db822414f730671be57ed68aa96836aa7ac7" + output_digest: "sha256:9a70d43a686d9e18925ed01d4e078b4d21a31a7600486e28ce06b92da4347479" files: - path: ".gds/compiled-policy.json" - digest: "sha256:b5517ed46f67866220c2b18dbfbda4a40d99f00327611e56742a118d0ac59d0b" + digest: "sha256:807282f820294914e1c7e6ad1bf27c54a799d56305c58630254ab50ab286f379" - path: ".github/workflows/gds-ci.yml" - digest: "sha256:1da9d1ccf7c40ec6328f2c957aeb910c9de68ab91d8e07917d1486165cf209cc" + digest: "sha256:f164762300a774d716fcee22720a25c42c8c3fb142bf6546286b34170b1cdc89" diff --git a/.gds/compiled-policy.json b/.gds/compiled-policy.json index 7d1aab5..4c4cb6b 100644 --- a/.gds/compiled-policy.json +++ b/.gds/compiled-policy.json @@ -3,7 +3,7 @@ "compiled_policy": { "repository_id": "repo_01M0EZ7TB3KNXNSP78Z8M64WXG", "bundle_version": "0.8.0-dev", - "digest": "sha256:13fde780e078b9143e913db7cf706c8908b52c21ec51f28d26d3c9fdd715e080" + "digest": "sha256:f901d1860f277a0262d83c6fa06a806f7740677fb14576bbf5816c69af565974" }, "sources": [ { @@ -22,6 +22,14 @@ "path": "policies/roles/public-module.yaml", "digest": "sha256:084f7b09dbfd85a386e47cf83ea0015154b6b01fa3cf85a68f04ef407b89ed4b" }, + { + "id": "continuous-development", + "tier": "stack", + "priority": 500, + "distribution": "public", + "path": "policies/stacks/continuous-development.yaml", + "digest": "sha256:678b6876cd6cf58d7b97e7e0751e7ec9c0d3f75c2c78c5bfbe0d02930774195d" + }, { "id": "github-device-sync", "tier": "repository", @@ -42,6 +50,9 @@ "context": { "private_parent_persistence": "forbidden" }, + "delivery": { + "profile": "continuous-development" + }, "git": { "branch_cleanup": "merged-only", "default_branch": "main", @@ -188,6 +199,13 @@ "file": "policies/base/repository-default.yaml", "operation": "set" }, + "/effective/delivery/profile": { + "source": "continuous-development", + "tier": "stack", + "priority": 500, + "file": "policies/stacks/continuous-development.yaml", + "operation": "set" + }, "/effective/git/branch_cleanup": { "source": "repository-default", "tier": "base", diff --git a/.github/workflows/gds-ci.yml b/.github/workflows/gds-ci.yml index 78b37fa..5b4cbf3 100644 --- a/.github/workflows/gds-ci.yml +++ b/.github/workflows/gds-ci.yml @@ -1,14 +1,15 @@ # GENERATED FILE - DO NOT EDIT DIRECTLY # generator: gds # bundle: 0.8.0-dev -# source-tree-digest: sha256:a2b5ad7bdb6a7198d0de86e3de879062c71df5e86ff2f257257693aee319aa4a -# input-digest: sha256:f914cbb8b69051475867d7fe14977debf309cb4ee1bd9bcddd6e64c7098bd886 +# source-tree-digest: sha256:27c680c6d2fa6dbdb297d8902b19bccd2e9114449d0494fd4866df78b149631e +# input-digest: sha256:66e0e6e6b2788574f5a52479e921db822414f730671be57ed68aa96836aa7ac7 # output-digest: sha256:4a875d4ed62fe6b2d279515f9a19274e159ae8ed58f3a1a0843c60a49f663886 # edit-source: # - .gds/repository.yaml # - policies/base/repository-default.yaml # - policies/repositories/github-device-sync.yaml # - policies/roles/public-module.yaml +# - policies/stacks/continuous-development.yaml # - templates/agents/repository.md.tmpl # - templates/github-actions/go.yml.tmpl # - templates/harnesses/claude.md.tmpl diff --git a/docs/runbooks/github-ruleset-reconcile.md b/docs/runbooks/github-ruleset-reconcile.md index 76ee7d4..b578801 100644 --- a/docs/runbooks/github-ruleset-reconcile.md +++ b/docs/runbooks/github-ruleset-reconcile.md @@ -1,7 +1,7 @@ # Runbook: reconciling the default-branch ruleset Status: local implementation runbook. Applying mutates live branch protection on -the control-plane repository; read the whole document before the first apply. +the selected repository; read the whole document before the first apply. `gds github ruleset` is the only supported way to change the tracked default-branch ruleset. Editing it in the GitHub UI leaves the tracked contract