From 94a4df6ed1fb2431db1923be29e1e474d5a54fe4 Mon Sep 17 00:00:00 2001 From: 0xLeif Date: Wed, 9 Sep 2026 20:37:35 -0600 Subject: [PATCH 1/2] Add: Trust 1.2.0 gate with SpecSync 6.0.0 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JNdwGkbfU1o5jk6LiPhcF2 --- .attest.json | 4 + .augur.toml | 3 + .github/workflows/trust.yml | 20 ++++ .specsync/config.toml | 8 ++ .specsync/hashes.json | 20 ++++ .trust.toml | 22 ++++ AGENTS.md | 12 ++ specs/corvid-skills/corvid-skills.spec.md | 133 ++++++++++++++++++++++ 8 files changed, 222 insertions(+) create mode 100644 .attest.json create mode 100644 .augur.toml create mode 100644 .github/workflows/trust.yml create mode 100644 .specsync/config.toml create mode 100644 .specsync/hashes.json create mode 100644 .trust.toml create mode 100644 AGENTS.md create mode 100644 specs/corvid-skills/corvid-skills.spec.md diff --git a/.attest.json b/.attest.json new file mode 100644 index 0000000..ba4a063 --- /dev/null +++ b/.attest.json @@ -0,0 +1,4 @@ +{ + "requireAttestation": true, + "requireTestsPassed": true +} diff --git a/.augur.toml b/.augur.toml new file mode 100644 index 0000000..031b459 --- /dev/null +++ b/.augur.toml @@ -0,0 +1,3 @@ +[thresholds] +review = 35 +block = 65 diff --git a/.github/workflows/trust.yml b/.github/workflows/trust.yml new file mode 100644 index 0000000..6cc854e --- /dev/null +++ b/.github/workflows/trust.yml @@ -0,0 +1,20 @@ +name: trust + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + trust: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + + - uses: CorvidLabs/trust@fcc889f54d8b4892a81af463c5a0250e2be66fc5 # v1.2.0 + id: trust diff --git a/.specsync/config.toml b/.specsync/config.toml new file mode 100644 index 0000000..c0f66ac --- /dev/null +++ b/.specsync/config.toml @@ -0,0 +1,8 @@ +specs_dir = "specs" +source_dirs = ["bin"] +exclude_dirs = [] +required_sections = ["Purpose", "Public API", "Invariants", "Behavioral Examples", "Error Cases", "Dependencies", "Change Log"] +enforcement = "strict" + +[lifecycle] +track_history = false diff --git a/.specsync/hashes.json b/.specsync/hashes.json new file mode 100644 index 0000000..becf888 --- /dev/null +++ b/.specsync/hashes.json @@ -0,0 +1,20 @@ +{ + "format_version": 1, + "hashes": { + ".specsync/config.toml": "a0b33ecbba81a0799d176051eccc8b3fbca744ddcceb0cf882bab0441e9d0119", + "bin/corvid-skills": "75ce5bff26e3390ca23e71dd60e4198f470f28791c674a3803e615009a04bac2", + "bin/fledge-skills": "dd28ea84fb9d235251b3718e77af90bf326f25c536410f1fd2f00ebe0c10cd9c", + "specs/corvid-skills/corvid-skills.spec.md": "167c25b889df5c4b604316b0c03d3722956deee7a20d560229498b3f11f024a6" + }, + "snapshots": { + "specs/corvid-skills/corvid-skills.spec.md": { + "snapshot_version": 1, + "spec_path": "specs/corvid-skills/corvid-skills.spec.md", + "errors": [], + "warnings": [], + "notices": [], + "input_digest": "94c43143dd19606eb923f606685e84850f05f12c6704784baf83bd89b5557f06", + "snapshot_digest": "f7ea2ea1e517db55285435b5de09fe2bbad19c40f4ef9c7184cce8c3693c0d60" + } + } +} \ No newline at end of file diff --git a/.trust.toml b/.trust.toml new file mode 100644 index 0000000..490fbb8 --- /dev/null +++ b/.trust.toml @@ -0,0 +1,22 @@ +schema_version = 1 +profile = "standard" + +[lifecycle] +command = ["fledge", "lanes", "run", "verify"] + +[contract] +enabled = true +require_coverage = 0 +skip_reason = "" + +[risk] +threshold = "block" + +[provenance] +mode = "soft" +policy = ".attest.json" +skip_reason = "" + +[atlas] +enabled = false +skip_reason = "Repo has no Atlas workflow; not adding one in this change" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..3da08a2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,12 @@ + +## CorvidLabs trust toolchain + +This repository uses one trust gate. Every session must use it and must not bypass or weaken it. + +- Run `fledge trust verify` before calling a change complete. +- Keep module specs synchronized with implementation changes. +- Treat an Augur block verdict as a hard stop that must be surfaced and de-risked. +- Record and verify provenance with Attest after the repository's verification lane passes. +- Keep generated trust configuration and this managed block in place. + + diff --git a/specs/corvid-skills/corvid-skills.spec.md b/specs/corvid-skills/corvid-skills.spec.md new file mode 100644 index 0000000..f2ac98b --- /dev/null +++ b/specs/corvid-skills/corvid-skills.spec.md @@ -0,0 +1,133 @@ +--- +module: corvid-skills +version: 1 +status: active +files: + - bin/corvid-skills + - bin/fledge-skills +db_tables: [] +depends_on: [] +--- + +# corvid-skills + +## Purpose + +`bin/corvid-skills` is the installer that copies or links the shared skill directories under +`skills/` into an agent host directory, either repository-local or machine-global, and records +every managed install in a `.corvid-skills.json` manifest next to that target root. It owns the +catalog listing, install, status, update, and uninstall behavior for this repository. + +`bin/fledge-skills` is the Fledge plugin entry point declared by `plugin.toml`. It resolves the +plugin source directory from `FLEDGE_PLUGIN_DIR` (falling back to the parent of its own +directory) and `exec`s `bin/corvid-skills` with the caller's arguments unchanged. + +## Public API + +SpecSync cannot parse extensionless shell executables, so this surface is documented as prose +rather than as an export table. + +- `corvid-skills list [--json]` prints the catalog skill names from `skills/`, sorted with + `LC_ALL=C`. `--json` emits `{"skills": [...]}`. +- `corvid-skills install [--repo |--global] [--host ] [--link] [--dry-run]` + copies (default) or symlinks (`--link`) the skill into the host directory and appends a + manifest entry recording destination, install mode, source revision, and `v2:` content digest. +- `corvid-skills status [--repo |--global] [--json]` reports each manifest entry as + `skill`, `host`, `destination`, `source_revision`, `install_mode`, `state`, where state is + `current`, `legacy`, `modified`, or `missing`. +- `corvid-skills update |--all [--repo |--global] [--host ] [--dry-run]` + refreshes unmodified managed copies and manifest-owned links to the current catalog revision + and digest. +- `corvid-skills uninstall [--repo |--global] [--host ] [--dry-run]` removes + a managed install and its manifest entry. +- `corvid-skills help`, `-h`, `--help`, or no arguments prints usage. +- `fledge-skills ` is the Fledge plugin shim; it `exec`s `bin/corvid-skills` with the + same arguments. + +Host directories are fixed: `codex` to `.codex/skills`, `claude` to `.claude/skills`, `cursor` to +`.cursor/skills`, `gemini` to `.gemini/skills`, `grok` to `.grok/skills`, and `openai` to +`.agents/skills`. + +## Invariants + +- Install never overwrites an existing destination; it fails if the destination path exists. +- Install, update, and uninstall refuse any path component that is a symlink, and refuse a + symlinked `.corvid-skills.json`. +- A skill name must match `^[a-z0-9][a-z0-9-]*$` and must resolve to a real directory under + `skills/` that contains `SKILL.md` and only regular files and directories. +- The manifest is written atomically through a temporary file in the manifest directory followed + by `os.replace`, and is always `schema_version = 1` with an `installs` list. +- A skill and host pair appears at most once in a manifest; a duplicate install is rejected. +- Update and uninstall act only on entries whose state is `current` (uninstall also accepts + `legacy`), or, for `link` mode, on a symlink that still points at this checkout's source + directory. +- `--global` and `--repo` are mutually exclusive; `--global` resolves to `CORVID_SKILLS_HOME` + or `HOME`. +- Copy install and copy update stage into a temporary sibling path and roll back the filesystem + change if the manifest write fails. +- `--dry-run` prints the intended action and makes no filesystem or manifest change. +- `--host auto` resolves only when exactly one host directory or host agent root is present. + +## Behavioral Examples + +- `corvid-skills list --json` on this checkout prints the sorted `skills/*/SKILL.md` directory + names, which `tests/installer.sh` asserts is a 16 entry sorted list. +- `corvid-skills install agent-coordination --repo --host claude` creates + `/.claude/skills/agent-coordination`, writes `/.corvid-skills.json` with + `install_mode: "copy"`, and prints `Installed agent-coordination for claude at ...`. +- `corvid-skills status --repo --json` after that install reports one entry with + `"state": "current"`. +- `corvid-skills update --all --repo --host claude --dry-run` prints one + `Would update ...` line per matching entry and changes nothing. +- `corvid-skills uninstall agent-coordination --repo --host claude` removes the + destination directory and drops the manifest entry. +- Editing a file inside an installed copy moves its status to `modified`, and update then + refuses that entry. + +## Error Cases + +All failures exit with status 2 through `fail()` and write `corvid-skills: ` to stderr, +except rollback paths that exit 1 after restoring the previous filesystem state. + +| Condition | Message | +|-----------|---------| +| Unknown subcommand | `unknown command: ` | +| Unknown flag | `unknown option: ` | +| `--repo` or `--host` without a value | `--repo needs a path` / `--host needs a value` | +| Skill name fails the name pattern | `invalid skill name: ` | +| Skill directory or `SKILL.md` missing | `unknown skill: ` | +| Skill directory holds a device, socket, or symlink entry | `skill contains unsupported filesystem entries: ` | +| Unsupported `--host` value | `unsupported host: ` | +| `--host auto` with zero or several host directories | `cannot infer an agent host; pass --host ...` / `multiple agent hosts are present (...); pass --host explicitly` | +| Target path is not a directory or not a Git repository | `not a directory: ` / `not a Git repository: ` | +| `--global` combined with `--repo` | `--global cannot be combined with --repo` | +| `--global` with no usable home | `HOME is unset; cannot use --global` / `skills home is not a directory: ` | +| Install destination already exists | `destination already exists: ` | +| Any symlinked path component or manifest | `refusing symlinked install path: ...`, `refusing symlinked managed path: ...`, `refusing symlinked managed copy: ...`, `refusing symlinked manifest: ...` | +| Manifest missing for update, uninstall | `managed-skills manifest not found: ` | +| Manifest is not schema 1 or has malformed entries | `unsupported managed-skills manifest: ` / `invalid managed-skills manifest entry` / `invalid control character in managed-skills manifest` / `invalid managed-skills manifest: ` | +| Manifest destination does not match the host layout | `refusing unsafe manifest destination: ` | +| Update or uninstall matches nothing | `no matching managed skills are installed` / `no matching managed skill is installed: ` | +| Managed copy drifted from its recorded digest | `refusing to update on : state is ` | +| Managed link no longer points at this checkout | `refusing to update ...` / `refusing to uninstall on : managed link was changed or removed` | +| Legacy `.openai/skills` placement on update | `OpenAI skill uses legacy .openai placement; uninstall then reinstall it for OpenAI` | +| Staging path collision | `temporary update path already exists for on ` / `temporary removal path already exists for on ` | +| `python3` unavailable for a manifest operation | `python3 is required to maintain .corvid-skills.json safely` | + +## Dependencies + +- `bash` 4 or newer, run with `set -euo pipefail`. +- `python3` for every manifest read, write, and JSON output path. +- `git` for `rev-parse --show-toplevel` (repository resolution) and `rev-parse --verify HEAD` + (recorded source revision; falls back to the literal `working-tree`). +- Coreutils and findutils: `find`, `sort`, `awk`, `cp`, `mv`, `rm`, `ln`, `mkdir`, `dirname`, + `basename`, `readlink`, `uname`. +- `shasum -a 256` when present, otherwise `sha256sum`, for content digests. +- `stat -f '%Lp'` on Darwin, `stat -c '%a'` elsewhere, for entry modes. +- Environment: `FLEDGE_PLUGIN_DIR`, `CORVID_SKILLS_HOME`, `HOME`. + +## Change Log + +| Change | Date | Version | +|--------|------|---------| +| Created | 2026-09-10 | 1 | From 5b8ee3fc73b9aa3bcc5c5a5fa7efbfb0075bf217 Mon Sep 17 00:00:00 2001 From: 0xLeif Date: Wed, 9 Sep 2026 22:08:04 -0600 Subject: [PATCH 2/2] Remove: drop the local SpecSync hash cache from the pin diff .specsync/hashes.json is a local cache written by running specsync; it is not tracked on main and does not belong in this change. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JNdwGkbfU1o5jk6LiPhcF2 --- .specsync/hashes.json | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .specsync/hashes.json diff --git a/.specsync/hashes.json b/.specsync/hashes.json deleted file mode 100644 index becf888..0000000 --- a/.specsync/hashes.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "format_version": 1, - "hashes": { - ".specsync/config.toml": "a0b33ecbba81a0799d176051eccc8b3fbca744ddcceb0cf882bab0441e9d0119", - "bin/corvid-skills": "75ce5bff26e3390ca23e71dd60e4198f470f28791c674a3803e615009a04bac2", - "bin/fledge-skills": "dd28ea84fb9d235251b3718e77af90bf326f25c536410f1fd2f00ebe0c10cd9c", - "specs/corvid-skills/corvid-skills.spec.md": "167c25b889df5c4b604316b0c03d3722956deee7a20d560229498b3f11f024a6" - }, - "snapshots": { - "specs/corvid-skills/corvid-skills.spec.md": { - "snapshot_version": 1, - "spec_path": "specs/corvid-skills/corvid-skills.spec.md", - "errors": [], - "warnings": [], - "notices": [], - "input_digest": "94c43143dd19606eb923f606685e84850f05f12c6704784baf83bd89b5557f06", - "snapshot_digest": "f7ea2ea1e517db55285435b5de09fe2bbad19c40f4ef9c7184cce8c3693c0d60" - } - } -} \ No newline at end of file