diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index da332f3..47589d6 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -12,7 +12,8 @@ }, "policy": { "installation": "AVAILABLE", - "authentication": "ON_INSTALL" + "authentication": "ON_INSTALL", + "products": ["CODEX"] }, "category": "Developer Tools" } diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 585d207..7fefaa2 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,11 +1,8 @@ { "$schema": "https://json.schemastore.org/claude-code-marketplace.json", "name": "codetruss", - "description": "Catch scope drift and AI slop before commit with local acceptance receipts", - "metadata": { - "description": "Catch scope drift and AI slop before commit with local acceptance receipts", - "version": "0.1.1" - }, + "description": "Verify the acceptance contract for coding-agent changes locally", + "version": "0.1.2", "owner": { "name": "CodeTruss", "email": "zack@codetruss.com" @@ -14,10 +11,9 @@ { "name": "codetruss", "source": "./plugins/codetruss-claude", - "description": "Bind agent changes to the task and produce a verifiable local receipt before commit", - "version": "0.1.1", + "description": "Enforce approved scope and checks with the separately installed free CodeTruss CLI", "category": "development", - "tags": ["scope-drift", "verification", "local-first", "coding-agents"] + "tags": ["acceptance-gate", "scope-drift", "verification", "local-first", "coding-agents"] } ] } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..94d4c6d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,38 @@ +name: Release + +on: + push: + tags: ['v*'] + +permissions: + attestations: write + contents: write + id-token: write + +jobs: + release: + name: Publish deterministic plugin archives + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + fetch-depth: 0 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24 + - run: npm test + - run: npm run release:verify + - name: Attest plugin archives + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: dist/*.zip + - name: Publish release + env: + GH_TOKEN: ${{ github.token }} + run: >- + gh release create "$GITHUB_REF_NAME" dist/* + --verify-tag + --generate-notes + --title "CodeTruss agent plugins $GITHUB_REF_NAME" diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index d76c6f0..84827dc 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -25,3 +25,5 @@ jobs: with: node-version: 24 - run: npm test + - run: npm run fixtures:verify + - run: npm run release:verify diff --git a/.gitignore b/.gitignore index 646ac51..bf56190 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store node_modules/ +dist/ diff --git a/README.md b/README.md index b36a72d..c21d376 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,10 @@ claude plugin marketplace add DeliriumPulse/codetruss-plugins claude plugin install codetruss@codetruss ``` -The same validated plugin is ready for Anthropic's reviewed marketplace. The -owned marketplace is live now; official listing remains pending review. +The owned marketplace is live now. The same validated plugin is prepared for +Anthropic's reviewed community marketplace but has not been submitted. The +automatically available official marketplace is separately curated at +Anthropic's discretion. ## Codex @@ -36,9 +38,9 @@ codex plugin marketplace add DeliriumPulse/codetruss-plugins codex plugin add codetruss@codetruss ``` -The validated skills-only bundle is ready for OpenAI's universal Plugin -Directory. The owned marketplace is live now; official listing remains pending -verified publisher submission and review. +The validated skills-only bundle is ready for OpenAI's Plugin Directory. The +owned marketplace is live now; public-directory submission has not occurred and +still requires a verified publisher with Apps Management write access. ## What the skill does @@ -60,10 +62,21 @@ self-contained. npm test claude plugin validate ./plugins/codetruss-claude python3 /path/to/plugin-creator/scripts/validate_plugin.py ./plugins/codetruss +npm run release:verify ``` `npm test` uses only Node.js built-ins and verifies manifests, marketplace entries, skill parity, privacy guardrails, and submission-case counts. +`npm run release:verify` builds the OpenAI and Claude submission archives twice +from the committed Git tree and proves their bytes are reproducible. + +## Security and support + +Read [SECURITY.md](SECURITY.md) before reporting a vulnerability. General +wrapper issues belong in this repository; CLI issues belong in the +[CodeTruss CLI tracker](https://github.com/DeliriumPulse/codetruss-cli/issues). +Never attach third-party source, credentials, or unredacted receipts to a public +issue. ## Licensing boundary diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..fbe3bc8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,18 @@ +# Security policy + +Please report suspected vulnerabilities privately to `zack@codetruss.com` with +the subject `CodeTruss security report`. Include the affected wrapper or CLI +version, reproduction steps, impact, and whether public disclosure is already +planned. Do not include third-party source code, credentials, or unredacted +receipts unless requested through a mutually agreed secure channel. + +We will acknowledge a report within two business days, provide a preliminary +triage within five business days when reproducible, and coordinate disclosure +after a fix or mitigation is available. Availability and timelines may change +for reports that cannot be reproduced or concern unsupported versions. + +The MIT wrapper repository contains skill instructions and manifests only. CLI +implementation reports belong in the public CLI issue tracker unless they are +security-sensitive. Deterministic CLI operation is local; optional provider +review sends the reviewed diff directly to the selected provider, and explicit +sync sends a privacy-minimized receipt to CodeTruss but never the patch. diff --git a/package.json b/package.json index 19ac4f3..bb37406 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,14 @@ { "name": "codetruss-agent-plugins", - "version": "0.1.1", + "version": "0.1.2", "private": true, "description": "Open Claude Code, Codex, and Agent Skills wrappers for the CodeTruss CLI", "license": "MIT", "scripts": { - "test": "node scripts/validate.mjs" + "test": "node scripts/validate.mjs", + "fixtures:verify": "node submission/fixtures/setup.mjs /tmp/codetruss-plugin-fixtures", + "release:build": "node scripts/build-release.mjs", + "release:verify": "node scripts/verify-release.mjs" }, "engines": { "node": ">=20.9" diff --git a/plugins/codetruss-claude/.claude-plugin/plugin.json b/plugins/codetruss-claude/.claude-plugin/plugin.json index 30c0e50..25ef789 100644 --- a/plugins/codetruss-claude/.claude-plugin/plugin.json +++ b/plugins/codetruss-claude/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "codetruss", - "version": "0.1.1", - "description": "Catch scope drift and AI slop before commit with local acceptance receipts.", + "version": "0.1.2", + "description": "Verify coding-agent changes locally with the separately installed free CodeTruss CLI.", "author": { "name": "CodeTruss", "email": "zack@codetruss.com", @@ -10,6 +10,6 @@ "homepage": "https://codetruss.com/cli", "repository": "https://github.com/DeliriumPulse/codetruss-plugins", "license": "MIT", - "keywords": ["coding-agents", "scope-drift", "local-first", "verification", "receipts"], + "keywords": ["acceptance-gate", "coding-agents", "scope-drift", "local-first", "verification", "receipts"], "skills": "./skills/" } diff --git a/plugins/codetruss-claude/LICENSE b/plugins/codetruss-claude/LICENSE new file mode 100644 index 0000000..d462a98 --- /dev/null +++ b/plugins/codetruss-claude/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 CodeTruss + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/codetruss-claude/README.md b/plugins/codetruss-claude/README.md new file mode 100644 index 0000000..b8f930e --- /dev/null +++ b/plugins/codetruss-claude/README.md @@ -0,0 +1,32 @@ +# CodeTruss for Claude Code + +This plugin teaches Claude Code to operate the separately installed free +CodeTruss CLI as a local acceptance gate for coding-agent changes. + +Prerequisites: + +- Git +- Node.js 20.9 or newer +- CodeTruss CLI v0.2.14 or newer from + +The plugin contains no analyzer, bundled hook, MCP server, background service, +or upload path. It delegates hook installation to the tested CLI after developer +confirmation. Deterministic checks stay local. Provider-backed review, +authentication, and receipt sync require separate explicit developer actions. + +Troubleshooting: + +- Run `codetruss --version`; install or upgrade from the CLI page when it is + missing or older than v0.2.14. +- Run `codetruss hooks status claude` and `codetruss hooks doctor claude` + before changing or reinstalling Claude settings. +- Exit 1 means `REVIEW_REQUIRED`, exit 2 means `FAILED`, and both still produce + a receipt. Exit 3 is a usage or environment failure. +- Report wrapper problems at + and CLI/security problems at . +- Follow for private vulnerability reporting + and the current product security boundary. + +The wrapper files in this package are MIT licensed. The separately installed +CLI is source-visible and free to use under the CodeTruss CLI Proprietary +License and CodeTruss Terms of Service. diff --git a/plugins/codetruss-claude/skills/codetruss/SKILL.md b/plugins/codetruss-claude/skills/codetruss/SKILL.md index 272c09e..4e7d8ae 100644 --- a/plugins/codetruss-claude/skills/codetruss/SKILL.md +++ b/plugins/codetruss-claude/skills/codetruss/SKILL.md @@ -1,6 +1,6 @@ --- name: codetruss -description: Catch scope drift and AI slop by setting up and operating CodeTruss local acceptance gates for AI-generated code. Use when a developer asks to bind an agent task to allowed or denied files, configure repository verification, install or diagnose Claude Code or Codex hooks, review a working-tree or staged diff before commit, interpret or verify a signed CodeTruss receipt, repair a failed verdict, or explicitly opt into provider-backed review or receipt sync. +description: Operate CodeTruss local acceptance gates for coding-agent changes. Use when a developer asks to bind an agent task to allowed or denied files, configure repository verification, install or diagnose Claude Code or Codex hooks, review a working-tree or staged diff before commit, interpret or verify a signed CodeTruss receipt, repair a failed verdict, or explicitly opt into provider-backed review or receipt sync. --- # CodeTruss diff --git a/plugins/codetruss-claude/skills/codetruss/agents/openai.yaml b/plugins/codetruss-claude/skills/codetruss/agents/openai.yaml index 784a465..288602d 100644 --- a/plugins/codetruss-claude/skills/codetruss/agents/openai.yaml +++ b/plugins/codetruss-claude/skills/codetruss/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "CodeTruss" - short_description: "Catch scope drift and AI slop before commit" + short_description: "Local acceptance gate for coding-agent changes" default_prompt: "Use $codetruss to review my current agent changes and explain the receipt." diff --git a/plugins/codetruss/.codex-plugin/plugin.json b/plugins/codetruss/.codex-plugin/plugin.json index 4a8e98e..e3391cb 100644 --- a/plugins/codetruss/.codex-plugin/plugin.json +++ b/plugins/codetruss/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "codetruss", - "version": "0.1.1", - "description": "Catch scope drift and AI slop before commit with local acceptance receipts.", + "version": "0.1.2", + "description": "Verify the acceptance contract for coding-agent changes locally.", "author": { "name": "CodeTruss", "email": "zack@codetruss.com", @@ -10,12 +10,12 @@ "homepage": "https://codetruss.com/cli", "repository": "https://github.com/DeliriumPulse/codetruss-plugins", "license": "MIT", - "keywords": ["coding-agents", "scope-drift", "local-first", "verification", "receipts"], + "keywords": ["acceptance-gate", "coding-agents", "scope-drift", "local-first", "verification", "receipts"], "skills": "./skills/", "interface": { "displayName": "CodeTruss", - "shortDescription": "Catch scope drift and AI slop before commit", - "longDescription": "Bind agent changes to the task, run deterministic local checks, and produce a verifiable receipt before commit.", + "shortDescription": "Local acceptance gate for coding-agent changes", + "longDescription": "Declare approved scope and repository checks, evaluate the captured Git state locally, and produce a verifiable receipt before commit. Requires the separately installed free CodeTruss CLI; no CodeTruss account or upload is required.", "developerName": "CodeTruss", "category": "Developer Tools", "capabilities": ["Interactive", "Read", "Write"], @@ -27,6 +27,9 @@ "Review my current changes against the task", "Verify and explain my latest CodeTruss receipt" ], - "brandColor": "#B93A26" + "brandColor": "#B93A26", + "composerIcon": "./assets/codetruss-mark-512.png", + "logo": "./assets/codetruss-mark-512.png", + "logoDark": "./assets/codetruss-mark-512.png" } } diff --git a/plugins/codetruss/LICENSE b/plugins/codetruss/LICENSE new file mode 100644 index 0000000..d462a98 --- /dev/null +++ b/plugins/codetruss/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 CodeTruss + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/codetruss/README.md b/plugins/codetruss/README.md new file mode 100644 index 0000000..3fa891f --- /dev/null +++ b/plugins/codetruss/README.md @@ -0,0 +1,32 @@ +# CodeTruss for Codex + +This skills-only plugin teaches Codex to operate the separately installed free +CodeTruss CLI as a local acceptance gate for coding-agent changes. + +Prerequisites: + +- Git +- Node.js 20.9 or newer +- CodeTruss CLI v0.2.14 or newer from + +The plugin contains no analyzer, MCP server, background service, or upload path. +Deterministic checks stay local. Provider-backed review, authentication, and +receipt sync require separate explicit developer actions. + +Troubleshooting: + +- Run `codetruss --version`; install or upgrade from the CLI page when it is + missing or older than v0.2.14. +- Run `codetruss hooks status codex` and `codetruss hooks doctor codex` before + changing hook configuration. Codex may require approval of the exact hook in + `/hooks`. +- Exit 1 means `REVIEW_REQUIRED`, exit 2 means `FAILED`, and both still produce + a receipt. Exit 3 is a usage or environment failure. +- Report wrapper problems at + and CLI/security problems at . +- Follow for private vulnerability reporting + and the current product security boundary. + +The wrapper files in this package are MIT licensed. The separately installed +CLI is source-visible and free to use under the CodeTruss CLI Proprietary +License and CodeTruss Terms of Service. diff --git a/plugins/codetruss/assets/codetruss-mark-512.png b/plugins/codetruss/assets/codetruss-mark-512.png new file mode 100644 index 0000000..d10bd0c Binary files /dev/null and b/plugins/codetruss/assets/codetruss-mark-512.png differ diff --git a/plugins/codetruss/skills/codetruss/SKILL.md b/plugins/codetruss/skills/codetruss/SKILL.md index 272c09e..4e7d8ae 100644 --- a/plugins/codetruss/skills/codetruss/SKILL.md +++ b/plugins/codetruss/skills/codetruss/SKILL.md @@ -1,6 +1,6 @@ --- name: codetruss -description: Catch scope drift and AI slop by setting up and operating CodeTruss local acceptance gates for AI-generated code. Use when a developer asks to bind an agent task to allowed or denied files, configure repository verification, install or diagnose Claude Code or Codex hooks, review a working-tree or staged diff before commit, interpret or verify a signed CodeTruss receipt, repair a failed verdict, or explicitly opt into provider-backed review or receipt sync. +description: Operate CodeTruss local acceptance gates for coding-agent changes. Use when a developer asks to bind an agent task to allowed or denied files, configure repository verification, install or diagnose Claude Code or Codex hooks, review a working-tree or staged diff before commit, interpret or verify a signed CodeTruss receipt, repair a failed verdict, or explicitly opt into provider-backed review or receipt sync. --- # CodeTruss diff --git a/plugins/codetruss/skills/codetruss/agents/openai.yaml b/plugins/codetruss/skills/codetruss/agents/openai.yaml index 784a465..288602d 100644 --- a/plugins/codetruss/skills/codetruss/agents/openai.yaml +++ b/plugins/codetruss/skills/codetruss/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "CodeTruss" - short_description: "Catch scope drift and AI slop before commit" + short_description: "Local acceptance gate for coding-agent changes" default_prompt: "Use $codetruss to review my current agent changes and explain the receipt." diff --git a/scripts/build-release.mjs b/scripts/build-release.mjs new file mode 100644 index 0000000..cdd21ea --- /dev/null +++ b/scripts/build-release.mjs @@ -0,0 +1,68 @@ +import { createHash } from 'node:crypto' +import { execFileSync } from 'node:child_process' +import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' + +const root = join(dirname(fileURLToPath(import.meta.url)), '..') +const packageManifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) +const version = packageManifest.version +const tag = `v${version}` +const ref = process.env.CODETRUSS_PLUGIN_RELEASE_REF || 'HEAD' +const dist = join(root, 'dist') +const commitDate = execFileSync('git', ['show', '-s', '--format=%cI', ref], { + cwd: root, + encoding: 'utf8', +}).trim() + +function readJsonAtRef(path) { + return JSON.parse(execFileSync('git', ['show', `${ref}:${path}`], { + cwd: root, + encoding: 'utf8', + })) +} + +const committedPackage = readJsonAtRef('package.json') +if (committedPackage.version !== version) { + throw new Error( + `Committed ${ref} is version ${committedPackage.version}, but the working tree is ${version}; commit the release inputs before packaging`, + ) +} + +for (const manifestPath of [ + 'plugins/codetruss/.codex-plugin/plugin.json', + 'plugins/codetruss-claude/.claude-plugin/plugin.json', +]) { + const manifest = readJsonAtRef(manifestPath) + if (manifest.version !== version) { + throw new Error(`${manifestPath} at ${ref} is ${manifest.version}, expected ${version}`) + } +} + +if (process.env.GITHUB_REF_TYPE === 'tag' && process.env.GITHUB_REF_NAME !== tag) { + throw new Error(`Release tag ${process.env.GITHUB_REF_NAME} does not match package ${tag}`) +} + +rmSync(dist, { recursive: true, force: true }) +mkdirSync(dist, { recursive: true }) + +const packages = [ + ['openai', 'plugins/codetruss'], + ['claude', 'plugins/codetruss-claude'], +] + +for (const [target, tree] of packages) { + const filename = `codetruss-${target}-plugin-v${version}.zip` + const output = join(dist, filename) + execFileSync('git', [ + 'archive', + '--format=zip', + `--mtime=${commitDate}`, + `--output=${output}`, + `${ref}:${tree}`, + ], { cwd: root, stdio: 'inherit' }) + const digest = createHash('sha256').update(readFileSync(output)).digest('hex') + writeFileSync(`${output}.sha256`, `${digest} ${filename}\n`) +} + +process.stdout.write(`Built reproducible CodeTruss plugin archives for ${tag} from ${ref}.\n`) diff --git a/scripts/validate.mjs b/scripts/validate.mjs index 33d7c6a..6429847 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -1,4 +1,5 @@ import assert from 'node:assert/strict' +import { createHash } from 'node:crypto' import { readFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -6,6 +7,7 @@ import { fileURLToPath } from 'node:url' const root = join(dirname(fileURLToPath(import.meta.url)), '..') const read = (path) => readFile(join(root, path), 'utf8') const json = async (path) => JSON.parse(await read(path)) +const packageManifest = await json('package.json') const canonicalSkill = await read('skills/codetruss/SKILL.md') const claudeSkill = await read('plugins/codetruss-claude/skills/codetruss/SKILL.md') @@ -41,6 +43,7 @@ const codexManifest = await json('plugins/codetruss/.codex-plugin/plugin.json') for (const manifest of [claudeManifest, codexManifest]) { assert.equal(manifest.name, 'codetruss') assert.match(manifest.version, /^\d+\.\d+\.\d+$/) + assert.equal(manifest.version, packageManifest.version) assert.equal(manifest.license, 'MIT') assert.equal(manifest.author.name, 'CodeTruss') assert.equal(manifest.author.email, 'zack@codetruss.com') @@ -51,20 +54,60 @@ assert.equal(codexManifest.interface.privacyPolicyURL, 'https://codetruss.com/pr assert.equal(codexManifest.interface.termsOfServiceURL, 'https://codetruss.com/terms') assert.ok(!('mcpServers' in codexManifest), 'local-first wrapper must not add an MCP server') assert.ok(!('hooks' in codexManifest), 'plugin must delegate hooks to the tested CLI installer') +assert.equal( + codexManifest.interface.shortDescription, + 'Local acceptance gate for coding-agent changes', +) +for (const assetField of ['composerIcon', 'logo', 'logoDark']) { + assert.equal(codexManifest.interface[assetField], './assets/codetruss-mark-512.png') +} +const brandMark = await readFile(join(root, 'plugins/codetruss/assets/codetruss-mark-512.png')) +assert.equal( + createHash('sha256').update(brandMark).digest('hex'), + '2c46b3aca474ec80918333b6331326ef6f1df6d4a09d48c4f4f9f128dc3d45b8', +) const claudeMarketplace = await json('.claude-plugin/marketplace.json') assert.equal(claudeMarketplace.name, 'codetruss') assert.equal(claudeMarketplace.plugins[0].source, './plugins/codetruss-claude') +assert.equal(claudeMarketplace.version, packageManifest.version) +assert.ok(!('version' in claudeMarketplace.plugins[0])) const codexMarketplace = await json('.agents/plugins/marketplace.json') assert.equal(codexMarketplace.name, 'codetruss') assert.equal(codexMarketplace.plugins[0].source.path, './plugins/codetruss') assert.deepEqual(codexMarketplace.plugins[0].policy, { installation: 'AVAILABLE', authentication: 'ON_INSTALL', + products: ['CODEX'], }) const submission = await read('submission/openai.md') assert.equal((submission.match(/^### Positive \d+:/gm) ?? []).length, 5) assert.equal((submission.match(/^### Negative \d+:/gm) ?? []).length, 3) +assert.match(submission, /Status: \*\*Prepared and locally validated; not submitted or approved\.\*\*/) +assert.match(submission, /Short description: Local acceptance gate for coding-agent changes\./) +assert.match(submission, /Requires the separately installed free CodeTruss CLI/) +assert.match(submission, /Availability:/) +assert.match(submission, /submission\/fixtures\/setup\.mjs/) + +const claudeSubmission = await read('submission/claude.md') +assert.match(claudeSubmission, /reviewed community marketplace/) +assert.match(claudeSubmission, /not submitted or approved/) +assert.match(claudeSubmission, /Submitter email: `zack@codetruss\.com`/) +assert.match(claudeSubmission, /Supported platform: `Claude Code`/) +assert.match(claudeSubmission, /Wrapper license: `MIT`/) +assert.match(claudeSubmission, /## Example use cases/) +assert.doesNotMatch(claudeSubmission, /It never uploads code/) +assert.match(claudeSubmission, /Optional\n> `--llm` sends the reviewed diff directly/) + +const publisherChecklist = await read('submission/PUBLISHER_CHECKLIST.md') +assert.match(publisherChecklist, /Apps Management: Write/) +assert.match(publisherChecklist, /gate the listing to Codex/) +assert.match(publisherChecklist, /Select `Claude Code` only/) +assert.match(publisherChecklist, /does not satisfy identity verification/) + +const readme = await read('README.md') +assert.doesNotMatch(readme, /official listing remains pending review/) +assert.match(readme, /official marketplace is separately curated/) process.stdout.write('CodeTruss Claude, Codex, and Agent Skills packages validated.\n') diff --git a/scripts/verify-release.mjs b/scripts/verify-release.mjs new file mode 100644 index 0000000..4b84a91 --- /dev/null +++ b/scripts/verify-release.mjs @@ -0,0 +1,32 @@ +import assert from 'node:assert/strict' +import { execFileSync } from 'node:child_process' +import { createHash } from 'node:crypto' +import { readdirSync, readFileSync } from 'node:fs' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { setTimeout } from 'node:timers/promises' + +const root = join(dirname(fileURLToPath(import.meta.url)), '..') +const dist = join(root, 'dist') + +function buildAndHash() { + execFileSync(process.execPath, [join(root, 'scripts/build-release.mjs')], { + cwd: root, + stdio: 'inherit', + }) + return Object.fromEntries( + readdirSync(dist).sort().map((name) => [ + name, + createHash('sha256').update(readFileSync(join(dist, name))).digest('hex'), + ]), + ) +} + +const first = buildAndHash() +await setTimeout(1_100) +const second = buildAndHash() +assert.deepEqual(second, first, 'release archives changed across identical builds') +assert.equal(Object.keys(first).filter((name) => name.endsWith('.zip')).length, 2) +assert.equal(Object.keys(first).filter((name) => name.endsWith('.sha256')).length, 2) + +process.stdout.write('CodeTruss plugin release archives are byte-for-byte reproducible.\n') diff --git a/skills/codetruss/SKILL.md b/skills/codetruss/SKILL.md index 272c09e..4e7d8ae 100644 --- a/skills/codetruss/SKILL.md +++ b/skills/codetruss/SKILL.md @@ -1,6 +1,6 @@ --- name: codetruss -description: Catch scope drift and AI slop by setting up and operating CodeTruss local acceptance gates for AI-generated code. Use when a developer asks to bind an agent task to allowed or denied files, configure repository verification, install or diagnose Claude Code or Codex hooks, review a working-tree or staged diff before commit, interpret or verify a signed CodeTruss receipt, repair a failed verdict, or explicitly opt into provider-backed review or receipt sync. +description: Operate CodeTruss local acceptance gates for coding-agent changes. Use when a developer asks to bind an agent task to allowed or denied files, configure repository verification, install or diagnose Claude Code or Codex hooks, review a working-tree or staged diff before commit, interpret or verify a signed CodeTruss receipt, repair a failed verdict, or explicitly opt into provider-backed review or receipt sync. --- # CodeTruss diff --git a/skills/codetruss/agents/openai.yaml b/skills/codetruss/agents/openai.yaml index 784a465..288602d 100644 --- a/skills/codetruss/agents/openai.yaml +++ b/skills/codetruss/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "CodeTruss" - short_description: "Catch scope drift and AI slop before commit" + short_description: "Local acceptance gate for coding-agent changes" default_prompt: "Use $codetruss to review my current agent changes and explain the receipt." diff --git a/submission/PUBLISHER_CHECKLIST.md b/submission/PUBLISHER_CHECKLIST.md new file mode 100644 index 0000000..1466764 --- /dev/null +++ b/submission/PUBLISHER_CHECKLIST.md @@ -0,0 +1,47 @@ +# Publisher submission checklist + +The packages are technically ready, but these account-level gates must be +completed by the verified publisher. Do not describe either listing as +submitted or approved until the vendor portal confirms that state. + +## OpenAI Plugin Directory + +1. In the publishing OpenAI Platform organization, complete business identity + verification under the exact public operator name `CodeTruss`. If only + individual verification is available, first align the plugin publisher, + website operator, support identity, privacy policy, and terms to that + verified identity. +2. Confirm the submitter role has `Apps Management: Write`. +3. Choose `Skills only` and gate the listing to Codex. The plugin requires a + local Git checkout and executable CLI; it is not a ChatGPT Work web workflow. +4. Upload `codetruss-openai-plugin-v0.1.2.zip` from the matching GitHub release, + the checksum-pinned 512×512 logo, the three starter prompts, exactly five + positive tests, and exactly three negative tests from `submission/openai.md`. +5. Select all portal-supported regions intended for launch, review the public + prerequisite/licensing text, and submit. Approval still requires an explicit + Publish action in the portal. + +An OpenAI API key or project membership does not satisfy identity verification +or Apps Management permission. + +## Anthropic community marketplace + +1. Use the Anthropic Console submission form with repository + `https://github.com/DeliriumPulse/codetruss-plugins` and plugin path + `plugins/codetruss-claude`. +2. Select `Claude Code` only. Cowork has not been tested and must not be claimed. +3. Copy the description and three examples from `submission/claude.md`, use + `zack@codetruss.com`, identify the wrapper license as MIT, review the terms, + and submit. +4. Record the reviewed commit SHA. Approved third-party submissions enter the + `claude-community` marketplace. The automatically available official + marketplace is separately curated at Anthropic's discretion. + +## Evidence to retain + +- vendor submission ID and timestamp; +- exact Git commit, release URL, archive SHA-256, and logo SHA-256; +- successful `gh attestation verify --repo DeliriumPulse/codetruss-plugins` output; +- screenshots of the final submitted fields; +- review status and every requested remediation; +- approval and publication timestamps as separate events. diff --git a/submission/claude.md b/submission/claude.md index 9b378c6..29fbfeb 100644 --- a/submission/claude.md +++ b/submission/claude.md @@ -1,8 +1,17 @@ # Claude community submission draft +Status: **Prepared and locally validated; not submitted or approved.** This is +for the reviewed community marketplace. Official-marketplace inclusion is a +separate Anthropic-curated decision. + - Plugin: `codetruss` - Repository: - Package path: `plugins/codetruss-claude` +- Submitter email: `zack@codetruss.com` +- Supported platform: `Claude Code` +- Wrapper license: `MIT` +- Terms acknowledgement: confirm in the Console form after reviewing the final + submission. - Homepage: - Logo: (512 × 512; SHA-256 `2c46b3aca474ec80918333b6331326ef6f1df6d4a09d48c4f4f9f128dc3d45b8`) @@ -12,12 +21,27 @@ Description: -> Catch scope drift and AI slop before commit. Keep Claude Code changes inside -> the approved task, run deterministic local analyzers and repository -> verification, and produce a verifiable receipt. The +> Verify the acceptance contract for Claude Code changes before commit. Keep +> changes inside the approved task, run deterministic local analyzers and +> repository verification, and produce a verifiable receipt. The > skill installs CodeTruss's existing project hook only after the developer -> confirms repository scope. It never uploads code; provider review and receipt -> sync remain explicit opt-ins. +> confirms repository scope. Deterministic review uploads nothing. Optional +> `--llm` sends the reviewed diff directly to the developer's chosen provider; +> explicit sync uploads only a redacted receipt and never the patch. Requires +> the separately installed free CodeTruss CLI; no CodeTruss account or upload +> is required for local use. The wrapper is MIT licensed; the CLI is +> source-visible under the CodeTruss CLI Proprietary License. + +## Example use cases + +1. Configure a narrow acceptance boundary for a repository by inspecting its + existing scripts, proposing allow/deny globs, and installing the Claude Code + hook only after developer confirmation. +2. Review the current working-tree or staged changes against the stated task, + then explain every scope, sensitive-surface, analyzer, and verification + reason in the resulting verdict. +3. Verify the latest receipt and explain the difference between post-generation + integrity evidence, trusted execution, authorship, and compliance. Pre-submission evidence: diff --git a/submission/fixtures/README.md b/submission/fixtures/README.md new file mode 100644 index 0000000..04bad01 --- /dev/null +++ b/submission/fixtures/README.md @@ -0,0 +1,40 @@ +# Reviewer fixtures + +These fixtures make the five positive OpenAI skill tests reproducible without +placing source code, credentials, or a CodeTruss account in the submission. + +Prerequisites: Git, Node.js 20.9 or newer, CodeTruss CLI v0.2.14 or newer, and +the CodeTruss plugin under review. + +Generate all repositories: + +```bash +node submission/fixtures/setup.mjs /tmp/codetruss-plugin-fixtures +``` + +The script recreates the destination and makes deterministic initial commits. + +## Positive-test mapping + +1. `configure-boundary`: start here for repository setup. It intentionally has + no `.codetruss.yml`. Ask the plugin to allow `src/**` and `tests/**`, deny + `infra/production/**` and `.env*`, use `npm run lint` plus `npm test`, and + install the Codex hook. +2. `review-working-tree`: contains an uncommitted `src/rate-limit.ts` change and + a valid policy. Ask the plugin to review it for the password-reset + rate-limiting task. +3. `review-staged`: contains staged `src/staged.ts` and unstaged + `src/unstaged.ts`. Ask for a staged-only pre-commit review and confirm the + receipt excludes the unstaged path. +4. `diagnose-claude-hook`: contains a stale Claude Stop-hook command. Ask the + plugin to diagnose it without deleting or reinstalling settings first. +5. `verify-receipt`: contains an uncommitted `src/receipt.ts` change. Create the + signed local receipt, then ask the plugin to verify and explain it: + + ```bash + cd /tmp/codetruss-plugin-fixtures/verify-receipt + codetruss review --task "Add the receipt fixture" --no-verify + ``` + +Exit 1 or 2 is a product verdict and still creates the receipt required by the +test. No fixture invokes `--llm`, authentication, or sync. diff --git a/submission/fixtures/setup.mjs b/submission/fixtures/setup.mjs new file mode 100644 index 0000000..a85a996 --- /dev/null +++ b/submission/fixtures/setup.mjs @@ -0,0 +1,85 @@ +import { execFileSync } from 'node:child_process' +import { mkdirSync, rmSync, writeFileSync } from 'node:fs' +import { dirname, join, resolve } from 'node:path' + +const destination = resolve(process.argv[2] || '/tmp/codetruss-plugin-fixtures') +const gitEnv = { + ...process.env, + GIT_AUTHOR_DATE: '2026-01-01T00:00:00Z', + GIT_COMMITTER_DATE: '2026-01-01T00:00:00Z', +} + +function run(cwd, command, args) { + execFileSync(command, args, { cwd, env: gitEnv, stdio: 'ignore' }) +} + +function write(root, path, contents) { + const target = join(root, path) + mkdirSync(dirname(target), { recursive: true }) + writeFileSync(target, contents) +} + +const policy = `version: 1 +allow: + - src/** + - tests/** +deny: + - infra/production/** + - .env* +verify: + - npm run lint + - npm test +receipts: + dir: .codetruss/receipts +` + +function createRepository(name, { withPolicy = true } = {}) { + const root = join(destination, name) + mkdirSync(root, { recursive: true }) + write(root, 'package.json', `${JSON.stringify({ + name: `codetruss-${name}-fixture`, + private: true, + scripts: { + lint: 'node -e "process.exit(0)"', + test: 'node -e "process.exit(0)"', + }, + }, null, 2)}\n`) + write(root, 'src/index.ts', 'export const fixture = true\n') + write(root, 'tests/index.test.ts', 'export const fixtureTest = true\n') + write(root, 'infra/production/main.tf', '# deliberately sensitive fixture surface\n') + write(root, '.env.example', 'EXAMPLE_ONLY=true\n') + if (withPolicy) write(root, '.codetruss.yml', policy) + run(root, 'git', ['init', '-q']) + run(root, 'git', ['config', 'user.name', 'CodeTruss Fixture']) + run(root, 'git', ['config', 'user.email', 'reviewer@example.invalid']) + run(root, 'git', ['add', '.']) + run(root, 'git', ['commit', '-q', '-m', 'Initial reviewer fixture']) + return root +} + +rmSync(destination, { recursive: true, force: true }) +mkdirSync(destination, { recursive: true }) + +createRepository('configure-boundary', { withPolicy: false }) + +const workingTree = createRepository('review-working-tree') +write(workingTree, 'src/rate-limit.ts', 'export const passwordResetLimit = 5\n') + +const staged = createRepository('review-staged') +write(staged, 'src/staged.ts', 'export const stagedChange = true\n') +run(staged, 'git', ['add', 'src/staged.ts']) +write(staged, 'src/unstaged.ts', 'export const unstagedChange = true\n') + +const hook = createRepository('diagnose-claude-hook') +write(hook, '.claude/settings.json', `${JSON.stringify({ + hooks: { + Stop: [{ + hooks: [{ type: 'command', command: 'codetruss hooks run claude --legacy' }], + }], + }, +}, null, 2)}\n`) + +const receipt = createRepository('verify-receipt') +write(receipt, 'src/receipt.ts', 'export const receiptFixture = true\n') + +process.stdout.write(`Created CodeTruss reviewer fixtures at ${destination}\n`) diff --git a/submission/openai.md b/submission/openai.md index b02977f..20cf4e2 100644 --- a/submission/openai.md +++ b/submission/openai.md @@ -2,26 +2,52 @@ Submission type: **Skills only** +Status: **Prepared and locally validated; not submitted or approved.** +Product scope: **Codex only.** The workflow requires a local Git checkout and +the separately installed CLI, so it must not be represented as a ChatGPT Work +web workflow. + ## Listing - Name: CodeTruss - Category: Developer Tools -- Short description: Catch scope drift and AI slop before commit. +- Short description: Local acceptance gate for coding-agent changes. - Logo: (512 × 512; SHA-256 `2c46b3aca474ec80918333b6331326ef6f1df6d4a09d48c4f4f9f128dc3d45b8`) - Website: - Support: - Privacy: - Terms: +- Availability: all regions offered by the submission portal, subject to + publisher eligibility. +- Prerequisite: Requires the separately installed free CodeTruss CLI. The + wrapper is MIT licensed; the CLI is source-visible under the CodeTruss CLI + Proprietary License. +- Publisher access: business/developer identity verification and Apps + Management write access must be completed in the publishing organization + before submission. +- Publisher alignment gate: metadata currently names `CodeTruss`. Submit only + from a verified business identity with that exact public operator name, or + first align the publisher metadata, website, support identity, privacy policy, + and terms to the verified individual identity. Long description: -> Bind agent changes to the task. Catch scope drift and AI slop with -> deterministic local checks, run your repository's own verification commands, -> and produce a verifiable receipt -> for AI-generated changes. CodeTruss works across coding agents. Deterministic -> analysis stays on your machine; provider review and receipt sync are explicit -> opt-ins. +> Declare the files a coding agent may change and the checks its work must pass. +> CodeTruss evaluates the captured Git state locally and returns a verifiable +> PASS, REVIEW_REQUIRED, or FAILED receipt before commit. It works across coding +> agents. Deterministic analysis stays on your machine; provider review and +> receipt sync are explicit opt-ins. Requires the separately installed free +> CodeTruss CLI; no CodeTruss account or upload is required for local use. + +Reviewer fixtures are generated with: + +```bash +node submission/fixtures/setup.mjs /tmp/codetruss-plugin-fixtures +``` + +The exact repository state and setup command for each positive test are in +`submission/fixtures/README.md`. ## Starter prompts @@ -41,7 +67,8 @@ Long description: verification config, install the Codex hook, and run the doctor. - Expected result: A configured repository and a reminder to approve the exact hook in `/hooks`; no LLM call, auth, or sync. -- Fixture: A clean Git repository with package scripts and CodeTruss installed. +- Fixture: `/tmp/codetruss-plugin-fixtures/configure-boundary`, generated by the + reviewer fixture command. CodeTruss CLI v0.2.14 or newer must be installed. ### Positive 2: review an existing working-tree change @@ -52,7 +79,7 @@ Long description: verify its integrity. - Expected result: Verdict first, explicit scope/sensitive/analyzer/verification reasons, receipt ID/path, and integrity status. -- Fixture: A Git repository with a changed file and valid `.codetruss.yml`. +- Fixture: `/tmp/codetruss-plugin-fixtures/review-working-tree`. ### Positive 3: review only staged changes @@ -60,7 +87,7 @@ Long description: - Expected behavior: Run `codetruss review --staged --task "Pre-commit review"`, preserve configured verification, inspect the receipt, and verify it. - Expected result: A staged-only verdict with reasons and receipt details. -- Fixture: A Git repository with different staged and unstaged changes. +- Fixture: `/tmp/codetruss-plugin-fixtures/review-staged`. ### Positive 4: diagnose an installed Claude hook @@ -71,7 +98,8 @@ Long description: a repair. - Expected result: Evidence-backed diagnosis that preserves existing settings and asks before any material rewrite. -- Fixture: A repository with a deliberately stale or malformed CodeTruss hook. +- Fixture: `/tmp/codetruss-plugin-fixtures/diagnose-claude-hook`, which contains + a deliberately stale Claude Stop-hook command. ### Positive 5: interpret and verify a receipt @@ -81,7 +109,8 @@ Long description: distinguish integrity evidence from trusted execution or authorship. - Expected result: Integrity status, verdict/reasons, limitations, and no compliance overclaim. -- Fixture: A repository containing a valid local receipt. +- Fixture: `/tmp/codetruss-plugin-fixtures/verify-receipt`; first run the exact + receipt-creation command in `submission/fixtures/README.md`. ## Negative tests @@ -116,7 +145,7 @@ Long description: ## Initial release notes -Initial skills-only CodeTruss integration for Codex and ChatGPT. It configures -and invokes the separately installed local CLI, preserves explicit network -consent, understands verdict exit codes, installs the existing Codex hook with -developer approval, and explains verifiable receipt limitations. +Initial skills-only CodeTruss integration for Codex. It configures and invokes +the separately installed local CLI, preserves explicit network consent, +understands verdict exit codes, installs the existing Codex hook with developer +approval, and explains verifiable receipt limitations.