diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index dba71e9..9444cbc 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1 +1,67 @@ -@../AGENTS.md + +# Claude Code repository contract + +## Scope + +- GDS repository ID: `repo_01KYFBZ4DBDJE4Z769C81WBGBA`. +- Roles: `module`. +- Canonical repository facts: `.gds/repository.yaml`. +- Applied policy bundle: `.gds/bundle.lock.yaml` (`0.1.0-dev`). +- This is a first-class Claude Code projection compiled from the same typed + inputs as `AGENTS.md`; neither projection is a manual policy source. + +## Repository boundaries + +- Treat this Git repository as one independent mutation boundary. +- Preserve unrelated dirty changes, branches, worktrees, and submodules. +- Run `gds context --json` before work crosses repository boundaries. +- Do not edit generated projections; change the declared canonical input and + regenerate. + +## Safety + +- External writes require explicit approval: `true`. +- Generated projection edits: `forbidden`. +- Private parent context persistence: `forbidden`. +- Visibility: `public`; data: `public`. + +## Verification commands + +- Test: `python3 -m json.tool config/nddev-contract.json`. + +## Claude workflow routing + +- Start here: run `gds-orient` (or `gds context --json`) to resolve scope before + any cross-repository work. +- Active skill profiles: `core, module`. Five profiles exist in total + (`core`, `estate-admin`, `module`, `device`, `portfolio`); only the listed ones + are active for this repository. The catalog is `skills/registry.yaml`, and each + skill lives under `skills/canonical//SKILL.md`. +- Load procedural detail from the applicable installed GDS skill projection or + plugin only when the task matches it. +- Destructive workflows remain explicit-only and still require their concrete + plan and approval gates. +- Treat documentation and Serena memories as derived evidence, never mutation + authority. + +## Done + +- Required checks pass or are explicitly reported `NOT_PROVEN`. +- Every affected Git boundary and remote result is classified. +- No secret, private-context leak, unrelated change, or unapproved projection + drift is introduced. diff --git a/.gds/bundle.lock.yaml b/.gds/bundle.lock.yaml new file mode 100644 index 0000000..f17ef76 --- /dev/null +++ b/.gds/bundle.lock.yaml @@ -0,0 +1,20 @@ +# GENERATED FILE - DO NOT EDIT DIRECTLY +schema_version: 1 + +bundle: + version: "0.1.0-dev" + release_sequence: 0 + channel: "development" + source_commit: "97e8bbaa3a0734b156b03bad704503bc46d7575b" + digest: "sha256:fd66beb15c847e94b68a00083df5f218c22f4e1174d39d4bd10ed7fb321b13bc" + +projection: + input_digest: "sha256:0cb183610b1beb479696ae77b3a4d7c12decc10d472c3b467e6ba807e072249d" + output_digest: "sha256:d85ee3c65c606c1c3e41b447f54864fa9ff5ffa08c10df753bf839d21bd42e36" + files: + - path: ".claude/CLAUDE.md" + digest: "sha256:a2b362f8ea8f7fe75f32c1074b89aafdafd11e3039268cd677985c82871ed8dd" + - path: ".gds/compiled-policy.json" + digest: "sha256:0a7e0932adb08a0e05dc8e12bf727e3b550be47670673e28de3e9cf746bece37" + - path: "AGENTS.md" + digest: "sha256:d18f81d3f72d09bac369c226a4c42e40a4dfae1836cfacfb37d453e7a3a6b346" diff --git a/.gds/compiled-policy.json b/.gds/compiled-policy.json new file mode 100644 index 0000000..d92f859 --- /dev/null +++ b/.gds/compiled-policy.json @@ -0,0 +1,550 @@ +{ + "schema_version": 1, + "compiled_policy": { + "repository_id": "repo_01KYFBZ4DBDJE4Z769C81WBGBA", + "bundle_version": "0.1.0-dev", + "digest": "sha256:6bb5db5691ec21b564339c7181cd14fe469f0a3b05888a868fb94bb848c55eca" + }, + "sources": [ + { + "id": "repository-default", + "tier": "base", + "priority": 100, + "distribution": "public", + "path": "policies/base/repository-default.yaml", + "digest": "sha256:e74e6dc4429eda77b02e0f5267dc0db5b25b1a666262660b9dd992d53922f15c" + }, + { + "id": "organization-default", + "tier": "owner", + "priority": 100, + "distribution": "public", + "path": "policies/owners/organization-default.yaml", + "digest": "sha256:fe271769a3e50404a5073ca6d045ad19f784069e7d6fdceab80254c06781ed55" + }, + { + "id": "public-module", + "tier": "role", + "priority": 100, + "distribution": "public", + "path": "policies/roles/public-module.yaml", + "digest": "sha256:ece6164691eda262e2692f97bd70262ea98c268084900b3f285f3d50f3767200" + } + ], + "effective": { + "agent": { + "generated_projection_edit": "forbidden", + "profiles": [ + "core", + "module" + ] + }, + "context": { + "private_parent_persistence": "forbidden" + }, + "git": { + "branch_cleanup": "merged-only", + "default_branch": "main", + "integration": "pull-request" + }, + "github": { + "actions": { + "allowed_actions": { + "management": "observed" + }, + "enabled": { + "management": "managed", + "value": true + }, + "selected_actions": { + "management": "observed" + }, + "sha_pinning_required": { + "management": "observed" + } + }, + "merge": { + "allow_auto_merge": { + "management": "managed", + "value": false + }, + "allow_merge_commit": { + "management": "managed", + "value": false + }, + "allow_rebase_merge": { + "management": "managed", + "value": false + }, + "allow_squash_merge": { + "management": "managed", + "value": true + }, + "allow_update_branch": { + "management": "managed", + "value": true + }, + "delete_branch_on_merge": { + "management": "managed", + "value": true + }, + "merge_commit_message": { + "management": "observed" + }, + "merge_commit_title": { + "management": "observed" + }, + "squash_merge_commit_message": { + "management": "managed", + "value": "PR_BODY" + }, + "squash_merge_commit_title": { + "management": "managed", + "value": "PR_TITLE" + } + }, + "rulesets": { + "management": "observed" + }, + "security": { + "management": "observed" + }, + "workflow": { + "can_approve_pull_request_reviews": { + "management": "managed", + "value": false + }, + "default_workflow_permissions": { + "management": "managed", + "value": "read" + } + } + }, + "package_management": { + "forbidden_executables": [ + "pip", + "pipx", + "poetry", + "npm", + "npx", + "pnpm", + "yarn", + "corepack", + "mise", + "asdf" + ], + "language_dependency_managers": [ + "uv", + "bun" + ], + "mutable_version_resolution": "forbidden", + "npm_family_on_managed_path": "forbidden", + "remote_stream_to_shell": "forbidden" + }, + "release": { + "compatibility_contract_required": true + }, + "rollout": { + "mode": "pull-request" + }, + "security": { + "external_write_requires_approval": true, + "public_projection_scan": "required", + "secrets_in_repository": "forbidden" + } + }, + "provenance": { + "/effective/agent/generated_projection_edit": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/agent/profiles/0": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "append" + }, + "/effective/agent/profiles/1": { + "source": "public-module", + "tier": "role", + "priority": 100, + "file": "policies/roles/public-module.yaml", + "operation": "append" + }, + "/effective/context/private_parent_persistence": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/git/branch_cleanup": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/git/default_branch": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/git/integration": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/actions/allowed_actions/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/actions/enabled/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/actions/enabled/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/actions/selected_actions/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/actions/sha_pinning_required/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_auto_merge/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_auto_merge/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_merge_commit/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_merge_commit/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_rebase_merge/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_rebase_merge/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_squash_merge/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_squash_merge/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_update_branch/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/allow_update_branch/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/delete_branch_on_merge/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/delete_branch_on_merge/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/merge_commit_message/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/merge_commit_title/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/squash_merge_commit_message/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/squash_merge_commit_message/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/squash_merge_commit_title/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/merge/squash_merge_commit_title/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/rulesets/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/security/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/workflow/can_approve_pull_request_reviews/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/workflow/can_approve_pull_request_reviews/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/workflow/default_workflow_permissions/management": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/github/workflow/default_workflow_permissions/value": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/0": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/1": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/2": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/3": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/4": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/5": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/6": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/7": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/8": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/forbidden_executables/9": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/language_dependency_managers/0": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/language_dependency_managers/1": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/mutable_version_resolution": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/npm_family_on_managed_path": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/package_management/remote_stream_to_shell": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/release/compatibility_contract_required": { + "source": "public-module", + "tier": "role", + "priority": 100, + "file": "policies/roles/public-module.yaml", + "operation": "set" + }, + "/effective/rollout/mode": { + "source": "organization-default", + "tier": "owner", + "priority": 100, + "file": "policies/owners/organization-default.yaml", + "operation": "set" + }, + "/effective/security/external_write_requires_approval": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/security/public_projection_scan": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + }, + "/effective/security/secrets_in_repository": { + "source": "repository-default", + "tier": "base", + "priority": 100, + "file": "policies/base/repository-default.yaml", + "operation": "set" + } + } +} diff --git a/AGENTS.md b/AGENTS.md index d2dedc4..5abc5f8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,56 +1,60 @@ -# nddev-pi-app Agent Rules - -Work only inside this public module unless the user explicitly changes scope. -Repository artifacts are English. - -## Ownership - -- Public manager: `cli-tools/nddev_pi.py`. -- Public validator: `cli-tools/validate_public_contracts.py`. -- Public contract: `config/nddev-contract.json`. -- Public build metadata: `build/manifest.json` and `build/version.json`. -- Runtime baseline pins: `references/pi-baseline.json`. -- Content setup: `setups/nddev-builder/`. -- Permission profiles: `profiles/full-auto/` and `profiles/safe/`. -- Native builder resources: `builder/nddev-builder/`. - -Do not add private validation, fixtures, benchmark data, operational memories, -runtime logs, generated evidence, credentials, live `~/.pi` state, root harness -files, registry updates, CI changes, pushes, or tags here. - -## Product Boundary - -The module manages only explicit caller-selected targets. The target is a -Pi configuration/runtime home, not the project workspace. Managed launch must -pass an explicit child working directory selected by the public manager. - -Use the setup/profile model: `nddev-builder` owns content, while `full-auto` -and `safe` own runtime posture. Keep future setup switching orthogonal to -future profile switching. - -## Native Pi Surfaces - -Use documented native Pi surfaces only: - -- `settings.skills` -- `settings.packages` -- local package `pi.skills` -- target-owned Pi configuration, session, package-cache, and runtime - environment paths declared in the public contract - -Do not claim a Pi plugin marketplace, native sub-agent format, native plan mode, -or built-in permission sandbox unless official Pi sources add one and the -contract is updated. - -## Validation - -Before committing public module changes, run: - -```bash -PYTHONDONTWRITEBYTECODE=1 /usr/bin/python3 -B cli-tools/validate_public_contracts.py -/usr/bin/python3 -B cli-tools/nddev_pi.py list --json -git diff --check -``` - -Do not run live software install, CI, push, or tag unless the user explicitly -approves that later phase. + +# GDS repository contract + +## Scope + +- Repository ID: `repo_01KYFBZ4DBDJE4Z769C81WBGBA`. +- Roles: `module`. +- Canonical repository facts: `.gds/repository.yaml`. +- Applied bundle: `.gds/bundle.lock.yaml` (`0.1.0-dev`). +- Compiled policy: `.gds/compiled-policy.json`. + +## Boundaries + +- This Git repository is one independent mutation boundary. +- Preserve unrelated branches, worktrees, submodules, and dirty changes. +- Resolve cross-repository work with `gds context --json` before acting. +- Generated files are projections; change their canonical inputs and regenerate. + +## Safety + +- External writes require explicit approval: `true`. +- Generated projection edits: `forbidden`. +- Private parent context persistence: `forbidden`. +- Visibility contract: `public`; data classification: `public`. + +## Development + +- Test: `python3 -m json.tool config/nddev-contract.json`. + +## Agent routing + +- Start here: run `gds-orient` (or `gds context --json`) to resolve scope before + any cross-repository work. It is the orientation entry point. +- Active skill profiles: `core, module`. Five profiles exist in total + (`core`, `estate-admin`, `module`, `device`, `portfolio`); only the listed ones + are active for this repository. The catalog is `skills/registry.yaml`, and each + skill lives under `skills/canonical//SKILL.md`. +- Use on-demand skills for procedures; do not duplicate them here. +- Treat docs and memories as derived evidence, not mutation authority. + +## Done + +- Required verification is complete or explicitly `NOT_PROVEN`. +- Git state and every affected repository boundary are classified. +- No private data, secret, or unapproved generated drift is introduced.